no message

This commit is contained in:
YoVinchen 2023-08-31 11:30:31 +08:00
commit 1b3c5235fe
251 changed files with 112922 additions and 0 deletions

11
.obsidian/app.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"promptDelete": false,
"alwaysUpdateLinks": true,
"showUnsupportedFiles": true,
"readableLineLength": false,
"strictLineBreaks": true,
"showLineNumber": true,
"rightToLeft": false,
"showFrontmatter": true,
"attachmentFolderPath": "照片"
}

5
.obsidian/appearance.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"accentColor": "#d9d9d9",
"theme": "system",
"translucency": false
}

3
.obsidian/community-plugins.json vendored Normal file
View File

@ -0,0 +1,3 @@
[
"obsidian-image-auto-upload-plugin"
]

29
.obsidian/core-plugins-migration.json vendored Normal file
View File

@ -0,0 +1,29 @@
{
"file-explorer": true,
"global-search": true,
"switcher": true,
"graph": true,
"backlink": true,
"canvas": true,
"outgoing-link": true,
"tag-pane": true,
"page-preview": true,
"daily-notes": true,
"templates": true,
"note-composer": true,
"command-palette": true,
"slash-command": false,
"editor-status": true,
"bookmarks": true,
"markdown-importer": false,
"zk-prefixer": false,
"random-note": false,
"outline": true,
"word-count": true,
"slides": false,
"audio-recorder": false,
"workspaces": false,
"file-recovery": true,
"publish": false,
"sync": false
}

20
.obsidian/core-plugins.json vendored Normal file
View File

@ -0,0 +1,20 @@
[
"file-explorer",
"global-search",
"switcher",
"graph",
"backlink",
"canvas",
"outgoing-link",
"tag-pane",
"page-preview",
"daily-notes",
"templates",
"note-composer",
"command-palette",
"editor-status",
"bookmarks",
"outline",
"word-count",
"file-recovery"
]

22
.obsidian/graph.json vendored Normal file
View File

@ -0,0 +1,22 @@
{
"collapse-filter": true,
"search": "",
"showTags": false,
"showAttachments": false,
"hideUnresolved": false,
"showOrphans": true,
"collapse-color-groups": true,
"colorGroups": [],
"collapse-display": true,
"showArrow": false,
"textFadeMultiplier": 0,
"nodeSizeMultiplier": 1,
"lineSizeMultiplier": 1,
"collapse-forces": false,
"centerStrength": 0.518713248970312,
"repelStrength": 10,
"linkStrength": 1,
"linkDistance": 250,
"scale": 0.0078125,
"close": true
}

1
.obsidian/hotkeys.json vendored Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,14 @@
{
"uploadByClipSwitch": true,
"uploader": "PicGo",
"uploadServer": "http://127.0.0.1:36677/upload",
"deleteServer": "http://127.0.0.1:36677/delete",
"imageSizeSuffix": "",
"picgoCorePath": "",
"workOnNetWork": false,
"fixPath": false,
"applyImage": false,
"newWorkBlackDomains": "",
"deleteSource": false,
"imageDesc": "origin"
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
{
"id": "obsidian-image-auto-upload-plugin",
"name": "Image auto upload Plugin",
"version": "3.6.0",
"minAppVersion": "0.10.7",
"description": "This plugin uploads images from your clipboard by PicGo",
"author": "renmu",
"authorUrl": "https://github.com/renmu123/obsidian-image-auto-upload-plugin",
"isDesktopOnly": true
}

189
.obsidian/workspace.json vendored Normal file
View File

@ -0,0 +1,189 @@
{
"main": {
"id": "6515734ec8ec4856",
"type": "split",
"children": [
{
"id": "9aac8742ad1c417c",
"type": "tabs",
"children": [
{
"id": "1627d09ae486f69c",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "软件测试/软件测试-软测基础.md",
"mode": "source",
"source": false
}
}
}
]
}
],
"direction": "vertical"
},
"left": {
"id": "7d9cdd2c78820643",
"type": "split",
"children": [
{
"id": "7bdf743935451396",
"type": "tabs",
"children": [
{
"id": "7bdfd42654fb2c49",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {
"sortOrder": "alphabetical"
}
}
},
{
"id": "04722c6153992570",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "复制",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical"
}
}
},
{
"id": "aba0fce28dc49642",
"type": "leaf",
"state": {
"type": "bookmarks",
"state": {}
}
}
]
}
],
"direction": "horizontal",
"width": 352.5
},
"right": {
"id": "c478b4c7ee8a6580",
"type": "split",
"children": [
{
"id": "7405d7cdf96c29e7",
"type": "tabs",
"children": [
{
"id": "d8965d91c701cdd6",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"file": "软件测试/软件测试-软测基础.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": false
}
}
},
{
"id": "32a0a6791f655e9d",
"type": "leaf",
"state": {
"type": "outgoing-link",
"state": {
"file": "软件测试/软件测试-软测基础.md",
"linksCollapsed": false,
"unlinkedCollapsed": true
}
}
},
{
"id": "4f8c1d97ee46fc94",
"type": "leaf",
"state": {
"type": "tag",
"state": {
"sortOrder": "frequency",
"useHierarchy": true
}
}
},
{
"id": "05c2a27f0f9ada08",
"type": "leaf",
"state": {
"type": "outline",
"state": {
"file": "软件测试/软件测试-软测基础.md"
}
}
}
]
}
],
"direction": "horizontal",
"width": 300,
"collapsed": true
},
"left-ribbon": {
"hiddenItems": {
"switcher:打开快速切换": false,
"graph:查看关系图谱": false,
"canvas:新建白板": false,
"daily-notes:打开/创建今天的日记": false,
"templates:插入模板": false,
"command-palette:打开命令面板": false
}
},
"active": "1627d09ae486f69c",
"lastOpenFiles": [
"软件测试/软件测试-移动app特性.md",
"软件测试/软件测试-软测基础.md",
"软件测试/软件测试-黑白盒测试.md",
"软件测试/软件测试-安全测试.md",
"HomeBrew/Mac OS 神器 HomeBrew.md",
"开发工具/安装教程/Portainer.md",
"开发工具/Docker基本命令.md",
"开发工具/安装教程/RabbitMQ.md",
"开发工具/安装教程/Nginx.md",
"开发工具/安装教程/Mysql.md",
"Linux/LINUX常用命令总结.md",
"开发工具/安装教程/MongoDB.md",
"开发工具/安装教程/Redis.md",
"开发工具/Git基本命令.md",
"开发工具/安装教程/Tomcat.md",
"开发工具/Redis基本命令.md",
"开发工具/Node基本命令.md",
"开发工具/安装教程",
"HomeBrew/Git.md",
"青空笔记/Docker笔记/Docker容器技术.md",
"青空笔记/数据结构笔记/数据结构与算法(四).md",
"教程/mac命令.md",
"青空笔记/SpringCloud笔记/SpringCloud笔记.md",
"开发工具/Untitled.md",
"开发工具",
"青空笔记/SpringCloud笔记/SpringCloud笔记.md",
"青空笔记/SpringCloud笔记/SpringCould笔记.md",
"青空笔记/SpringCloud笔记/SpringCloud笔记.md",
"未命名.canvas",
"照片/Pasted image 20230803101741.png",
"照片",
"Pasted image 20230803101614.png",
"Pasted image 20230803101543.png",
"数据库系统原理/单元复习资料/数据库第二章.png",
"面试",
"教程/网站面板",
"教程"
]
}

474
Activti 流程管理.md Normal file
View File

@ -0,0 +1,474 @@
# Activti流程管理
```java
Activti提供的主要的接口服务其中主要用到
存储库服务repositoryService用于管理和操作流程定义和流程部署相关的数据。它提供了一系列方法来查询、创建、更新和删除流程定义、流程部署以及相关的资源文件。
运行时服务runtimeService用于管理和操作正在执行的流程实例和任务。它允许启动新的流程实例、对流程实例进行操作如激活、挂起、删除等、获取当前正在运行的流程实例信息等操作。
任务服务taskService用于管理和操作与用户任务相关的数据和操作。它允许查询、创建、更新和删除任务以及对任务进行分配、完成、指派等操作。
历史服务historyService用于访问和查询与历史数据相关的信息。它提供了查询已完成流程实例、任务、变量等历史数据的能力。通过历史服务可以获取对流程的审计跟踪和回顾以及生成历史报告和统计数据。
//存储库服务
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
//运行时服务
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
//表单服务
<bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
//身份服务
<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
//任务服务
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
//历史服务
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
//管理服务
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
```
## 1、存储库服务 repositoryService
### 1.全部流程实例激活挂起
激活:
```java
activateProcessDefinitionById(,,)
```
根据流程定义的ID激活流程定义。
第一个参数 是要激活的流程定义的唯一标识符。
第二个参数 `true` 表示级联激活,即同时激活与该流程定义关联的所有挂起的流程实例。
第三个参数 `null` 表示没有要激活的特定日期。
挂起:
```java
suspendProcessDefinitionById(,,)
```
根据流程定义的ID挂起流程定义。
第一个参数 是要挂起的流程定义的唯一标识符。
第二个参数 `true` 表示级联挂起,即同时挂起与该流程定义关联的所有正在执行的流程实例。
第三个参数 `null` 表示没有要挂起的特定日期。
示例:
```java
/**
* 全部流程实例挂起
*/
@Test
public void suspendProcessInstance() {
ProcessDefinition leave = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave").singleResult();
// 获取到当前流程定义是否为暂停状态 suspended方法为true是暂停的suspended方法为false是运行的
boolean suspended = leave.isSuspended();
if (suspended) {
// 暂定,那就可以激活
// 参数1:流程定义的id 参数2:是否激活 参数3:时间点
//多个流程激活
repositoryService.activateProcessDefinitionById(leave.getId(), true, null);
System.out.println("流程定义:" + leave.getId() + "激活");
} else {
//多个流程挂起
repositoryService.suspendProcessDefinitionById(leave.getId(), true, null);
System.out.println("流程定义:" + leave.getId() + "挂起");
}
}
```
### 2.删除流程实例
单个删除
```java
deleteDeployment()
```
根据流程部署的ID删除相应的流程定义和资源。如果该流程定义已经有流程实例启动则会删除失败。
第一个参数 是流程ID
级联删除
```java
deleteDeployment(,true)
```
设置为级联删除方式,即使流程定义已经有流程实例启动,也会强制删除流程定义及其相关的流程实例和历史数据。
第一个参数 是流程ID
第二个参数 true 表示开启级联删除
示例:
```java
/**
* 删除流程定义
*/
public void deleteDeployment() {
//部署id
String deploymentId = "ce1f3cc0-08cf-11ee-b8cb-e645a9a03302";
//删除流程定义,如果该流程定义已有流程实例启动则删除时出错
repositoryService.deleteDeployment(deploymentId);
//设置true 级联删除流程定义即使该流程有流程实例启动也可以删除设置为false非级别删除方式
repositoryService.deleteDeployment(deploymentId, true);
}
```
### 3.查询流程实例
```java
createProcessDefinitionQuery()
```
创建一个流程定义查询对象,用于构建查询条件。
```java
orderByProcessDefinitionVersion()
```
按照流程定义的版本进行排序。
```java
desc()
```
降序排列,即最新的版本排在前面。
```java
list()
```
执行查询,并返回符合条件的流程定义结果列表。
示例:
```java
/**
* 查询流程定义
*/
@Test
public void findProcessDefinitionList() {
List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery()
.orderByProcessDefinitionVersion()
.desc()
.list();
//输出流程定义信息
for (ProcessDefinition processDefinition : definitionList) {
System.out.println("流程定义 id= " + processDefinition.getId());
System.out.println("流程定义 name= " + processDefinition.getName());
System.out.println("流程定义 key= " + processDefinition.getKey());
System.out.println("流程定义 Version= " + processDefinition.getVersion());
System.out.println("流程部署ID = " + processDefinition.getDeploymentId());
}
}
```
### 4.单个文件部署
```java
createDeployment()
```
创建一个流程部署对象,用于部署流程定义和相关资源。
```java
addClasspathResource("")
```
从类路径中添加一个 BPMN 文件资源到部署中,路径为 ""。该文件包含了请假申请流程的流程定义。
参数 是bpmn文件路径
```java
addClasspathResource("")
```
从类路径中添加一个 PNG 文件资源到部署中,路径为 ""。该文件用于流程定义的可视化展示。
参数 是png文件路径
```java
name("")
```
设置流程部署的名称为 ""。
参数 流程部署名称
```java
deploy()
```
执行部署操作,将流程定义和资源文件部署到流程引擎中。
示例:
```java
/**
* 单个文件部署
*/
@Test
public void deployProcess() {
// 流程部署
Deployment deploy = repositoryService.createDeployment().addClasspathResource("process/leave.bpmn20.xml").addClasspathResource("process/leave.png").name("请假申请流程").deploy();
System.out.println(deploy.getId());
System.out.println(deploy.getName());
}
```
## 2、运行时服务 runtimeService
### 1.启动流程实例
```java
startProcessInstanceByKey("")
```
按照流程定义的名称key启动一个流程实例。流程定义的键通常是在部署流程时设置的唯一标识符。
参数 是流程的名称
示例:
```java
/**
* 启动流程实例
*/
@Test
public void startUpProcess() {
//创建流程实例,我们需要知道流程定义的key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave");
//输出实例的相关信息
System.out.println("流程定义id" + processInstance.getProcessDefinitionId());
System.out.println("流程实例id" + processInstance.getId());
System.out.println("当前活动Id" + processInstance.getActivityId());
}
```
### 2.单个流程实例激活挂起
激活实例流程:
```java
activateProcessInstanceById()
```
挂起实例流程:
```java
suspendProcessInstanceById()
```
示例:
```java
/**
* 单个流程挂起
*/
@Test
public void SingleSuspendProcessInstance() {
String processInstanceId = "ce1f3cc0-08cf-11ee-b8cb-e645a9a03302";
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//获取到当前流程定义是否为暂停状态 suspended方法为true代表为暂停 false就是运行的
boolean suspended = processInstance.isSuspended();
if (suspended) {
//单个流程激活
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "激活");
} else {
//单个流程挂起
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "挂起");
}
}
```
### 3.启动实例流程
```
startProcessInstanceByKey("", )
```
启动一个流程实例
第一个参数 是启动的流程定义的键(流程名称)
第二个参数 可选参数,表示与流程实例相关联的业务关键字
示例:
```java
/**
* 启动流程实例添加businessKey
*/
@Test
public void startUpProcessAddBusinessKey() {
String businessKey = "1";
// 启动流程实例指定业务标识businessKey也就是请假申请单id
ProcessInstance processInstance = runtimeService.
startProcessInstanceByKey("leave", businessKey);
// 输出
System.out.println("业务id:" + processInstance.getBusinessKey());
}
```
### 4.查询流程定义
```java
runtimeService.createProcessInstanceQuery()
```
创建流程实例查询对象
```java
processInstanceId()
```
设置流程实例ID为查询条件
参数 是流程实例ID
```java
singleResult()
```
执行查询并返回单个结果,即符合条件的唯一流程实例
```java
/**
* 单个流程挂起
*/
@Test
public void SingleSuspendProcessInstance() {
String processInstanceId = "ce1f3cc0-08cf-11ee-b8cb-e645a9a03302";
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//获取到当前流程定义是否为暂停状态 suspended方法为true代表为暂停 false就是运行的
boolean suspended = processInstance.isSuspended();
if (suspended) {
//单个流程激活
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "激活");
} else {
//单个流程挂起
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程实例:" + processInstanceId + "挂起");
}
}
```
## 3、任务服务 taskService
### 1.完成任务
```java
complete()
```
用于完成当前用户任务的方法
参数 任务ID
示例:
```java
/**
* 完成任务
*/
@Test
public void completTask() {
//要查询的负责人
Task task = taskService.createTaskQuery().taskAssignee("zhangsan").singleResult();//返回一条
//完成任务,参数任务id
taskService.complete(task.getId());
}
```
### 2.查询当前个人待执行任务
```java
createTaskQuery
```
创建任务查询对象
taskAssignee(assignee)
设置任务负责人的查询条件
参数 是查询的任务负责人的名称
```
list()
```
执行查询操作并返回查询结果
示例:
```java
/**
* 查询当前个人待执行的任务 zhangsan
*/
@Test
public void findPendingTaskList() {
//任务负责人
String assignee = "zhangsan";
List<Task> list = taskService.createTaskQuery()
.taskAssignee(assignee)//只查询该任务负责人的任务
.list();
for (Task task : list) {
System.out.println("流程实例id" + task.getProcessInstanceId());
System.out.println("任务id" + task.getId());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务名称:" + task.getName());
}
}
```
## 4、历史服务 historyService
### 1.查询已处理任务
```java
createHistoricTaskInstanceQuery()
```
创建一个历史任务实例查询对象,用于执行历史任务的查询操作
```java
taskAssignee("")
```
设置查询条件,只返回指定负责人的历史任务
参数 是指定负责人的名称
```java
finished()
```
只返回已完成的历史任务
```java
list()
```
执行查询操作并返回查询结果
示例:
```java
/**
* 查询已处理历史任务
*/
@Test
public void findProcessedTaskList() {
//张三已处理过的历史任务
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().taskAssignee("zhangsan").finished().list();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("流程实例id" + historicTaskInstance.getProcessInstanceId());
System.out.println("任务id" + historicTaskInstance.getId());
System.out.println("任务负责人:" + historicTaskInstance.getAssignee());
System.out.println("任务名称:" + historicTaskInstance.getName());
}
}
```

65
HomeBrew/Git.md Normal file
View File

@ -0,0 +1,65 @@
# HomeBrew 安装 Git
Git 是一个开源的分布式版本控制系统用于敏捷高效地处理任何或小或大的项目。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
此处使用 homebrew 安装先确保安装Homebrew后再进行后续操作
先在终端输入下面命令查看是否安装HomeBrew
```
brew -v
```
未安装可以看这篇文章安装 [Mac OS 神器 HomeBrew](https://blog.hhdxw.top/archives/242)
### 查看搜索可安装
```shell
brew install git
```
### 安装Git
```shell
brew install git
```
### 查看Git版本
```shell
git --version
```
### 配置 SSH key
### 输入如下命令产生新的key
```shell
ssh-keygen -t rsa -C "your_email@example.com"
```
### 将SSH key添加到Github
登录到Github页面 -> 右上角Setttings -> SSH keys ->Add key
查看生成的key内容
```shell
cat ~/.ssh/id_rsa.pub
```
将以上内容复制到 Github ==> Setting ==>Key 中完成添加新的key。
## 配置Git用户信息
```shell
git config --global user.name "你的名字或昵称"
git config --global user.email "你的邮箱"
```
### 卸载命令
```text
brew uninstall git
```

View File

@ -0,0 +1,194 @@
# Mac OS 开发神器 HomeBrew
Homebrew 是一款适用于 macOS 系统的自由及开放源代码软件包管理系统旨在使软件安装更加简单。Homebrew 提供了一个方便的命令行界面,允许用户通过简单的命令来安装、更新和卸载许多常用的开源软件包,如 Git、Python、Node.js 等等。Homebrew 可以帮助你轻松地维护你的软件环境,并且可以让你在使用 macOS 的同时也能够享受到 Linux 的软件包管理方式。使用 Homebrew你可以避免手动编译和安装软件包节省你的时间和精力。
首先是HomeBrew的官网 https://brew.sh/index_zh-cn
那么我们就先来安装homebrew
## Homebrew 安装命令
在 Mac 上安装 Homebrew
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
在 Linux 上安装 Homebrew
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
在 Windows 上安装 Homebrew
```shell
N/A(homebrew 暂时不支持windows)
```
上面的都是国外的镜像源没有科技的小伙伴们的速度都会比较慢,下面是一些国内镜像源的安装地址
中科大镜像源:
```shell
/bin/bash -c "$(curl -fsSL https://mirrors.ustc.edu.cn/brew-install/install.sh)"
```
清华镜像源:
```shell
/bin/bash -c "$(curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/homebrew/install/master/install.sh)"
```
阿里云镜像源:
```shell
/bin/bash -c "$(curl -fsSL https://mirrors.aliyun.com/homebrew/install/install.sh)"
```
## Homebrew 常用命令
其中`<package_name>`为需要安装的包名例如node
### 1、搜索软件包
这个命令用于查找 Homebrew 中包含特定关键字的软件包。可以在 `<keyword>` 参数中输入任何与要查找的软件包相关的词汇或名称Homebrew 会返回所有包含该词的软件包列表
```shell
brew search <keyword>
```
### 2、安装软件包
这个命令可以安装指定的软件包
```shell
brew install <package_name>
```
### 3、卸载软件包
这个命令可以卸载指定的软件包
```shell
brew uninstall <package_name>
```
### 4、更新 Homebrew
这个命令可以更新 Homebrew 自身,包括 Homebrew 的程序代码、依赖项和其他组件
```shell
brew update
```
### 5、查看哪些软件需要更新
这个命令用于显示已安装软件包中哪些需要更新
```shell
brew outdated
```
### 6、升级已安装的软件包
这个命令用于升级所有已安装的软件包。
```shell
brew upgrade
```
### 7、查看已安装的软件包
这个命令可以列出已安装的所有软件包。
```shell
brew list
```
### 8、更新指定的包
使用这个命令可以只升级指定的软件包。
```
brew upgrade <package_name>
```
### 9、清理所有包的旧版本
这个命令可以清理所有软件包的旧版本
```
brew cleanup
```
### 10、显示软件包信息
这个命令可以显示有关指定软件包的详细信息,包括版本、依赖项和安装路径等
```shell
brew info <package_name>
```
### 11、切换指定包版本
这个命令用于切换已经安装的软件包到指定版本
这个命令查看是否存在想要切换的版本
```shell
brew search <package_name>
```
这个命令切断当前版本的链接
```shell
brew unlink <package_name>@<version>
```
这个命令连接新版本的链接
```shell
brew link <package_name>@<version>
```
### 12、显示已安装软件包的依赖关系
这个命令可以查看已安装软件包的依赖关系
```shell
brew deps <package_name>
```
### 13、显示软件包安装目录
这个命令可以查看软件包的安装目录
```shell
brew --prefix <package_name>
```
### 14、显示软件包的版本号
这个命令可以查看软件包的版本号、依赖关系和安装路径等信息
```shell
brew info <package_name>
```
### 15、更改国内镜像源
由于某些网络限制或其他原因Homebrew 在国内可能会受到网络访问不畅的影响。可以通过更改国内镜像源来解决这个问题。例如,要将 Homebrew 镜像源更改为中科大镜像源,可以使用以下命令:
```shell
/bin/bash -c "$(curl -fsSL https://cdn.jsdelivr.net/gh/ineo6/homebrew-install/install/install.sh)"
```
### 16、查看 Homebrew 版本号
这个命令查看当前安装的 Homebrew 版本号。
```shell
brew --version
```

82
HomeBrew/Node.md Normal file
View File

@ -0,0 +1,82 @@
# HomeBrew 安装 Node.js
简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎V8 引擎执行 Javascript 的速度非常快,性能非常好。
此处使用 homebrew 安装先确保安装Homebrew后再进行后续操作
先在终端输入下面命令查看是否安装HomeBrew
```
brew -v
```
未安装可以看这篇文章安装 [Mac OS 神器 HomeBrew](https://blog.hhdxw.top/archives/242)
### 搜索可安装的Node
```shell
brew search node
```
### 安装Node
安装默认版本
```shell
brew install node
```
安装指定版本
```shell l
brew install node@18
```
### 卸载Node
```shell
brew unistall node
```
### 查看Node版本
```shell
node -v
```
### 切换Node版本
切断16版本链接
```shell
brew unlink node@16
```
链接18版本
```shell
brew link --overwrite --force node@18
```
其中 Homebrew 包管理器中,`--overwrite` 和 `--force` 是两个选项,它们的作用如下:
1. `--overwrite` 选项
当 Homebrew 安装一个包时如果这个包已经存在于系统中Homebrew 默认会跳过这个包的安装。但是,如果您希望强制安装一个已经存在的包,可以使用 `--overwrite` 选项。
使用 `--overwrite` 选项可能会覆盖您系统中已经存在的一些文件,因此需要小心使用。请确保在使用这个选项前,已经备份了您的系统数据。
1. `--force` 选项
`--force` 选项是针对在 Homebrew 中进行软件包安装或卸载时出现错误的情况。有时当您尝试安装或卸载一个软件包时Homebrew 会输出一些警告或错误,阻止您完成操作。如果您确定这个操作是安全的,可以使用 `--force` 选项强制执行这个操作。
`--overwrite` 选项一样,`--force` 选项可能会导致系统中的文件被覆盖或者删除,因此也需要小心使用。它可能会破坏系统的稳定性,因此必须谨慎使用。
总之,`--overwrite` 和 `--force` 选项都是使 Homebrew 绕过某些限制和警告的选项,并且需要小心使用。在进行任何系统操作之前,请务必了解它们的意义和作用,并且备份您的系统数据。
### 卸载命令
```text
brew uninstall node
```

View File

@ -0,0 +1,54 @@
# smartctl 硬盘读写查看
`smartctl` 是一款基于命令行的磁盘自我监测分析报告技术Self-Monitoring, Analysis and Reporting Technology简称 SMART工具用于对硬盘进行读写测试、状态检查以及管理。它能够获取硬盘的各种指标信息如温度、错误率、剩余寿命等并通过判断这些指标信息来评估硬盘的健康状态。
此处使用 homebrew 安装先确保安装Homebrew后再进行后续操作
先在终端输入下面命令查看是否安装HomeBrew
```
brew -v
```
未安装可以看这篇文章安装 [Mac OS 神器 HomeBrew](https://blog.hhdxw.top/archives/242)
在 macOS 系统中,可以通过 Homebrew 软件包管理器安装 `smartctl` 命令,步骤如下:
### 更新 Homebrew 软件包管理器
```shell
brew update
```
### 搜索可安装
```
brew search smartmontools
```
### 安装 smartmontools
```shell
brew install smartmontools
```
### 显示硬盘的 SMART 信息
```shell
smartctl -a /dev/disk0
```
其中,`-a` 选项用于显示所有可用的 SMART 信息,`/dev/disk0` 表示要检测的硬盘设备文件。
![c87f114b790cfba15db88f5e1d1d9e96](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/c87f114b790cfba15db88f5e1d1d9e96.png)
结果如下里面的Percentage Used 就是损耗值Data Units Written 就是写入量。
其中这么大的写入读取量全部是由于 mac os 相对激进的 swap 策略
### 卸载命令
```text
brew uninstall smartmontools
```

View File

@ -0,0 +1,283 @@
# 2021版
## Spring的基本应用
### 一、idea创建maven项目的过程
#### 1.设置idea打开时欢迎页面
1.在idea的欢迎页面中点击 Customize 进入自定义设置
2.点击 settings 进入系统设置
![image-20220301163353065](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301163353065.png)
3.在 settings 中搜索System Settings 并点击
4.将 Project 中的 Reopen projects on satrtup 对勾取消
5.将下面的 NEW windows 勾选上
![image-20220301163856266](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301163856266.png)
即可完成设置欢迎页面。
#### 2.idea中创建Maven项目的过程
1.打开欢迎页面中的设置(同上面设置)
2.再设置中搜索 Maven 并进入
3.按照图中箭头顺序2更换 apache-maven -3.6.3路径最好将下载的maven文件解压到除C盘以外的根目录文件可以在群里下载也可点击此下载
4.根据箭头3重写 User settings filer 和 Local repository 的路径官网下载的maven无repository文件夹需要自己新建并重命名更改成和照片相同位置即可点击OK完成设置。
![image-20220301164904720](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301164904720.png)
5.修改文件maven—conf—setting.xml用记事本打开文件setting.xml在其中搜索mirrors节点找到如图代码区域其中蓝色部分是已经添加的代码添加阿里云下载镜像注意要添加在<mirrors></mirrors>两个标签之间,其它配置同理)代码如下:
```java
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
```
![image-20220302110623820](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220302110623820.png)
6.搜索 localRepository 将其中路径改为自己仓库位置蓝色部分官网下载的maven无repository文件夹需要自己新建并重命名保存完成修改。
![image-20220301170612258](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301170612258.png)
7.创建maven项目的过程按照顺序依次选择点击最后next结束
![image-20220301171039307](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301171039307.png)
8.其中1是项目名称c012.是项目存储路径3.Groupld是项目名com.gzh(自己名字缩写)4.是版本号不用修改
![image-20220302110722790](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220302110722790.png)
9.这里应该是之前设置的默认项(如果不是如图所示应该重复上面的步骤进行maven配置)点击finish完成创建。
![image-20220301171713956](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301171713956.png)
10.进入后会自动安装maven的文件出现如图所示即安装成功
![image-20220301172210713](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301172210713.png)
### 二、Spring的体系结构
#### 1、核心模块(CoreContainer)
Spring核心模块包含有Core、Beans、Context和Expression Language四个小模块。其中Core和Beans是整个Spring框架基础部分也是Spring的核心依赖注入loC与DI的最基本实现Spring的其他模块大多依赖这两个功能。
spring-core其他模块的基础核心包含Spring框架的核心工具类Spring其他模块都要使用该包里面的类。
spring-beans:Spring定义bean的支持负责访问配置文件、创建和管理bean支持依赖注入和控制反转的相关操作。传说中的bean工厂类就在这个jar包中。
spring-context:spring运行时容器在Core和Beans的基础上提供对Spring的上下文支持ApplicationContext是该包的关键通过它可以方便快捷的取出依赖注入的Bean。
spring-expression:spring表达式语言帮助Spring在运行时查询和操作对象。支持设置获取对象的属性值方法的调用
#### 2、AOP模块
spring-aop对于代理AOP的支持
spring-Aspects对于AspectJ的AOP支持
#### 3、Web模块
spring-web提供基础的web功能在Web项目中提供Spring的容器
spring-webmvc提供基于Servlet的SpringMVC
Spring-WebSocket提供WebSocket功能
spring-webmvc-portlet:提供portlet的支持
#### 4数据库模块
spring-jdbc:提供jdbc访问数据库的支持包含Srping对数据库访问操作进行封装的所有类它提供了一个DBC的抽象层从而实现对其他厂商的支持。
spring-tx提供对事物的支持
spring-orm:提供对象关系-映射的支持使得Spring可以方便的整合 他第三方ORM库如JAP、Mybatis、Hibernate等
spring-oxm提供对象xml映射支持
spring-jms提供对java消息服务的支持
### 三、Spring的入门程序
#### 1.基于Java完成接口、实现类、方法的调用。
test
```java
项目分层:
控制层——调用服务层用户操作控制层发送url请求到控制层
服务层——调用Dao层
Dao层——和数据库打交道
```
1.在 src->main 下创建两个新文件夹并重命名为 Java 和 resources
![image-20220301180826354](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301180826354.png)
2.右击名为 Java 的文件选择 Mark Directory as 属性中的 Sources Root (源根)
![image-20220301223812386](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301223812386.png)
3.右击名为 resources 的文件选择 Mark Directory as 属性中的 Resources Root (源根)
![image-20220301223743212](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301223743212.png)
4.在 Java 源包下创建名为 UserDao 接口、名为 UserDaoImpl 的 Java 以及Test测试类
代码分别如下
```java
// UserDao 接口
public interface UserDao {
public void say ();
}
```
```java
// UserDaoImpl 实现类
public class UserDaoImpl implements UserDao{
@Override
public void say() {
System.out.println("UserDao say...");
}
}
```
```java
//Test 测试类
public class test {
public static void main(String[] args) {
//调用say方法
UserDao userDao = new UserDaoImpl();
userDao.say();
}
}
```
#### 2.使用Spring框架完成接口对象的创建及方法的调用。
1.导包,在idea中的目录中的pom.xml下找到如照片代码并添加蓝色区域代码<dependency></dependency>标签同一级,都应该在<dependencies></dependencies>标签中)
![image-20220301225430222](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301225430222.png)
代码如下:
```java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
完成导包后如图:
![image-20220301230136985](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301230136985.png)
可能有部分同学导包的时候保存代码之后未下载可以试一试重启idea应该可以解决下载问题
2.导包完成后在resources文件夹下建立 applicationContext.xml
![image-20220301230431966](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220301230431966.png)
3.并利用Spring框架创建com.wqx.UserDaoImpl类对象userDao代码如下
```java
<bean id="userDao" class="com.gzh.UserDaoImpl"/>
```
![image-20220302102447695](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220302102447695.png)
#### 3.使用Spring框架创建的对象调用方法
1.在 Test 测试类下输入代码:
```java
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.say();
```
点击运行完成并输出UserDao say...
![image-20220302104836410](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220302104836410.png)

View File

@ -0,0 +1,145 @@
# 第一章Spring的基本应用
## 四、依赖注入
依赖注入Dependency Injection建成DI与控制反转IoC的含义相同
依赖注入的作用就是在使用Spring 框架创建对象时动态地将其所依赖的对象注入Bean组件中其实现方式通常有两种一种是属性setter方法注入另一种是构造方法注入具体介绍如下:
属性 setter方法注入指Spring容器使用setter方法注入被依赖的实例。通过调用无参构造器或无参静态工厂方法实例化 Bean后调用该Bean的setter 方法,即可实现基于 setter方法的依赖注入。
构造方法注入指Spring容器使用构造方法注入被依赖的实例。基于构造方法的依赖注入通过调用带参数的构造方法来实现每个参数代表着一个依赖。
在com.gzh的包下创建UserService接口并创建一个say方法代码如下
```java
public interface UserService {
public void say();
}
```
在com.gzh的包下创建UserServiceImpl实现类代码如下
```java
public class UserServiceImpl implements UserService{
//声明UserDao的属性
private UserDao userDao;
//添加UserDao属性的setter方法用于实现依赖注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//实现接口中的方法
public void say(){
//调用userDao中的say()方法,并执行输出语句
this.userDao.say();
System.out.println("UserService say Hellow World!");
}
}
```
在applicationContext.xml里面创建一个id为userService的实例
```java
<bean id="userService" class="com.gzh.UserServiceImpl">
<!-- 将id为userDao的Bean实例注入到userService的实例中-->
<property name="userDao" ref="userDao"/>
</bean>
```
在com.gzh下创建TestDI实例
```java
public class TsetDI {
public static void main(String[] args) {
//1.初始化Spring容器加载配置文件
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("applicationContext.xml");
//2.通过容器获取UserService实例
UserService userService =(UserService) applicationContext.getBean("userService");
//3.调用实例中的say()方法
userService.say();
}
}
```
![image-20220303222001817](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220303222001817.png)
## 1.IOC控制反转类对象的创建由程序员转给了Spring框架
Spring框架创建类对象的步骤
1导包5个
commons_logging
spring-context
spring-beans
spring-core
spring-expression
```java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
2resources文件夹下创建applicationContext.xml
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.gzh.UserDaoImpl"/>
```
3获取Spring框架创建的类对象
```java
//使用Spring框架创建对象调用方法
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.say();
```
## 2.DI依赖注入
D依赖动词
```java
class B{}
class A{
B b;
void a(){
b.b();
}
}
//类的对象作为A类的成员变量就是A依赖B。
```
I注入就是给成员变量赋值
Spring 框架如何实现依赖注入?
直接在配置文件中写如下代码:
```java
<bean id="userService" class="com.gzh.UserServiceImpl">
<!-- 将id为userDao的Bean实例注入到userService的实例中-->
<property name="userDao" ref="userDao"/>
</bean>
//name属性值是成员变量ref属性值是id属性的值
```
#

View File

@ -0,0 +1,144 @@
# 第二章Spring中的Bean
## 1、Bean的配置
如果把Spring看做一个大型工厂则Spring容器中的Bean就是该工厂的产品。要想使用这个工厂生产和管理Bean就需要在配置文件中告诉它需要哪些Bean以及需要使用何种方式将这些Bean装配到一起。
**testBean的本质就是Java中的类而Spring中的Bean其实就是对实体类的引用来生产Java类对象从而实现生产和管理Bean .**
XML配置文件的根元素是<beans><beans>中包含了多个<bean>子元素,每个<bean>子元素定义了一个Bean并描述了该Bean如何被装配到Spring容器中
关于<beans>元素的常用属性如下表所示:
| 属性或元素名称 | 描述 |
| :------------: | :----------------------------------------------------------: |
| id | 是一个Bean的唯一标识符,Spring容器对Bean的配置、管理都通过该属性来完成。 |
| name | Spring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理name 属性中可以为 Bean指定多个名称每个名称之间用逗号或分号隔开。 |
| class | 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名。 |
| scopes | 用来设定 Bean 实例的作用域其属性值有singleton单例、prototype原型、request、session、global Session、application和 websocket。其默认值为 singleton。 |
#### 作用域的种类
| 作用域名称 | 说明 |
| :---------------: | :----------------------------------------------------------: |
| singleton单例 | 使用singleton定义的Bean在Spring容器中将只有一个穿例也就是说无论有多少个Bean 引用它始终将指向同一个对象。这也是Spring 容器默认的作用域。 |
| prototype原型 | 每次通过Spring容器获取的prototype定义的Bean时容器都将创建一个新的 Bean 实例。 |
**test如果在Bean中未指定id和name则Spring会将class值当作id使用。**
## 2、构造器实例化
首先创建一个Maven项目然后导包
```java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
然后在 main 文件下面创建Java源码包并在包下创建名为 com.ssm.instance.constructor 包 并在其下创建 Bean1 类
然后在 main 文件创建名为 resources 的 Resources Root (源根)并配置 Bean1 的 id 和 class
```java
<bean id="bean1" class="com.ssm.instance.constructor.Bean1"/>
```
然后在 com.ssm.instance.constructor 包下创建 InstanceTest1 类
```java
public static void main(String[] args) {
//定义配置文件路径
String xmlPath = "beans1.xml";
//ApplicationContext在加载配置文件时对Bean进行实例化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
Bean1 bean = (Bean1) applicationContext.getBean("bean1");
System.out.println(bean);
}
```
程序执行截图:
![image-20220309123304518](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220309123304518.png)
## 3、静态工厂实例化
首先在 Java 包下创建一个名为 com.ssm.instance.static_factory 包,然后在其包下创建一个 名为 Bean2 的类以及一个叫做 MyBean2Factory 的类 并在这个类中创建一个静态方法来实现返回 Bean2 实例
```java
//使用自己的工厂创建Bean实例
public static Bean2 createBean(){
return new Bean2();
}
```
然后在 resources 下创建 beans2.xml 并输入以下代码:
```java
<bean id ="bean2"
class="com.ssm.instance.static_factory.MyBean2Factory"
factory-method="createBean"/>
```
然后在 static_factory 下创建一个名为 InstanceTest2 的测试类,
```java
public static void main(String[] args) {
String xmlPath = "beans2.xml";
ApplicationContext applicationContext =new ClassPathXmlApplicationContext(xmlPath);
System.out.println(applicationContext.getBean("bean2"));
}
```
程序执行截图:
![image-20220309142136727](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220309142136727.png)
## 4、实例工厂实例化
首先在 Java 文件下面创建一个名为 com.ssm.instance.factory 的包,并在其下面创建一个名为 Bean3 的类和一个名为 MyBean3Factory 的类,创建 Bean3 的实例方法,输入以下代码:
```java
public MyBean3Factory (){
System.out.println("Bean3 工厂实例化中");
}
//创建 Bean3 实例的方法
public Bean3 createBean(){
return new Bean3();
}
```
在 resources 下创建 beans3.xml 并输入以下代码:
```java
<!-- 配置工厂 -->
<bean id="myBean3Factory"
class="com.ssm.instance.factory.MyBean3Factory"/>
<!-- 使用 factory-bean 属性指向配置的实例工厂,
使用 factory-method 的属性确定使用工厂中的哪个方法 -->
<bean id="bean3"
factory-bean="myBean3Factory"
factory-method="createBean" />
```
然后在 factory 下创建一个名为 InstanceTest3 的测试类,并输入以下代码:
```java
public static void main(String[] args) {
//指定配置文件路径
String xmlPath = "beans3.xml";
//ApplicationContext在加载配置文件时对Bean进行实例化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
System.out.println(applicationContext.getBean("bean3"));
}
```
程序执行截图:
![image-20220309144326438](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220309144326438.png)

View File

@ -0,0 +1,388 @@
# 第二章Spring中的Bean
## 9.基于XML的装配
### 什么是Bean的装配
Bean的装配可以理解为依赖关系注入Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式如基于XML的装配、基于注解Annotation的装配和自动装配其中最常用的是基于注解的装配本节将主要讲解这三种装配方式的使用。
1.在 java 包下创建名为 com.ssm.assemble 的包并在包下创建名为 User 的类输入利用生成构造函数、setter方法和toString方法
代码如下:
```java
private String username;
private Integer password;
private List<String> list;
// 1.使用构造注入
// 1.1提供所有参数的有参构造方法。
public User(String username, Integer password, List<String> list) {
this.username = username;
this.password = password;
this.list = list;
}
// 2.使用设值注入
// 2.2提供默认空参构造方法
// 2.3为所有属性提供setter方法
public User() {
super();
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(Integer password) {
this.password = password;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password=" + password +
", list=" + list +
'}';
}
```
2.在 resources 文件下创建名为 beans5.xml 的文件并通过两种方法装配User实例
代码如下:
```java
<!-- 1——1.使用构造方法注入方式装配User实例-->
<bean id="user1" class="com.ssm.assemble.User">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="123456"/>
<constructor-arg index="2">
<list>
<value>"constructorvalue1</value>
<value>"constructorvalue2</value>
</list>
</constructor-arg>
</bean>
<!-- 1——2.使用设值注入方式装配User实例-->
<bean id="user2" class="com.ssm.assemble.User">
<property name="username" value="张三"></property>
<property name="password" value="654321"></property>
<!-- 注入list集合-->
<property name="list">
<list>
<value>"setlistvalue1"</value>
<value>"setlistvalue2"</value>
</list>
</property>
</bean>
```
3.在 com.ssm.assemble 包下创建 XmlBeanAssembleTest 测试类,并运行程序
代码如下:
```java
// 定义配置文件路径
String xmlPath = "beans5.xml";
// 加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 构造方法输出结果
System.out.println(applicationContext.getBean("user1"));
// 构造方法输出结果
System.out.println(applicationContext.getBean("user2"));
```
运行结果如图:
![image-20220310180658138](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220310180658138.png)
### 总结基于XML的装配使用方式
:one:创建 Java 类,提供有参无参构造方法以及属性 setter 方法
:two:创建 Spring 的 xml 配置文件使用两种方式配置Bean
:three:创建测试类,测试程序
## 10.基于Annotation的装配
通过在类上方和成员变量上方添加注解
SSM项目分三层
Dao层接口和实现类——和数据库打交道
```java
//UserDaoImpl 类注解
@Repository("userDao")
```
服务层接口和实现类——调用Dao层
```java
//UserServiceImpl 类注解
@Service("userService")
//UserServiceImpl 成员变量注解
@Resource(name = "userDao")
```
控制层:类——调用服务层
```java
//UserController 类注解
@Resource(name = "userDao")
//UserController 成员变量注解
@Controller("userController")
```
### 1.首先实现三层结构:
创建 com.ssm.annotation 包并在其包下进行以下操作
##### Dao层
创建 UserDao 接口,代码如下:
```java
package com.ssm.annotation;
public interface UserDao {
public void save();
}
```
创建 UserDaoImpl 实现类,代码如下:
```java
package com.ssm.annotation;
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("userDao...save...");
}
}
```
##### 服务层
创建 UserService 接口,代码如下:
```java
package com.ssm.annotation;
public interface UserService {
public void save();
}
```
创建 UserServiceImpl 实现类,代码如下:
```java
package com.ssm.annotation;
public class UserServiceImpl implements UserService{
private UserDao userDao;
@Override
public void save(){
userDao.save();
System.out.println("Userservice...save...");
}
}
```
可以称为服务层调Dao层
##### 控制层
创建一个 UserController 控制器,代码如下:
```java
package com.ssm.annotation;
public class UserController {
private UserService userService;
public void save() {
userService.save();
System.out.println("userController...save...");
}
}
```
### 2.装配
对Dao层的实现类上方添加注解
```java
//相当于在xml文件中写<bean id="userDao" class="com.ssm.annotaion.UserDaoImpl"/>
@Repository("userDao")
//Repository 仓库 Dao层需要数据库打交道
```
对服务层的实现类以及成员变量上方添加注解
```java
//相当于在xml文件中写<bean id="UserService" class="com.ssm.annotaion.UserServiceImpl"/>
@Service("userService")
@Resource(name = "userDao")
```
对服务层的实现类和成员变量上方添加注解
```java
@Controller("userController")
@Resource(name = "userService")
```
创建 beans6.xml 文件利用xml文件扫描这些包来实现装配
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.ssm.annotation"/>
</beans>
```
创建 Test 测试类
```java
package com.ssm.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans6.xml");
UserController userController = (UserController) applicationContext.getBean("userController");
userController.save();
}
}
```
装配成功运行结果如截图如下:
![image-20220311125821133](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220311125821133.png)
### 3.自动装配
将一个 Bean 自动的注入到其他 Bean 的 property 中Spring 的<Bean>元素中包含一个 autwire 属性,我们可以通过设置 autowire 的属性值来自动装配 Bean 。
| 属性值 | 说明 |
| :---------------: | :----------------------------------------------------------: |
| default默认值 | 由<bean>的上级标签<beans>的 default-autowire 属性值确定。例如<beans>default-autowire="byName">,则该<bean>元素中的 autowire 属性对应的属性值就为byName。 |
| byNamee | 根据属性的名称自动装配。容器将根据名称查找与属性完全一致的Bean并将其属性自动装配。 |
| byTypee | 根据属性的数据类型Type自动装配如果一个Bean的数据类型兼容另一个Bean中属性的数据类型则自动装配。 |
| constructor | 根据构造函数参数的数据类型进行byType模式的自动装配。 |
| no | 默认情况下不使用自动装配Bean 依赖必须通过 ref元素定义。 |
自动装配一定要有 setter 方法
分别创建类A、B
```java
package com.ssm.autoware;
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
void a(){
b.b();
System.out.println("a");
}
}
```
```java
package com.ssm.autoware;
public class B {
void b(){
System.out.println("b");
}
}
```
填写 xml 装配文件
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="b" class="com.ssm.autoware.B"/>
<bean id="a" class="com.ssm.autoware.A" autowire="byName"/>
</beans>
```
最后通过 Test 文件测试
```java
package com.ssm.autoware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("beans7.xml");
A a = (A) applicationContext.getBean("a");
a.a();
}
}
```
### 2.5作用域
| 作用域名称 | 说明 |
| :---------------: | :----------------------------------------------------------: |
| singleton单例 | 使用singleton定义的Bean在Spring容器中将只有一个实例也就是说无论有多少个Bean引用它始终将指同一个对象。这也是Spring容器默认的作用域。 |
| prototype原型 | 每次通过 Spring 容器获取的 prototype 定义的 Bean 时,容器都将建一个新的 Bean实例。 |
| requesto | 在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。对不同的 HTTP 请求则会产生一个新的 Bean而且该 Bean 仅在当前HTTP Request内有效。 |
| sessione | 在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。对不同的 HTTP 请求则会产生一个新的 Bean且该 Bean 仅在当前 HTTP Session 内有效。 |
| globalSessione | 在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。仅在使用portlet上下文时有效。 |
| applicatione | 为每个 ServletContext 对象创建一个实例。仅在 Web 相关的ApplicationContext中生效。 |
| websocket | 为每个 websocket对象创建一个实例。仅在 Web 相关的ApplicationContext中生效。 |
### 2.8生命周期
了解Spring中Bean生命周期有何意义
了解Spring中Bean的生命周期的意义就在于可以利用Bean在其存活期间的特定时刻完成一些相关操作。这种时刻可能有很多但一般情况下常会在Bean的postinitiation(初始化后)和predestruction销毁前执行一些相关操作。
| | |
| :-------------: | :----------------------------------------------------------: |
| singleton作用域 | Spring容器可以管理singleton作用域的Bean的生命周期在此作用域下Spring能够精确的知道该Bean何时被创建何时初始化完成以及何时被销毁。 |
| prototype作用域 | prototype作用域的Bean,Spring只负责创建当容器创建了Bean实例后Bean的实例就交给客户端代码来管理Spring容器将不再跟踪其生命周期。 |

View File

@ -0,0 +1,272 @@
# 第三章Spring AOP
代理:
生活中的代理: 代购(代理对象):卖化妆品 代理 韩国卖化妆品的那个商店(被代理对象):卖化妆品
代理对象和被代理对象的区别?
```
代理对象可以完成被代理对象的功能,除此之外,代理对象还可以添加额外功能
```
示例:
```java
package com.gzh;
//韩国商店
public class Shop {
void sell(){
System.out.println("韩国商店卖化妆品100元");
}
}
```
```java
package com.gzh;
public class Daigou {
private Shop shop;
public void setShop(Shop shop) {
this.shop = shop;
}
void sell(){
System.out.println("代购要收十元小费");
shop.sell();
System.out.println("代购卖化妆品110元");
}
}
```
```java
package com.gzh;
//Test类模拟买化妆品的人
public class Test {
public static void main(String[] args) {
Daigou daigou = new Daigou();
daigou.setShop(new Shop());
daigou.sell();
}
}
```
运行截图:
![image-20220323125142944](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220323125142944.png)
## AOP术语
AOP面向切面编程
1Aspect切面本质就是类例如MyAspect切面类完成额外功能或非核心业务功能。
2Joinpoint连接点目标方法的调用的前和后都可以称为连接点目标方法在被代理类中
3pointcut切入点就是 切入了额外功能的 连接点
4Advice通知、增强处理就是额外功能
5Target Object目标对象被代理对象。例如com.jdk.UserDaoImpl
6Proxy(代理):代理对象
7Weaving织入产生代理对象的过程例如createProxy
## 3.2.1 JDK动态代理
代理是谁或者说被代理对象是谁是实现了接口的类com.jdk.UserDaoImpl
额外功能所在的类? MyAspect类
如何产生代理对象? JdkProxy类
代理对象的额外功能是如何完成的?
```java
package com.jdk;
public interface UserDao {
void addUser();
void deleteUser();
}
```
```java
package com.jdk;
//被代理对象就是这个实现类,该类中的方法叫做目标方法
public class UserDaoImpl implements UserDao{
@Override
public void addUser() {
System.out.println("添加用户");
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
}
```
```java
package com.jdk;
//额外的功能在目标方法调用前调用check_permission;在目标方法调用后条用log方法
public class MyAspect {
public void check_permission(){
System.out.println("模拟权限检查");
}
public void log(){
System.out.println("模拟记录日志");
}
}
```
```java
package com.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//产生代理对象的类
public class JdkProxy implements InvocationHandler {
private UserDao userDao;
//方法的返回值是代理对象
public Object createProxy(UserDao userDao){
this.userDao=userDao;
ClassLoader classLoader= JdkProxy.class.getClassLoader();
Class[] clazz=userDao.getClass().getInterfaces();
return Proxy.newProxyInstance(classLoader,clazz,this);
}
//invoke方法就是代理对象完成目标功能和额外功能的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MyAspect myAspect=new MyAspect();
myAspect.check_permission();
Object obj = method.invoke(userDao,args);//当程序指向到此语句时,转而调用目标方法
myAspect.log();
return obj;
}
}
```
```java
package com.jdk;
public class JdkTest {
public static void main(String[] args) {
//被代理对象
UserDao userDao = new UserDaoImpl();
userDao.addUser();
System.out.println("----------------");
//生成代理对象
JdkProxy jdkProxy = new JdkProxy();
UserDao proxy = (UserDao) jdkProxy.createProxy(userDao);
proxy.addUser();//当程序指向到此语句时转而执行invoke方法
}
}
```
运行截图:
![image-20220323150132535](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220323150132535.png)
## 3.2.2CGLIB代理
代理是谁或者说被代理对象是谁User类有两个目标方法addUser() deleteUser()
额外功能所在的类? MyAspect类
如何产生代理对象? CglibProxy类中的方法
代理对象的额外功能是如何完成的?
```java
package com.cglib;
public class User {
void addUser() {
System.out.println("添加用户");
}
void deleteUser() {
System.out.println("删除用户");
}
}
```
```java
package com.cglib;
//额外的功能在目标方法调用前调用check_permission;在目标方法调用后条用log方法
public class MyAspect {
public void check_permission() {
System.out.println("模拟权限检查");
}
public void log() {
System.out.println("模拟记录日志");
}
}
```
```java
package com.cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Cglibproxy implements MethodInterceptor {
public Object createProxy(Object target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
MyAspect myAspect = new MyAspect();
myAspect.check_permission();
Object obj = methodProxy.invokeSuper(proxy, args);//程序执行到此条语句时,转而执行目标方法
myAspect.log();
return obj;
}
}
```
```java
package com.cglib;
public class cglibTest {
public static void main(String[] args) {
//被代理对象
User user = new User();
user.addUser();
System.out.println("---------------");
//代理对象
Cglibproxy cglibProxy = new Cglibproxy();
User proxy = (User) cglibProxy.createProxy(user);
proxy.addUser();//程序执行到此条语句时转为执行intercept方法
}
}
```
运行截图如下:
![image-20220324113512719](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324113512719.png)
JDK代理和CGLIB代理方式的缺点
代理对象不管调用哪一种目标方法时,都会调用额外的功能。
能不能有一种手段可以使得程序员自己自由指定那些目标被调用时调用额外的功能呢Spring

View File

@ -0,0 +1,277 @@
# 第三章
### 1.代理
生活中的代理: 代购
从Java的角度去实现代理
### 3.2.1 JDK动态代理
被代理对象:实现了接口的类 写的就是核心的业务功能
切面类:写的是非核心的业务功能
生成代理对象的类JdkProxy
代码实现同上节课
### 3.2.2 CGLIB代理
被代理对象:某个类
切面类:
生成代理对象的类CglibProxy
代码实现同上节课
### AOP 术语:
AOP面向切面编程
切面类MyAspect
连接点: addUser() deleteUser() 调用前或后
切入点:就是连接点
增强处理/通知:就是切面中的方法 check_permission() log()
目标对象: 被代理对象
代理:代理对象
织入:生成代理对象的过程
### 从Spring的角度去实现代理
(1)导包:
5个核心包commons-logging spring-context spring-beans spring-core spring-expression
2个包spring-aop aoplliance
(2)创建接口和实现类
(3)创建切面类
(4)生成代理对象 xml文件
(5)测试
pom.xml文件
```java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
```
```java
package com.aop;
public interface UserDao {
void addUser();
void deleteUser();
}
```
```java
package com.aop;
public class UserDaoImpl implements UserDao {
@Override
public void addUser() {
System.out.println("添加用户");
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
}
```
```java
package com.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyAspect implements MethodInterceptor {
void check_permission() {
System.out.println("模拟权限检查");
}
void log() {
System.out.println("模拟记录日志");
}
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
check_permission();
Object proceed = methodInvocation.proceed();//调用目标方法
log();
return proceed;
}
}
```
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 1.目标对象:被代理对象-->
<bean id="userDao" class="com.aop.UserDaoImpl"/>
<!-- 2.切面类对象-->
<bean id="myAspect" class="com.aop.MyAspect"/>
<!-- 3.生成代理对象-->
<bean id="userDaoproxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 3.1指定代理实现的接口-->
<property name="proxyInterfaces" value="com.aop.UserDao"/>
<!-- 3.2指定目标对象-->
<property name="target" ref="userDao"/>
<!-- 3.3指定切面,植入环绕通知-->
<property name="interceptorNames" value="myAspect"/>
<!-- 3.4指定代理方式true使用cglibfalse默认使用jdk动态代理-->
<property name="proxyTargetClass" value="false"/>
</bean>
</beans>
```
```java
package com.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopTest {
public static void main(String[] args) {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("a.xml");
//被代理对象
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.addUser();
System.out.println("------------------------------");
//代理对象
UserDao userDaoproxy = (UserDao) applicationContext.getBean("userDaoproxy");
userDaoproxy.addUser();
}
}
```
代码实现截图:
![image-20220324140614514](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324140614514.png)
不管是从Java角度还是Spring角度实现的代理有一个共同点缺点
代理对象不管调用哪个目标方法,都会切入切面类中的方法。
有没有一种手段,可以让代理对象自由地决定调用哪个目标方法时才切入切面类中的方法?
Aspectj框架实现代理
### 补充:异常
### 1.异常类
#### 1算术异常
java.lang.ArithmeticException: / by zero
```java
package com.exception;
public class ExceptionTest {
static int divide(int x,int y){
int result=x/y;
return result;
}
public static void main(String[] args){
int divide = divide(4,0);
System.out.println(divide);
}
}
```
![image-20220324142225871](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324142225871.png)
#### 2空指针异常
java.lang.NullPointerException
```java
package com.exception;
class A{
void a(){}
}
public class ExceptionTest2 {
static A a;
public static void main(String[] args){
a.a();
}
}
```
![image-20220324143554018](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324143554018.png)
### 2.处理异常
#### 1捕获异常
try{}catch(){}finally{}
finally可以省略catch可以有多个
```java
package com.exception;
public class ExceptionTest5 {
static int divide(int x,int y) throws Exception{
int result=x/y;
return result;
}
public static void main(String[] args) {
try {
divide(4,0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
#### 2抛异常
throws
当调用了方法抛出异常的方法时,调用者可以继续抛异常,也可捕获异常
```java
package com.exception;
public class ExceptionTest4 {
static int divide(int x,int y) throws Exception{
int result=x/y;
return result;
}
public static void main(String[] args) throws Exception {
divide(4,0);
}
}
```

View File

@ -0,0 +1,328 @@
# 第三章Spring AOP
## 复习知识
### 1.从java角度出发实现代理
JDK动态代理 和 CGLIB代理 的区别:
1被代理对象不同
2产生代理对象的类不同
### 2.从Spring角度出发实现代理
1导包7个包 5个核心包commons-logging spring-context spring-beans spring-core spring-expression
2个包spring-aop aoplliance
2创建被代理对象实现了某个接口的类
3切面类实现接口
4产生代理对象方式xml文件
5测试
### 3.AOP术语7个
切面类MyAspect
连接点: addUser() deleteUser() 调用前或后
切入点:就是连接点
增强处理/通知:就是切面中的方法 check_permission() log()
目标对象: 被代理对象
代理:代理对象
织入:生成代理对象的过程
### 4.1和2中实现的代理有一个共同的特点缺点
代理对象不管调用哪一个目标方法,都会切入切面类中的方法
### 5.有没有一种手段:让代理对象自由地选择调用哪一个目标方法时才切入切面类中的方法?
——————————————————————————————————————————————————
## 基于AspectJ实现AOP实现代理
### 一、基于xml
(1)导包5个核心包commons-logging spring-context spring-core spring-beans spring-expression
2个包spring-aspects aspectjweaver
(2) 创建被代理对象
(3) 创建切面类
(4) 创建代理对象xml文件使用aop编程
(5) 测试
代码实现如下:
```java
package com.aspectj.xml;
public interface UserDao {
void addUser();
void deleteUser();
}
```
```java
package com.aspectj.xml;
public class UserDaoImpl implements UserDao {
@Override
public void addUser() {
System.out.println("添加用户");
// 模拟异常
// System.out.println(1/0);
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
}
```
```java
package com.aspectj.xml;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspect {
//前置通知
public void myBefore(JoinPoint joinPoint){
System.out.print("前置通知:模拟执行权限检查...,");
System.out.print("目标类是:"+joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
}
//后置通知
public void myAfterRturning(JoinPoint joinPoint) {
System.out.print("后置通知:模拟记录日志...");
System.out.println("被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());
}
// 环绕通知
// ProceedingJoinPoint 是 JoinPoint 子接口,表示可以执行目标方法
// 1.必须是 Object 类型的返回值
// 2.必须接收一个参数,类型为 ProceeddingJoinPoint
// 3.必须 throws Throwable
public Object myAround(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
//开始
System.out.println("环绕开始:执行目标方法之前,模拟开始事务...");
// 执行当前目标方法
Object obj = proceedingJoinPoint.proceed();
//结束
System.out.println("环绕结束:执行目标方法之后,模拟关闭事物...");
return obj;
}
//异常通知
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("异常通知:"+"出错了"+e.getMessage());
}
//最终通知
public void myAfter(){
System.out.println("最终通知:模拟方法结束后的释放资源...");
}
}
```
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1.目标对象:被代理对象-->
<bean id="userDao" class="com.aspectj.xml.UserDaoImpl"/>
<!-- 2.切面类对象-->
<bean id="myAspect" class="com.aspectj.xml.MyAspect"/>
<!-- 3.产生代理对象的aop编程-->
<aop:config>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 1. *目标方法返回值-->
<!-- 2. com.aspectj.xml 包-->
<!-- 3. * 包下所有类-->
<!-- 4. * 类中所有方法-->
<!-- 5. ..)类中所有方法-->
<!-- 配置切入点-->
<aop:pointcut id="myPointCut" expression="execution(* com.aspectj.xml.*.*(..))"/>
<!-- 配置前置通知-->
<aop:before method="myBefore" pointcut-ref="myPointCut"/>
<!-- 配置后置通知:目标方法被成功执行后,才调用的方法-->
<aop:after-returning method="myAfterRturning" pointcut-ref="myPointCut"/>
<!-- 配置环绕通知:目标方法调用前会被调用,目标方法被成功执行后,还会被调用-->
<aop:around method="myAround" pointcut-ref="myPointCut"/>
<!-- 配置异常通知:调用目标方法时发生异常才会被调用-->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
<!-- 配置最终通知:目标方法被调用后,不管是否被成功调用,此方法都会被调用-->
</aop:aspect>
</aop:config>
</beans>
```
```java
package com.aspectj.xml;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class XmlTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("a.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.addUser();
System.out.println("_______________");
userDao.deleteUser();
}
}
```
正常运行结果:
![image-20220328214914512](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220328214914512.png)
运行发生异常截图:出现结果为零异常
![image-20220328214954611](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220328214954611.png)
### 二、基于注解Annotation-------减少xml中的代码量
(1) 导包 5个核心包commons-logging spring-context spring-core spring-beans spring-expression
2个包spring-aspects aspectjweaver
(2) 创建被代理对象
(3) 创建切面类 注意切面类中的注解相当于a.xml文件中的哪一句代码
(4) 创建xml文件扫描所有的注解和开启AspectJ实现AOP
```java
package com.aspectj.annotation;
public interface UserDao {
void addUser();
void deleteUser();
}
```
```java
package com.aspectj.annotation;
import org.springframework.stereotype.Repository;
//注解实现
//@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void addUser() {
System.out.println("添加用户");
// 模拟异常
// System.out.println(1/0);
}
@Override
public void deleteUser() {
System.out.println("删除用户");
}
}
```
```java
package com.aspectj.annotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//切面类,在此类中编写通知
@Aspect
@Component
public class MyAspect {
// 定义切入点表达式
@Pointcut("execution(* com.aspectj.annotation.*.*(..))")
// 使用一个返回值为 void 、方法体为空的方法来命名切入点
private void myPointCut(){}
// 前置通知
@Before("myPointCut()")
public void myBefore(JoinPoint joinPoint){
System.out.println("前置通知:模拟执行权限检查...,");
System.out.print("目标类是:"+joinPoint.getTarget());
System.out.println(",被植入增强处理的目标方法为:"+joinPoint.getSignature().getName());
}
//后置通知
@AfterReturning("myPointCut()")
public void myAfterReturning(JoinPoint joinPoint){
System.out.println("后置通知:模拟记录日志...");
System.out.println("被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());
}
//环绕通知
@Around("myPointCut()")
public Object myAround(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
//开始
System.out.println("环绕开始:执行目标方法之前,模拟开始事务...");
//执行当前目标方法
Object obj = proceedingJoinPoint.proceed();
//结束
System.out.println("环绕结束:执行目标方法之后,模拟关闭事物...");
return obj ;
}
//异常通知
@AfterThrowing(value = "myPointCut()",throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
System.out.println("异常通知:"+"出错了"+e.getMessage());
}
//最终通知
@After("myPointCut()")
public void myAfter(){
System.out.println("最终通知:模拟方法结束后的释放资源...");
}
}
```
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 通过Bean实现-->
<bean id="userDao" class="com.aspectj.annotation.UserDaoImpl"/>
<!--扫描所有注解-->
<context:component-scan base-package="com.aspectj.annotation"/>
<!-- 开始Aspectj实现AOP-->
<aop:aspectj-autoproxy/>
</beans>
```
```java
package com.aspectj.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("b.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.deleteUser();
userDao.addUser();
}
}
```
运行截图:
![image-20220328215304530](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220328215304530.png)

View File

@ -0,0 +1,400 @@
# 第四章Spring的数据库开发
JDBC: Java Database Connector
JdbcTemplate方法
## 一、execute()
#### (1)mysql创建数据库spring
```mysql
create database spring;
```
#### (2)导包
五个核心包commons-logging spring-core spring-beans spring-context spring-expression
其他两个包spring-jdbc mysql-connector-java
```java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
#### (3)创建配置文件a.xml
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--1.配置数据源: 创建DriverManagerDataSource对象连接数据库-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</bean>
<!-- 2.创建JdbcTemplate类对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 创建实现类对象-->
<bean id="accountDao" class="com.gzh.dao.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
</beans>
```
#### (4)测试execute()方法
```java
package com.gzh;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
public class JdbcTest {
public static void main(String[] args) {
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("a.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
String sql="create table account(id int primary key auto_increment,username varchar (50),balance double)";
jdbcTemplate.execute(sql);
}
}
```
运行结果如下数据库中已经成功创建表account
![image-20220329195454770](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329195454770.png)
## 二、update():增删改
实体类对象 转换 表中记录
### 实体类:
1和表对应一张表对应一个实体类
2实体类中的成员变量 表中字段一一对应(数据类型 名称)
3实体类中的作用就是和表进行数据传输
SSM项目分三层dao层 服务层 控制层此代码为了简便只创建dao层
dao层
接口:接口中所有方法就是系统的功能。 面向接口编程
实现类声明了一个JdbcTemplate类对象
### 步骤:
#### 1创建实体类
```java
package com.gzh.domain;
public class Account {
private int id;
private String username;
private double balance;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", username='" + username + '\'' +
", balance=" + balance +
'}';
}
}
```
#### 2创建接口
```java
package com.gzh.dao;
import com.gzh.domain.Account;
public interface AccountDao {
//增加记录
int addAccount(Account account);
//删除根据用户ID删除账户
int deleteById(int id);
//更新记录
int updateAccount(Account account);
}
```
#### 3实现接口
```java
package com.gzh.dao;
import com.gzh.domain.Account;
import org.springframework.jdbc.core.JdbcTemplate;
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
//增加记录
@Override
public int addAccount(Account account) {
String sql = "insert into account values(?,?,?)";
int update = jdbcTemplate.update(sql, account.getId(), account.getUsername(), account.getBalance());
return update;
}
//删除根据用户ID删除账户
@Override
public int deleteById(int id) {
String sql = "delete from account where id=?";
int update = jdbcTemplate.update(sql, id);
return update;
}
//更新记录
@Override
public int updateAccount(Account account) {
String sql = "update account set username=?,balance=? where id=?";
int update = jdbcTemplate.update(sql, account.getUsername(), account.getBalance(), account.getId());
return update;
}
}
```
#### 4写配置文件
```java
<!-- 1.配置数据源: 创建DriverManagerDataSource对象连接数据库-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</bean>
<!-- 2.创建JdbcTemplate类对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 3.创建实现类对象-->
<bean id="accountDao" class="com.gzh.dao.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
```
#### 5测试Test方法
```java
package com.gzh;
import com.gzh.dao.AccountDao;
import com.gzh.domain.Account;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JdbcTest {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("a.xml");
AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
@Test
//增加记录
public void addAccountTets() {
Account account = new Account();
account.setId(1);
account.setUsername("zhangsan");
account.setBalance(1000);
accountDao.addAccount(account);
}
@Test
//删除根据用户ID删除账户
public void deleteByIdTest() {
accountDao.deleteById(1);
}
@Test
//更新记录
public void updateAccountTest() {
Account account = new Account();
account.setUsername("zhangsan");
account.setBalance(3000);
account.setId(1);
accountDao.updateAccount(account);
}
}
```
#### 运行截图:
1.创建两个数据
![image-20220331221520933](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331221520933.png)
2.测试删除数据
![image-20220331221604934](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331221604934.png)
3.更新数据
![image-20220331221704292](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331221704292.png)
### 补充:
#### 1.Object
当方法形参个数不确定的时候可以使用Object...,代表的是多个多种类型的参数
#### 2.基本数据类型 包装类
int Integer
double Double
```
int a = 5;
Integer b = a; //装箱
int c = b; //拆箱
```
#### 3.单元测试
可以直接运行一个非main方法的方法 @Test
```java
public class AccountDao{
@Test
public void cat(){
System.out.println("a");
}
@Test
public void cat(){
System.out.println("b");
}
}
```
## 三、query():查
表中的记录 转换 实体类对象
### 步骤:
#### 1创建实体类
同上
#### 2创建接口
```java
//查询 根据id进行查询 单条记录
Account findAccountById(int id);
//查所有记录
List<Account> findAllAccounts();
```
#### 3实现接口
```java
//查询 根据id进行查询 单条记录
@Override
public Account findAccountById(int id) {
String sql = "select * from account where id =?";
RowMapper<Account> rowMapper = new BeanPropertyRowMapper<>(Account.class);
Account account = jdbcTemplate.queryForObject(sql, rowMapper, id);
return account;
}
//查所有记录
@Override
public List<Account> findAllAccounts() {
String sql = "select * from account";
RowMapper<Account> rowMapper = new BeanPropertyRowMapper<Account>(Account.class);
List<Account> account = jdbcTemplate.query(sql, rowMapper);
return account;
}
```
#### 4写配置文件
同上
#### 5测试Test方法
```java
@Test
//查询 根据id进行查询 单条记录
public void findAccountByIdTest() {
Account accountById = accountDao.findAccountById(1);
System.out.println(accountById);
}
@Test
//查所有记录
public void findAllAccoundsTest() {
List<Account> accounts = accountDao.findAllAccounts();
for (Account i : accounts) {
System.out.println(i);
}
}
```
#### 运行截图:
1.单个查询
![image-20220331223326855](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331223326855.png)
2.多项查询
![image-20220331223422159](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331223422159.png)

View File

@ -0,0 +1,145 @@
# 第五章Spring的事务管理
transfer()的语句要么全做,要么全不做?
```java
把transfer方法做成事务方法。
事务方法:方法体中的代码要么全部,要么全不做。
```
如何把transfer()做成事务方法呢?
```java
1.基于xml文件
2.基于注解
```
AOP关键导包
```java
<dependency>
<groupId>org.aspectj</groupId >
<artifactId>aspectjweaver</artifactId >
<version>1.8.7</version >
</dependency>
```
以转钱为例,在未进行事务管理之前转账记录在遇到异常会将方法执行一半,这样会使部分资金转账失效,并且无退回,用事务管理之后方法不会因为异常而执行一半,只有**完全执行**和**不执行**。
## 一、基于XML方式的声明式事务
#### 1创建实体类
同上
#### 2创建接口
```java
//转钱outUser给inUser转money钱
void transfer(String outUser, String inUser, double money);
```
#### 3实现接口
```java
//转钱outUser给inUser转money钱
@Override
public void transfer(String outUser, String inUser, double money) {
String sql = "update account set balance=balance-? where username=?";
jdbcTemplate.update(sql, money, outUser);
//模拟异常
System.out.println(1 / 0);
String sql1 = "update account set balance=balance+? where username=?";
jdbcTemplate.update(sql1, money, inUser);
}
```
#### 4写配置文件
在上一章文件中增添以下配置
```java
<!-- 基于事务管理器,以来于数据源-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- (1).基于XML方式的声明式事务-->
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(void com.gzh.dao.AccountDaoImpl.transfer(String,String,double))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
```
#### 5测试Test方法
```java
@Test
//转钱outUser给inUser转money钱
public void transferTest() {
accountDao.transfer("zhangsan", "lisi", 500);
}
```
#### 运行截图:
1.无异常
![image-20220331225557619](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331225557619.png)
2.有异常
![image-20220331225618374](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331225618374.png)
## 二、基于Annotation注解方式的声明式事务
#### 1创建实体类
同上
#### 2创建接口
同上
#### 3实现接口
```java
//在实现类上添加注解
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
```
#### 4写配置文件
在上一章文件中增添以下配置
```java
<!-- 基于事务管理器,以来于数据源-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- (2).基于注解方式声明式事务-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
```
#### 5测试Test方法
同上
#### 运行截图:
1.无异常:
![image-20220331225721435](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331225721435.png)
2.有异常:
![image-20220331225754769](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220331225754769.png)

View File

@ -0,0 +1,455 @@
# 第6章MyBatis
Spring: 负责实现业务层的逻辑
MyBatis主要和数据库打交道
Spring MVC主要负责前端页面
## 6.1 MyBatis
1.持久层框架: 负责数据库开发
2.ORM框架Object/Relational Mapping
3.POJO(Plain Old Java Object)普通的Java对象
PO(Persisent Object):持久化对象
## 6.2
## 6.3
## 6.4 MyBatis的入门程序
基于MyBatis的客户管理系统的设计与实现
### 系统功能:
```java
1. 根据id查询客户
2. 根据姓名模糊查询
3. 添加客户
4. 更新客户
5. 删除客户
```
### 程序准备:
#### 1mysql中创建数据库mybatis,表t_customer,插入数据。
```mysql
create database mybatis;
```
```mysql
create table t_customer(
id int (32) primary key auto_increment,
username varchar(50),
jobs varchar(50),
phone varchar(16)
);
```
```mysql
insert into t_customer values
('1','joy','doctor','13745874578'),
('2','jack','teacher','13521210112'),
('3','tom','worker','15179405961');
```
![image-20220405130626049](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405130626049.png)
#### 2创建项目导2个包mybatis mysql-connector-java
```java
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<!-- 版本号与自己mysql版本一致-->
</dependency>
```
#### 3创建持久化类实体类
作用:和表进行数据转换
-- 增:实体类对象 转换 表中的记录
-- 查:表中的记录 转换 实体类对象
注意:成员变量的名字、数据类型 需要和 表中字段的名字、数据类型 保持一致
生成setter、getter 和 toString()方法
```java
package com.gzh.po;
public class Customer {
private int id;
private String username;
private String jobs;
private String phone;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getJobs() {
return jobs;
}
public void setJobs(String jobs) {
this.jobs = jobs;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", username='" + username + '\'' +
", jobs='" + jobs + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
```
#### 4在resources文件夹下创建CustomerMapper.xml文件用来写sql语句
##### 1.首先创建模板
在 file (文件)中的 setting (设置)中搜索 File and Code Templates (文件和代码模板),在其中首页 Files (文件)下创建文件 Mapper.xml然后在下面填入以下代码选择 OK (确定) 退出
```java
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="">
</mapper>
```
![image-20220405131535640](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405131535640.png)
##### 2.创建CustomerMapper.xml文件
在 resources 文件夹右击选择 new新建Mapper
![image-20220405132203804](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405132203804.png)
##### 3.写sql语句
```java
1.namespace属性的值copy path复制路径/引用)中 file name(文件名),去掉.xml
<mapper namespace="CustomerMapper">
2.#{id}占位符
3.parameterType是来设置占位符对应的参数的数据类型
4.resultType用来设置接收查询结果的持久化类注意的是resultType属性值是全类名全限定名
<select id="findCustomerById" parameterType="int"resultType="com.gzh.po.Customer">
select * from t_customer where id=#{id}
</select>
```
![image-20220405132451651](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405132451651.png)
#### 5在resources文件夹下创建mybatis-config.xml文件该文件是MyBatis框架的配置文件
##### 1.首先创建模板
在 file (文件)中的 setting (设置)中搜索 File and Code Templates (文件和代码模板),在其中首页 Files (文件)下创建文件 mybatis-config.xml然后在下面填入以下代码选择 OK (确定) 退出
```java
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>
</configuration>
```
![image-20220405131954150](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405131954150.png)
##### 2.创建mybatis-config.xml文件
在 resources 文件夹右击选择 new新建mybatis-config
![image-20220405132528897](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405132528897.png)
##### 3.配置MyBatis框架
```java
<configuration>
<!-- 1.连接数据库-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!-- 四个成员变量不能错-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</dataSource>
</environment>
</environments>
<!-- 2.加载Mapper文件-->
<mappers>
<!-- resource 从 copy path复制路径/引用)中 file name(文件名)-->
<mapper resource="CustomerMapper.xml"/>
</mappers>
</configuration>
```
![image-20220405132915669](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405132915669.png)
#### 6单元测试查询
在 com.gzh.po 包下创建测试类MybatisTest
1.加载配置文件和 Mapper 文件
通过 CustomerMapper.xml 文件中的 select 的 id 的值来命名测试类
![image-20220405133745512](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405133745512.png)
在输入 **Resources** 时通过提示导入名为 org 开头的包
![image-20220405134057509](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405134057509.png)
在此输入完此行代码后 getResourceAsStream 会爆红,不用管后续处理
```java
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
```
##### 2.构建会话工厂
```java
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
```
##### 3.构建会话 SqlSession
```java
SqlSession sqlSession = sqlSessionFactory.openSession();
```
因为要测试多个方法,所以将以上构造剪切到**成员变量**
![image-20220405134848712](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405134848712.png)
##### 4.处理爆红错误
将鼠标放置到爆红的 resourceAsStream 处 Alt+回车 处理问题,选择添加类默认构造函数签名的异常
![image-20220405134938312](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405134938312.png)
##### 5.导包 Test ,并写完查询类
selectOne中的参数 = CustomerMapper.xml文件中 namespace + select id
MybatisTest.java 总体代码如下:
```java
package com.gzh.po;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MybatisTest {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
public MybatisTest() throws IOException {
}
@Test
public void findCustomerById(){
// s: = CustomerMapper.xml文件中 namespace + select id
Customer o = sqlSession.selectOne("CustomerMapper.findCustomerById", 1);
System.out.println(o);
}
}
```
运行结果如下:
![image-20220405135447683](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405135447683.png)
### 1.根据id查询客户
```java
<select id="findCustomerById" parameterType="int" resultType="com.gzh.po.Customer">
select * from t_customer where id=#{id}
</select>
```
```java
@Test
public void findCustomerById() {
Customer o = sqlSession.selectOne("com.CustomerMapper.findCustomerById", 1);
System.out.println(o);
}
```
![image-20220407152029547](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152029547.png)
### 2.根据姓名模糊查询
```java
<select id="findCustomerByName" parameterType="String" resultType="com.gzh.po.Customer">
select * from t_customer where username like '%${value}%'
</select>
```
```java
@Test
public void findCustomerByName() {
List<Customer> o = sqlSession.selectList("CustomerMapper.findCustomerByName", "j");
for (Customer customer : o){
System.out.println(customer);
}
}
```
![image-20220407152044583](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152044583.png)
### 3.添加客户
```java
<insert id="addCustomer" parameterType="com.gzh.po.Customer">
insert into t_customer values (#{id},#{username},#{jobs},#{phone})
</insert>
```
```java
@Test
public void addCustomer(){
Customer customer = new Customer();
customer.setId(1);
customer.setUsername("zhangsan");
customer.setJobs("student");
customer.setPhone("110");
sqlSession.insert("CustomerMapper.addCustomer",customer);
sqlSession.commit();//只要更改数据库中的数据,就需要调用该方法完成数据的
sqlSession.close();//关闭数据库的连接
}
```
![image-20220407152231144](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152231144.png)
### 4.更新客户
```java
<update id="updateCustomer" parameterType="com.gzh.po.Customer">
update t_customer set username = #{username},jobs = #{jobs},phone = #{phone} where id = #{id}
</update>
```
```java
@Test
public void updateCustomer() {
Customer customer = new Customer();
customer.setId(4);
customer.setUsername("zhangsan");
customer.setJobs("teacher");
customer.setPhone("18888888888");
sqlSession.update("CustomerMapper.updateCustomer", customer);
sqlSession.commit();
sqlSession.close();
}
```
![image-20220407152334704](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152334704.png)
### 5.删除客户
```java
<delete id="deleteCustomer" parameterType="int">
delete from t_customer where id = #{id}
</delete>
```
```java
@Test
public void deleteCustomer() {
sqlSession.delete("CustomerMapper.deleteCustomer", 1);
sqlSession.commit();
sqlSession.close();
}
```
![image-20220407152346163](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152346163.png)
### 如何在控制台输入SQL语句
(1) 导包 log4j
```java
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
```
(2) 复制log4j.properties文件到resources.文件夹下
(3) resources下新建directory,名为com
(4) 将CustomerMapper.xml文件复制到com下
![image-20220407152650898](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152650898.png)
(5) 复制后的CustomerMapper.Xml中的namespacel的值修改com.CustomerMapper
![image-20220407152719404](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152719404.png)
(6) 修改mybatis-config.xml文件中resource属性的值
![image-20220407152735127](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152735127.png)
(7) 修改测试方法中的值:
![image-20220407152802930](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152802930.png)
运行测试结果如下:
![image-20220407152822914](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407152822914.png)

View File

@ -0,0 +1,385 @@
# 第七章MyBatis核心配置
## 7.1 核心对象
### 1.复制第6章的代码
#### 1导包 mybatis mysql
```java
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
```
#### 2准备数据
沿用上一章节数据
#### 3复制实体类
```java
package com.gzh.po;
public class Customer {
private int id;
private String username;
private String jobs;
private String phone;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getJobs() {
return jobs;
}
public void setJobs(String jobs) {
this.jobs = jobs;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", username='" + username + '\'' +
", jobs='" + jobs + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
```
#### 4复制两个xml文件
mybatis-config.xml
```java
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>
<!--1.连接数据库-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<!--
transactionManager设置事务管理方式
属性:
type设置事务管理方式type="JDBC|MANAGED"
type="JDBC":设置当前环境的事务管理都必须手动处理
type="MANAGED"设置事务被管理例如spring中的AOP
-->
<dataSource type="POOLED">
<!--
dataSource设置数据源
属性:
type设置数据源的类型type="POOLED|UNPOOLED|JNDI"
type="POOLED":使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从缓存中直接获取,不需要重新创建
type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建
type="JNDI":调用上下文中的数据源
-->
<!--四个成员变量不能错-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</dataSource>
</environment>
</environments>
<!--2.加载Mapper文件-->
<mappers>
<!--
以包为单位,将包下所有的映射文件引入核心配置文件
注意:
1. 此方式必须保证mapper接口和mapper映射文件必须在相同的包下
2. mapper接口要和mapper映射文件的名字一致
-->
<!--resource 从 copy path复制路径/引用)中 file name(文件名)-->
<mapper resource="CustomerMapper.xml"/>
</mappers>
</configuration>
```
CustomerMapper.xml
```java
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!-- namespace属性的值copy path 中 file name(复制引用中的文件名),去掉.xml-->
<mapper namespace="CustomerMapper">
<!-- 1.根据id查询客户信息-->
<select id="findCustomerById" parameterType="int" resultType="com.gzh.po.Customer">
select * from t_customer where id=#{id}
</select>
<!-- 2.根据客户名进项模糊搜索-->
<select id="findCustomerByName" parameterType="String" resultType="com.gzh.po.Customer">
select * from t_customer where username like '%${value}%'
</select>
<!-- 3.添加客户-->
<insert id="addCustomer" parameterType="com.gzh.po.Customer">
insert into t_customer values (#{id},#{username},#{jobs},#{phone})
</insert>
<!-- 4.更新客户-->
<update id="updateCustomer" parameterType="com.gzh.po.Customer">
update t_customer set username = #{username},jobs = #{jobs},phone = #{phone} where id = #{id}
</update>
<!-- 5.删除客户-->
<delete id="deleteCustomer" parameterType="int">
delete from t_customer where id = #{id}
</delete>
</mapper>
```
#### 5测试类
```java
package com.gzh.po;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
public MybatisTest() throws IOException {
}
@Test
public void findCustomerById() {
Customer o = sqlSession.selectOne("CustomerMapper.findCustomerById", 2);
System.out.println(o);
}
```
运行结果如下:
![image-20220412211705869](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220412211705869.png)
### 2.创建工具类对外提供SqlSession对象
在 main 下创建一个新的包 com.gzh.utils (通常为工具包),并创建类 MyBatisUtil
```java
package com.gzh;
import com.gzh.po.Customer;
import com.gzh.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class MyBatisTest {
SqlSession sqlSession=MyBatisUtil.getSession();
@Test
public void findCustomerByIdTest(){
Customer o = sqlSession.selectOne("CustomerMapper.findCustomerById", 2);
System.out.println(o);
}
}
```
将 Test 测试类转移到 com.gzh 包下,代码如下:
```java
public class MyBatisTest {
SqlSession sqlSession=MyBatisUtil.getSession();
@Test
public void findCustomerByIdTest(){
Customer o = sqlSession.selectOne("CustomerMapper.findCustomerById", 2);
System.out.println(o);
}
}
```
运行截图:
![image-20220412213246062](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220412213246062.png)
## 7.2 配置文件
### 1.properties 元素
连接数据库,通过该元素进行内部配置外在化。
(1) 在resources下创建db.properties
```java
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=8520
```
(2) 修改配置文件 2处
1.在<configuration>文件下添加<properties>
```java
<properties resource="db.properties"/>
```
2.在<dataSource>标签中<property>的 value 属性修改如下:
```java
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
```
3测试运行截图
![image-20220413084844679](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220413084844679.png)
### 2.typeAliases元素 给实体类起别名
1修改CustomerMapper.xml中的修改resultType属性
```java
<select id="findCustomerById" parameterType="int" resultType="customer">
select * from t_customer where id=#{id}
</select>
```
2在mybatis-config.xml文件中起别名添加
```java
<properties resource="db.properties"/>
<typeAliases>
<typeAlias type="com.wqx.po.Customer" alias="customer"/>
</typeAliases>
```
3测试截图如下
![image-20220413090235983](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220413090235983.png)
## 7.3 映射文件
### 1.resultMap元素:将表中字段和实体类成员变量进行对应
1修改实体类 username->name
重写getter and setter 以及 toString()
2测试结果当实体类中的成员变量名和表中字段名字不一致时导致字段值不能被赋值给成员变量
Customer{id=2, name='null', jobs='teacher', phone='13521210112'}
![image-20220413091252095](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220413091252095.png)
3如何解决当实体类中的成员变量名和表中字段名字不一致时还可以将字段值赋值给成员变量
resultMap
4修改CustomerMapper.xml
添加 resultMap 和 修改 select 中主键的 resultType 属性改为 resultMap
```java
<resultMap id="a" type="customer">
<id property="id" column="id"/>
<result property="name" column="username"/>
<result property="jobs" column="jobs"/>
<result property="phone" column="phone"/>
</resultMap>
<select id="findCustomerById" parameterType="int" resultMap="a">
select * from t_customer where id=#{id}
</select>
```
---如何将sql语句显示到控制台
1log4j.properties
```java
#Global logging configuration
log4j.rootLogger=ERROR,stdout
#MyBatis logging configuration...
log4j.logger.com=DEBUG
#Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t]-%m%n
```
2导包
```java
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
```
3resources 下 创建com,把CustomerMapper.xml文件移动到com下
![image-20220413093052137](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220413093052137.png)
4修改两个xml文件
CustomerMapper.xml
```java
namespace="com.CustomerMapper"
```
mybatis-config.xml
```java
resource="com/CustomerMapper.xml"
```
5修改测试方法
```java
Customer o = sqlSession.selectOne("com.CustomerMapper.findCustomerById", 2);
```
6运行截图
![image-20220413092737690](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220413092737690.png)

View File

@ -0,0 +1,233 @@
# 第八章动态SQL
基于MyBatis的客户管理系统的设计与开发
## 1.复制第6章的代码
导包mybatis mysql
准备数据
数据库mybatis 表 t_customer
创建实体类Customer
创建CustomerMapper.xml文件写SQL语句的
创建mybatis-config.xml文件配置文件
创建工具类,对外提供
测试
在上一章节中有所展示记录
## 2.系统功能
### 1. if 元素
如果姓名和职业都不为空,按姓名和职业查找客户
如果姓名不为空职业为空,按姓名查找客户
如果姓名为空职业不为空,按职业查找客户
如果姓名和职业都为空,则查找所有客户。
#### 下面是 CustomerMapper.xml 文件中的 sql 语句:
```java
<!--
1.如果姓名和职业都不为空,按姓名和职业查找客户
select * from t_customer where 1=1 and username like concat('%',#{username},'%') and jobs=#{jobs}
2.如果姓名不为空职业为空,按姓名查找客户
select * from t_customer where 1=1 and username like concat('%',#{username},'%')
3.如果姓名为空职业不为空,按职业查找客户
select * from t_customer where 1=1 and jobs=#{jobs}
4.如果姓名和职业都为空,则查找所有客户。
select * from t_customer where 1=1
-->
test="username!=null and username!=''"
此处的username是实体类Customer的成员变量,如果test中条件成立and这一行代码就会被拼接到1=1的后面否则就不拼接
and username like concat('%',#{username},'%')
此处的第一个username是字段名第2个username.是实体类Customer的成员变量 concat函数 连接字符串
```
```java
<select id="findCustomerByNameAndJobs" parameterType="com.gzh.po.Customer" resultType="com.gzh.po.Customer">
select * from t_customer where 1=1
<if test="username!=null and username!=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs!=null and jobs!=''">
and jobs=#{jobs}
</if>
</select>
```
#### 测试类,通过名字进行查询:
```java
@Test
public void findCustomerByNameAndJobsTest(){
Customer customer = new Customer();
customer.setUsername("w");
List<Customer> objects = sqlSession.selectList("CustomerMapper.findCustomerByNameAndJobs", customer);
for (Customer object: objects) {
System.out.println(object);
}
}
```
#### 运行截图:
传一个名字,按名字查询:
![image-20220415134517801](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220415134517801.png)
不传参查询全部:
![image-20220415134721203](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220415134721203.png)
### 2. choose - when - otherwise 元素
当客户名不为空,只根据客户名查询
当客户名为空,职业不为空,则只根据职业查询
当客户名和职业都为空,则查询电话不为空的客户
#### 下面是 CustomerMapper.xml 文件中的 sql 语句:
```java
<!--
2.当客户名不为空,只根据客户名查询
select * from t_customer where 1=1 and username like concat('%',#{username},'%')
当客户名为空,职业不为空,则只根据职业查询
select * from t_customer where 1=1 and jobs=#{jobs}
当客户名和职业都为空,则查询电话不为空的客户
select * from t_customer where 1=1 and phone is not null
-->
```
```java
<select id="findCustomerByNameOrJobs" parameterType="com.gzh.po.Customer" resultType="com.gzh.po.Customer">
select * from t_customer where 1=1
<choose>
<when test="username!=null and username!=''">
and username like concat('%',#{username},'%')
</when>
<when test="jobs!=null and jobs!=''">
and jobs=#{jobs}
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>
```
#### 测试类,通过职业进行查询:
```java
@Test
public void findCustomerByNameOrJobs(){
Customer customer = new Customer();
customer.setJobs("teacher");
List<Customer> objects = sqlSession.selectList("CustomerMapper.findCustomerByNameOrJobs", customer);
for (Customer object: objects) {
System.out.println(object);
}
}
```
#### 运行截图:
传职业,按职业查询:
![image-20220415134806665](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220415134806665.png)
不传参,查询有手机号:
![image-20220415134848949](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220415134848949.png)
### 3. where 元素
> 根据需要自动添加 where ,而且会自动保留或去掉 and 关键字
如果姓名和职业都不为空,按姓名和职业查找客户
如果姓名不为空职业为空,按姓名查找客户
如果姓名为空职业不为空,按职业查找客户
如果姓名和职业都为空,则查找所有客户。
#### 下面是 CustomerMapper.xml 文件中的 sql 语句:
```java
<select id="findCustomerByNameAndJobs1" parameterType="com.gzh.po.Customer" resultType="com.gzh.po.Customer">
select * from t_customer
<where>
<if test="username!=null and username!=''">
and username like concat('%',#{username},'%')
</if>
<if test="jobs!=null and jobs!=''">
and jobs=#{jobs}
</if>
</where>
</select>
```
#### 测试类,通过姓名进行查询:
```java
@Test
public void findCustomerByNameAndJobs1Test(){
Customer customer = new Customer();
customer.setUsername("j");
List<Customer> objects = sqlSession.selectList("CustomerMapper.findCustomerByNameAndJobs1", customer);
for (Customer object: objects) {
System.out.println(object);
}
}
```
#### 运行截图:
传一个名字,按名字查询:
![image-20220415135501209](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220415135501209.png)
不传参查询全部:
![image-20220415135537915](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220415135537915.png)
### 4. set 元素
> 根据id更新客户信息 set元素根据需要自动去掉多余的逗号
通过 ID 更新信息
#### 下面是 CustomerMapper.xml 文件中的 sql 语句:
```java
<select id="updateCustomer" parameterType="com.gzh.po.Customer"> update t_customer
<set>
<if test="username!=null and username!=''">
username=#{username},
</if>
<if test="jobs!=null and jobs!=''">
jobs=#{jobs},
</if>
<if test="phone!=null and phone!=''">
phone=#{phone},
</if>
</set>
where id=#{id}
</select>
```
测试类,通过 ID 进行修改:
```java
@Test
public void updateCustomer(){
Customer customer = new Customer();
customer.setId(3);
customer.setUsername("maliu");
sqlSession.selectList("CustomerMapper.updateCustomer", customer);
sqlSession.commit();
sqlSession.close();
}
```
运行截图:
![image-20220415135735652](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220415135735652.png)

View File

@ -0,0 +1,231 @@
# 第九章MyBatis 的关系映射
> 实体和实体之间: 1:1 1:多 多:多
# 基于 MyBatis 的客户管理系统的设计与设计
## 功能:
### 一、根据id查询客户的所有信息(id,name,age,sex,Car_id,code)
> 进行关联查询的方式有两种:
>
> 1.嵌套查询需要写多个Mapper文件也就需要写多条SQL语句但是每一条SQL语句都很简单。
>
> 2.嵌套结果只需要写一个Mapper文件也就是只需要写一条SQL语句但是这一条sQL语句比较复杂
#### 1.准备数据
创建数据库 tb_idcard 和 tb_person两个表
```mysql
create table tb_idcard(
id int primary key auto_increment,
code varchar(18)
);
```
```mysql
insert into tb_idcard(code) values
('154326874565214862'),
('13254868459587852');
```
```mysql
create table tb_person(
id int primary key auto_increment,
name varchar(32),
age int,
sex varchar(8),
card_id int unique,
foreign key(card_id) references tb_idcard(id)
);
```
```mysql
insert into tb_person(name,age,sex,card_id) values
('Rose',20,'女',1),
('Tom',20,'男',2);
```
![image-20220419102233809](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220419102233809.png)
#### 2.创建项目导入依赖mybatis mysql
```java
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
```
#### 3.创建实体类
```java
//tb_idcard
private int id;
private String Code;
利用 getter setter 和 toString 方法生成代码
```
```java
//tb_person
private int id;
private String name;
private int age;
private String sex;
//注意此成员变量是另一个实体类的对象反映的是实体脚erson.和实体类红dcard,的1的关系
private IdCard card;
利用 getter setter 和 toString 方法生成代码
```
#### 4.创建 IdCardMapper.xml PersonMapper.xml 文件
```java
<mapper namespace="IdCardMapper">
<!--根据 id 查询证件信息-->
<select id="findCodeById" parameterType="int" resultType="com.gzh.domain.IdCard">
select * from tb_idcard where id=#{id}
</select>
</mapper>
```
```java
<mapper namespace="PersonMapper">
<!-- 1.根据 id 查询用户信息-->
<resultMap id="a" type="com.gzh.domain.Person">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
<association property="card" column="card_id" javaType="com.gzh.domain.IdCard"
select="IdCardMapper.findCodeById"/>
</resultMap>
<select id="findPersonById" resultMap="a" >
select * from tb_person where id=#{id}
</select>
</mapper>
```
#### 5.创建 mybatis-config.xml 文件
```java
<configuration>
<!--1.连接数据库-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</dataSource>
</environment>
</environments>
<!--2.加载数据库-->
<mappers>
<mapper resource="IdCardMapper.xml"/>
<mapper resource="PersonMapper.xml"/>
</mappers>
</configuration>
```
#### 6.复制工具类 MyBatisUtils
```java
//对外提供 sqlSession 对象
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
static {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSession() {
return sqlSessionFactory.openSession();
}
}
```
#### 7.测试类
```java
public class MyBatisTest {
SqlSession sqlSession = MyBatisUtils.getSession();
@Test
public void findPersonByIdTest(){
Person o = sqlSession.selectOne("PersonMapper.findPersonById",1);
System.out.println(o);
sqlSession.close();
}
}
```
运行截图:
![image-20220419112333746](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220419112333746.png)
### 二、使用嵌套结果根据id查询客户的所有信息(id,name,age,sex,Car_id,code)
#### 1.mybatis-config.xml 中修改:注释掉以下语句
```java
<!-- <mapper resource="IdCardMapper.xml"/>-->
```
#### 2.PersonMapper
```java
<!-- 根据嵌套结果来做查询-->
<resultMap id="b" type="com.gzh.domain.Person">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="sex" column="sex"/>
<association property="card" javaType="com.gzh.domain.IdCard">
<id property="id" column="card_id"/>
<result property="code" column="code"/>
</association>
</resultMap>
<select id="findPersonById2" parameterType="int" resultMap="b">
select p.*,idcard.code
from tb_person p,tb_idcard idcard
where p.card_id=idcard.id and p.id=#{id}
</select>
```
#### 3.测试
```java
public class MyBatisTest {
SqlSession sqlSession = MyBatisUtils.getSession();
@Test
public void findPersonByIdTest(){
Person o = sqlSession.selectOne("PersonMapper.findPersonById2",1);
System.out.println(o);
sqlSession.close();
}
}
```
![image-20220419120201332](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220419120201332.png)

View File

@ -0,0 +1,289 @@
# 第十章Spring 和 MyBatis 的整合
基于SSM的用户管理系统的设计与实现
## 基于传统的DAO方式的整合
#### 0.导包
mybatis mybatis-spring spring mysql spring-tx spring-jdbc commons-dbcp2
```java
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
#### 1.准备数据
mybatis 中的 t_customer
![image-20220426132557267](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220426132557267.png)
#### 2.创建实体类
```java
//在com.gzh.domain下创建
private int id;
private String username;
private String jobs;
private String phone;
//利用 getter setter 和 toString 方法生成代码
```
#### 3.在resources下创建CustomerMapper.xml文件
```java
<!-- 1.根据id查找用户-->
<select id="findCustomerById" parameterType="int" resultType="com.gzh.domain.Customer">
select * from t_customer where id=#{id}
</select>
</mapper>
```
#### 4.在resources下创建mybatis-config.xml文件
```java
<!--加载Mapper文件-->
<mappers>
<mapper resource="CustomerMapper.xml"/>
</mappers>
```
#### 5.创建DAO层接口和实现类
```java
//在com.gzh.dao包下创建接口
public interface CustomerDao {
Customer findCustomerById(int id);
}
```
```java
//在com.gzh.dao.impl包下创建实现类
public class CustomerDaoImpl extends SqlSessionDaoSupport implements CustomerDao {
@Override
public Customer findCustomerById(int id){
Customer o = getSqlSession().selectOne("CustomerMapper.findCustomerById", id);
return o;
}
}
```
#### 6.在resources下创建applicationContext.xml文件
```java
<!-- 1.连接数据库-->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</bean>
<!-- 2.加载MyBAtis的配置文件-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!-- 3.创建接口对象-->
<bean id="customerDao" class="com.gzh.dao.impl.CustomerDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
```
#### 7.测试
```java
//在com.gzh.domain包下创建测试类
@Test
public void findCustomerByIdTest(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerDao customerDao = (CustomerDao) applicationContext.getBean("customerDao");
Customer customerById = customerDao.findCustomerById(1);
System.out.println(customerById);
}
```
![image-20220426134717655](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220426134717655.png)
## 基于Mapper方式的整合
### 基于MapperFactoryBean的整合
#### 0.导包
与DAO方式导包数量相同
#### 1.准备数据
同上数据
#### 2.创建实体类
```java
//在com.gzh.domain下创建
private int id;
private String username;
private String jobs;
private String phone;
//利用 getter setter 和 toString 方法生成代码
```
#### 3.创建com.gzh.mapper. CustomerMapper接口文件
```java
public interface CustomerMapper {
Customer findCustomerById(int i);
}
```
#### 4.在resources下创建com->gzh->mapper->CustomerMapper.Xml文件
com.gzh.mapper 文件夹要一个一个创建,才能保证是嵌套的
```java
<mapper namespace="com.gzh.mapper.CustomerMapper">
<!--1.根据id查询客户信息-->
<select id="findCustomerById" parameterType="int" resultType="com.gzh.domain.Customer">
select * from t_customer where id=#{id}
</select>
</mapper>
```
#### 5.在resources下创建mybatis-config.xml文件
```java
<mappers>
<mapper resource="com/gzh/mapper/CustomerMapper.xml"/>
</mappers>
```
#### 6.在resources下创建applicationContext.xml文件
```java
<!-- 1.连接数据库-->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</bean>
<!-- 2.加载MyBAtis的配置文件-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!-- 3.创建MapperFactoryBean类对象-->
<bean id="factoryBean" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.gzh.mapper.CustomerMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
```
#### 7.测试
```java
@Test
public void findCustomerById(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerMapper factoryBean = (CustomerMapper) applicationContext.getBean("factoryBean");
Customer customerById = factoryBean.findCustomerById(1);
System.out.println(customerById);
}
```
![image-20220426135752830](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220426135752830.png)
虽然使用Mapper接口编程的方式很简单但是在具体使用时还是需要遵循以下规范。
> (I)Mapper接口的名称和对应的Mapper.xml映射文件的名称必须一致。
>
> (2)Mapper,.xml文件中的namespace与Mapper接口的类路径相同即接口文件和映射文件
> 需要放在同一个包中)。
>
> (3)Mapper接口中的方法名和Mapper.xml中定义的每个执行语句的id相同。
>
> (4)Mapper接口中方法的输入参数类型要和Mapper,.xml中定义的每个sql的parameterType
> 的类型相同。
>
> (5)Mapper接口方法的输出参数类型要和Mapper.xml中定义的每个sql的resultType的
> 类型相同。
只要遵循了这些开发规范MyBatis就可以自动生成Mapper接口实现类的代理对象从而
简化我们的开发。
### 基于MapperScannerConfigurer的整合
在上面的基础上修改
1.在 applicationContext 中注释以下代码
```java
<!-- 3.创建MapperFactoryBean类对象-->
<bean id="factoryBean" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.gzh.mapper.CustomerMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
```
2.在 applicationContext 中添加以下代码
```java
<!-- 4.基于MapperScannerConfigurer的整合-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.gzh.mapper"/>
</bean>
```
3.创建新的测试类
```java
@Test
public void findCustomerById1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerMapper bean = applicationContext.getBean(CustomerMapper.class);
Customer customerById = bean.findCustomerById(1);
System.out.println(customerById);
}
```
![image-20220427102429052](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220427102429052.png)

View File

@ -0,0 +1,191 @@
# 第十一章Spring MVC
第一个spring应用
## 0.创建项目,导包
```java
FirstController 类的包 实现HttpServletResponse HttpServletRequest两个方法
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
### 1.main->webapp->WEB-INF->web.xml文件中配置前端控制器
> DispatcherServlet:就是一个Servlet
>
> 配置前端控制器就是给DispatcherServlet配置一个访问的url
如何给一个java类配置访问它的url呢
```java
<servlet>
<servlet-name>逻辑名</servlet-name>
<servlet-class>Java类的全类名物理名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>逻辑名</servlet-name>
<url-pattern>url</url-pattern>
</servlet-mapping>
```
> 补充:
>
> Java Web中有一个概念Servlet:是什么本质就是Java类但是此类是通过url来访问的
```java
<servlet>
<servlet-name>apringmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>apringmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
```
### 2.创建控制器 FirstController
首先在 java 下创建包 com.gzh.controller ,然后创建 FirstController 类,实现接口选择 Controller 第一个
![image-20220430213958181](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430213958181.png)
```java
public class FirstController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","这是我的第一个Spring MVC程序");
modelAndView.setViewName("/WEB-INF/jsp/first.jsp");
return modelAndView;
}
}
```
### 3.创建first.jsp
在 WEB-INF 文件下创建 jsp 文件夹然后在下面创建一个名为 first 的 jsp 文件
然后在 body 标签中创建一个 `${msg}` 在上面的 FirstController 类中 `modelAndView.addObject("msg","这是我的第一个Spring MVC程序");`相对应
```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
```
### 4.在resources下创建springmvc-config.xml
```java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- name中 / 表示为根目录-->
<bean name="/firstController" class="com.gzh.controller.FirstController"/>
<!-- 处理器映射器 通过一个名字 将一个 url 和 java 类进行映射-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 适配器 去找控制器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 视图解析器 把 first.jsp 渲染到浏览器上-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
</beans>
```
## 5.在 Tomcat 服务器上部署项目
首先将 Tomcat 解压到盘符下然后在idea中添加 Tomcat
1首先点击 add Configurations 添加 Tomcat 服务器
2点击加号添加服务器
3选择 Tomcat 服务区 本地服务Local 本地 remote 远程服务)
![image-20220430215445248](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430215445248.png)
4点击配置服务器选择 Tomcat 服务器的主目录
![image-20220430215956914](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430215956914.png)
5点击部署点击添加服务选择工件Artifact
![image-20220430220220555](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430220220555.png)
6随便选择一个即可
![image-20220430220452741](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430220452741.png)
7最好将 应用程序上下文 改为项目名称
![image-20220430220832300](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430220832300.png)
8然后启用服务器就可以了
![image-20220430221340859](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430221340859.png)
## 6.项目部署
`http://localhost:8080/c11/firstController` 链接中能够看到实现的语句
![image-20220430221617115](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430221617115.png)
项目根目录:`http://localhost:8080/c11/`
在上面中的 `/` 表示 `http://localhost:8080/c11/`
`/firstController` 就代表 `http://localhost:8080/c11/firstController`
![image-20220430221939788](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220430221939788.png)
1用户通过客户端向服务器发送请求请求会被Spring MVC的前端控制器DispatcherServlet所拦截。
2DispatcherServlet拦截到请求后会调用HandlerMapping处理器映射器。
3处理器映射器根据请求URL找到具体的处理器生成处理器对象及处理器拦截器如果有则生成一并返回给DispatcherServlet。
4DispatcherServlet会通过返回信息选择合适的HandlerAdapter处理器适配器
5HandlerAdapter会调用并执行Handler处理器这里的处理器指的就是程序中编写的Controller类也被称之为后端控制器。
6Controller执行完成后会返回一个ModelAndView对象该对象中会包含视图名或包含模型和视图名。
7HandlerAdapter将ModelAndView对象返回给DispatcherServlet。
8DispatcherServlet会根据ModelAndView对象选择-个合适的ViewResolver视图解析器
9ViewResolver解析后会向DispatcherServlet中返回具体的View视图
10DispatcherServlet对View进行渲染即将模型数据填充至视图中
11视图渲染结果会返回给客户端浏览器显示。

View File

@ -0,0 +1,191 @@
# 第十二章Spring MVC 的核心类和注解
## 1.Spring MVC 配置文件的联众处理方式:
--是在 resources 文件夹下创建,此时需要在 web.xml 中通过 <init-param> 元素来加载配置文件
```java
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
```
--是在 WEB-INF 下创建 xxx-servlet.xml 此时不需要在web.xml文件中加载了也就是删掉 init-param 元素就可以。
```java
<!-- name中 / 表示为根目录-->
<bean name="/firstController" class="com.gzh.controller.FirstController"/>
<!-- 处理器映射器 通过一个名字 将一个 url 和 java 类进行映射-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 适配器 去找控制器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 视图解析器 把 first.jsp 渲染到浏览器上-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
```
xxx是什么
是 DispatcherServlet 的逻辑名,<servlet-name>中的文本。在这是指 springmvc
## 2.实现控制器的两种方式:
1.实现接口重写handleRequest方法
2.使用注解 @Controlleri 可以将 ]ava 类标注成控制器
使用注解 @RequestMapping 将url 映射到控制器的方法上
```java
@Controller
public class SecondController {
@RequestMapping("/second")
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","这是我的第一个Spring MVC程序");
modelAndView.setViewName("/WEB-INF/jsp/first.jsp");
return modelAndView;
}
}
```
然后在 WEB-INF 下创建 springmvc-servlet.xml 文件
```java
<context:component-scan base-package="com.gzh.controller"/>
```
然后重新部署即可
> 使用注解比实现接口 实现的控制器 先进:
> 实现接口的控制器因为只重写了一个方法,所以只能处理一个请求。
> 但是使用注解的控制器中可以定义多个方法,也就是可以处理多个请求。
## 3.基于注解的 Spring MVC 应用
### 1.创建项目导包spring-web spring-webmvc
```java
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
### 2.web.xml中配置前端控制器
```java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd
http://java.sun.com/xml/ns/javaee "
id="WebApp_ID" version="3.0">
<!--1.配置前端控制器:设置访问某类的url-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
```
### 3.使用注解的方式实现控制器
```java
@Controller
public class MyController {
@RequestMapping("/a")
public String a(){
return "/WEB-INF/jsp/a.jsp";
}
@RequestMapping("/b")
public String b(){
return "/WEB-INF/jsp/b.jsp";
}
@RequestMapping("/c")
public String c(){
return "/WEB-INF/jsp/c.jsp";
}
}
```
### 4.创建前端视图
在 webapp -> WEB-INF -> 下创建名为 jsp 的文件夹,在文件夹中创建 jsp 文件分别创建三个前端视图a.jsp b.jsp c.jsp
### 5.创建配置文件
在 WEB-INF 文件夹下创建名为 springmvc-servlet 的 xml 文件
```java
添加扫描注解
<context:component-scan base-package="com.gzh.controller"/>
```
### 6.在tomcat服务器上部署项目
![image-20220506092448960](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506092448960.png)
### 7.成功发布项目
![image-20220506093333560](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506093333560.png)
## 4.定义视图解析器(配置前后缀)
### 1.修改前端控制器
```java
@Controller
public class MyController {
@RequestMapping("/a")
public String a(){
return "a";
}
@RequestMapping("/b")
public String b(){
return "b";
}
@RequestMapping("/c")
public String c(){
return "c";
}
}
```
### 2.修改配置文件 springmvc-servlet.xml
```java
<context>下添加以下代码
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
```
### 3.重新发布项目
![image-20220506094644157](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506094644157.png)

View File

@ -0,0 +1,410 @@
# 第十三章:数据绑定
## 1.什么叫数据绑定
将请求消息数据 和 后台方法形参 建立连接的过程 就叫数据绑定。
请求消息数据:
可以通过url携带数据比如localhost:8080/c14/get?id=1
还可以通过表单提交数据
后台方法形参
控制器中方法的形参
根据后台方法形参的类型,将数据绑定分为:简单数据绑定,复杂数据绑定
## 2.简单数据绑定
### 1默认的数据类型
> HttpServletRequest:通过request对象获取请求信息。
>
> HttpServletResponse:通过response处理响应信息。
>
> HttpSession:通过session对象得到session中存储的对象。
>
> Model//ModelMap:Model是一个接口ModelMap是一个接口实现作用是将model数据填充到request域。
后台方法形参的默认的数据类型有4个以 HttpServletRequest 为例进行讲解
#### 1.创建项目,导包 spring-web spring-webmvc
```java
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
```
#### 2.web.xml 文件中配置前端控制器
```java
<!--1.配置前端控制器:设置访问某类的url-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
```
#### 3.在 resources 下创建 springmvc-config.xml
只创建文件
#### 4.创建控制器
```java
@Controller
public class UserController {
@RequestMapping("/selectUser")
public String selectUser(HttpServletRequest request) {
String id = request.getParameter("id");
System.out.println("id=" + id);
return "success";
}
}
```
#### 5.创建前端页面 success.jsp
在 WEB-INF 文件夹下面创建 jsp 文件夹,然后创建前端页面
```html
<body>
success
</body>
```
#### 6.解析注解和配置视图解析器
```java
<!--解释控制器中的注解-->
<context:component-scan base-package="com.gzh.controller"/>
<!--配置前端视图解析器 id可以不写不写等于class-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
```
#### 7.在 tomcat 服务器上部署项目,发布项目
![image-20220506220115521](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506220115521.png)
#### 7.测试 发送:
```java
http://localhost:8080/c15/selectUser?id=1
```
![image-20220506220059705](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506220059705.png)
### 2简单的数据类型 int double float string
#### 1.控制器:
```java
@RequestMapping(value = "/getUser")
public String getUser(int id) {
System.out.println("id=" + id);
return "success";
}
```
#### 2.测试 发送
```java
http://localhost:8080/c15/getUser?id=4
```
![image-20220506221558058](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506221558058.png)
### 注意:
**getuser()** 中的参数 **i** 要和后面的一致,在绑定时也要进行相应更改
![image-20220506222128788](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506222128788.png)
添加注解 **@RequestParam** 就可以将 **id** 参数的值绑定到 **a**
![image-20220506222455550](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506222455550.png)
### 3POJO plain old Java object
### 以用户注册为例:
#### 1.创建实体类User
```java
private Integer id;
private String username;
private String password;
实现 getter setter 和 toString 方法
```
#### 2.创建前端页面 register.jsp
```html
<body>
<form action="http://localhost:8080/c15/registerUser" method="post">
<%-- name 属性值 和 成员变量名 保持一致--%>
用户名:<input type="text" name="username"/>
密码:<input type="password" name="password"/>
<input type="submit" value="注册"/>
</form>
</body>
```
#### 3.控制器
```java
// 该方法是用来返回register.jsp页面
@RequestMapping("/toRegister")
public String toRegister() {
return "register";
}
// 该方法是用来处理数据的
@RequestMapping("/registerUser")
public String registerUser(User user) {
System.out.println(user.getUsername() + ":" + user.getPassword());
return "success";
}
```
#### 4.测试 发布
![image-20220506223113983](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506223113983.png)
在中文的情况下可能会发生乱码,所以添加编码过滤器,将所有文件用 utf-8 格式编码
在 WEB-INF 文件夹下的 web.xml 文件下的 前端控制器代码下 添加以下代码
```java
<!-- 配置编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```
测试 发布:中文不会产生乱码
![image-20220506223612935](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506223612935.png)
### 4包装的POJO类型
使用简单POO类型已经可以完成多数的数据绑定但有时客户端请求中传递的参数会比较复杂。例如在用户查询订单时页面传递的参数可能包括订单编号、用户名称等信息这就包含了订单和用户两个对象的信息。如果将订单和用户的所有查询条件都封装在一个简单POJO中显然会比较混乱这时就可以考虑使用包装POJO类型的数据绑定。
#### 1.在 com.gzh.domain 包下创建名为 Orders 的类
```java
private Integer ordersId;
private User user;
实现 getter 和 setter 方法
```
#### 2.在 com.gzh.controller 包下创建控制器类 OrdersController
编写一个跳转到订单查询页面的方法和一个查询订单及用户信息的方法
```java
@Controller
public class OrdersController {
@RequestMapping("/toFindOrdersWithUser")
public String toFindOrdersWithUser(){
return "orders";
}
@RequestMapping("/")
public String findOrdersWithUser(Orders orders){
Integer ordersId = orders.getOrdersId();
User user = orders.getUser();
String username = user.getUsername();
System.out.println("ordersId" + ordersId);
System.out.println("username" + username);
return "success";
}
}
```
#### 3.创建前端页面 orders.jsp
在 WEB-INF 文件夹下的 jsp 文件夹下,创建前端页面 orders.jsp
```html
<body>
<form action="http://localhost:8080/c15/findOrdersWithUser" method="post">
订单编号:<input type="text" name="ordersId" />
所属用户:<input type="text" name="user.username" />
<input type="submit" value="查询" />
</form>
</body>
```
#### 4.测试 发布
![image-20220507091032381](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220507091032381.png)
## 3.复杂的数据绑定
### 1绑定数组
#### 1.创建前端页面 user.jsp
```html
<body>
<form method="post" action="http://localhost:8080/c15/delect">
<table width="20%" border="1">
<tr>
<td>选择</td>
<td>用户名</td>
</tr>
<tr>
<td><input type="checkbox" name="ids" value="1"/></td>
<td>tom</td>
</tr>
<tr>
<td><input type="checkbox" name="ids" value="2"/></td>
<td>jack</td>
</tr>
</table>
<input type="submit" value="删除"/>
</form>
</body>
```
#### 2.编写批量删除用户的方法(同时添加一个向 user.jsp 页面跳转的方法)
```java
// 该方法是返回user.jsp的
@RequestMapping("/toUser")
public String toUser(){
return "user";
}
// 该方法是来处理user.jsp页面传递的数据
@RequestMapping("/delect")
public String delectUser(int[] ids){
if (ids != null){
for (int id : ids){
System.out.println("删除了id为"+id+"的用户");
}
}else {
System.out.println("数组ids为空");
}
return "success";
}
```
#### 3.测试 发布:
![image-20220506224513695](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506224513695.png)
![image-20220506224526191](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220506224526191.png)
### 2绑定集合
以批量修改用户为例:
#### 1.创建包装类 UsersVo
```java
private List<User> users;
实现 getter 和 setter 方法
```
#### 2.编写控制器方法
```java
@RequestMapping("/toUserEdit")
public String toUserEdit() {
return "user_edit";
}
@RequestMapping("/editUsers")
public String editUsers(UserVo userList) {
// 将所有用户数据封装到集合中
List<User> users = userList.getUsers();
// 循环输出信息
for (User user : users) {
// 如果接收的用户id不为空则表示对该用户进行了修改
if (user.getId() != null) {
System.out.println("修改了id为" + user.getId() + "的用户名为:" + user.getUsername());
}
}
return "success";
}
```
#### 3.编写前端页面 user_edit.jsp
```html
<body>
<form action="http://localhost:8080/c15/editUsers" method="post" id="formid">
<table width="30%" border="1">
<tr>
<td>选择</td>
<td>用户名</td>
</tr>
<tr>
<td>
<input name="users[0].id" value="1" type="checkbox"/>
</td>
<td>
<input name="users[0].username" value="tome" type="text"/>
</td>
</tr>
<tr>
<td>
<input name="users[1].id" value="2" type="checkbox"/>
</td>
<td>
<input name="users[1].username" value="jack" type="text"/>
</td>
</tr>
</table>
<input type="submit" value="修改"/>
</form>
</body>
```
#### 4.测试发布
![image-20220507121847120](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220507121847120.png)

View File

@ -0,0 +1,222 @@
# 第十四章JSON 数据和 RESTful 风格的 url
## 1.JSON: JavaSript Object Notation
> JSON数据的两种数据结构
>
> 1.对象结构
>
> 2.数组结构
## 2.第13章和第14章的区别
第13章发送ur1,请求控制器中的某个方法该方法返回jsp页面
第14章发送url,请求webapp下的jsp页面该页面中包含一个门S0N数据该数据会被传递到控制器中的某个方法上然后方法再将数据返回显示到浏览器中。
## 3.验证JS0N数据和Java类对象的转换
### 1.创建项目,导包:
```java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8</version>
</dependency>
```
### 2.web.xml文件
```java
<!-- 打开项目直接访问的页面-->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index1.jsp</welcome-file>
</welcome-file-list>
<!-- 配置前端控制器DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
```
### 3.springmvc-servlet.xml文件
```java
<!-- 定义组件扫描器:指定需要扫描的包-->
<context:component-scan base-package="com.gzh.controller"/>
<!-- 配置视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置 Spring MVC的注解驱动-->
<mvc:annotation-driven/>
<!-- 配置静态资源的访问映射,配置的文件,将不被前端控制器拦截-->
<mvc:resources mapping="/js/**" location="/js/"/>
```
### 4.创建实体类对象User
```java
package com.gzh.po;
private String username;
private String password;
通过 getter setter 和 toString 方法生成代码
```
### 5.在WEB-INF下创建 index.jsp
```html
<head>
<title>测试JSON交互</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.11.3.min.js">
</script>
<script type="text/javascript">
function testJson() {
var username = $("#username").val();
var password = $("#password").val();
$.ajax({
url: "${pageContext.request.contextPath}/testJson",
type: "post",
data: JSON.stringify({username: username, password: password}),
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (data) {
if (data != null) {
alert("您输入的用户名为" + data.username + "密码为" + data.password);
}
}
});
}
</script>
</head>
<body>
<form>
用户名<input type="text" name="username" id="username"><br>
密码<input type="password" name="password" id="password"><br>
<input type="button" value="测试JSON交互" onclick="testJson()">
</form>
</body>
```
### 6.导入文件 jquery-1.11.3.min.js
在webapp下创建文件夹 js 在文件夹下复制文件
![image-20220513233035481](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220513233035481.png)
### 7.创建UserController方法
```java
package com.gzh.controller;
@Controller
public class UserController {
@RequestMapping("/testJson")
@ResponseBody
public User testJson(@RequestBody User user){
System.out.println(user);
return user;
}
}
```
### 8.发布项目
![image-20220513231414012](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220513231414012.png)
## 4.RESTful支持
### 1.在 UserController 方法中添加查询方法
```java
/**
*接收RESTful风格的请求,其接收方式为GET
*/
@RequestMapping(value="/user/{id}",method= RequestMethod.GET)
@ResponseBody
public User selectUser(@PathVariable("id") String id){
//查看数据接收
System.out.println("id="+id);
User user=new User();
//模拟根据id查询出到用户对象数据
if(id.equals("1234")){
user.setUsername("tom");
}
//返回JSON格式的数据
return user;
}
```
### 2.编写页面文件 restful.jsp
```html
<head>
<title>RESTful测试</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery-1.11.3.min.js">
</script>
<script type="text/javascript">
function search(){
// 获取输入的查询编号
var id = $("#number").val();
$.ajax({
url : "${pageContext.request.contextPath }/user/"+id,
type : "GET",
//定义回调响应的数据格式为JSON字符串,该属性可以省略
dataType : "json",
//成功响应的结果
success : function(data){
if(data.username != null){
alert("您查询的用户是:"+data.username);
}else{
alert("没有找到id为:"+id+"的用户!");
}
}
});
}
</script>
</head>
<body>
<form>
编号:<input type="text" name="number" id="number">
<input type="button" value="搜索" onclick="search()" />
</form>
</body>
```
### 3.发布项目
![image-20220513232938453](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220513232938453.png)

View File

@ -0,0 +1 @@
![](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220512145028013.png)

View File

@ -0,0 +1,282 @@
# 第十六章:文件上传和下载
## 1.文件上传
### 1.创建项目,导包
```java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
```
### 2.web.xml
```java
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
```
### 3.springmvc-config.xml
```java
<!-- 定义组件扫描器,指定需要扫描的包 -->
<context:component-scan base-package="com.gzh.controller" />
<!--配置注解驱动 -->
<mvc:annotation-driven />
<!-- 定义视图解析器 -->
<bean id="viewResolver" class=
"org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 设置前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 设置后缀 -->
<property name="suffix" value=".jsp" />
</bean>
<!-- 配置文件上传解析器 MultipartResolver -->
<bean id="multipartResolver" class=
"org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置请求编码格式-->
<property name="defaultEncoding" value="UTF-8" />
</bean>
```
### 4.创建fileUpload.jsp
webapp下的jsp文件可以通过url直接访问
而WEB-INF下的js文件需要控制器中的方法返回才可以访问到
```html
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>Title</title>
<script>
function check() {
var name=document.getElementById("name").value
var file=document.getElementById("file").value
if(name==""){
alert("填写上传人");
return false;
}
if(file.length==0 || file==""){
alert("请选择上传文件")
return false;
}
return true;
}
</script>
</head>
<body>
<form action="${pageContext.request.contextPath}/fileUpload" method="post" enctype="multipart/form-data" onsubmit="return check()">
上传人:<input type="text" id="name" name="name"/>
请选择文件:<input type="file" id="file" name="uploadfile" multiple="multiple"/>
<input type="submit" value="上传"/>
</form>
</body>
```
### 5.创建success.jsp error.jsp
```html
<body>
上传失败
</body>
```
```html
<body>
上传成功
</body>
```
![image-20220517103654553](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220517103654553.png)
### 6.创建控制器
```java
package com.gzh.controller;
/**
* 文件上传
*/
@Controller
public class FileUploadController {
/**
* 执行文件上传
*/
@RequestMapping("/fileUpload")
public String handleFormUpload(@RequestParam("name") String name,
@RequestParam("uploadfile") List<MultipartFile> uploadfile,
HttpServletRequest request) {
// 判断所上传文件是否存在
if (!uploadfile.isEmpty() && uploadfile.size() > 0) {
//循环输出上传的文件
for (MultipartFile file : uploadfile) {
// 获取上传文件的原始名称
String originalFilename = file.getOriginalFilename();
// 设置上传文件的保存地址目录
String dirPath =
request.getSession().getServletContext().getRealPath("/upload/");
File filePath = new File(dirPath);
// 如果保存文件的地址不存在,就先创建目录
if (!filePath.exists()) {
filePath.mkdirs();
}
// 使用UUID重新命名上传的文件名称(上传人_uuid_原始文件名称)
String newFilename = name + "_" + UUID.randomUUID() +
"_" + originalFilename;
try {
// 使用MultipartFile接口的方法完成文件上传到指定位置
file.transferTo(new File(dirPath + newFilename));
} catch (Exception e) {
e.printStackTrace();
return "error";
}
}
// 跳转到成功页面
return "success";
} else {
return "error";
}
}
}
```
### 7.发布项目
![image-20220517105222969](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220517105222969.png)
![image-20220517105211357](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220517105211357.png)
![image-20220517105334825](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220517105334825.png)
## 2.文件下载
### 1.创建download.jsp
```html
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>下载页面</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/download?filename=1.jpg">
文件下载
</a>
<a href="${pageContext.request.contextPath }/download?filename=<%=URLEncoder.encode("壁纸.jpg", "UTF-8")%>">
中文名称文件下载
</a>
</body>
```
### 2.添加控制器
下载文件的名字会产生乱码
```java
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) throws Exception {
// 指定要下载的文件所在路径
String path = request.getSession().getServletContext().getRealPath("/upload/");
// 创建该文件对象
File file = new File(path + File.separator + filename);
// 设置响应头
HttpHeaders headers = new HttpHeaders();
// 通知浏览器以下载的方式打开文件
headers.setContentDispositionFormData("attachment", filename);
// 定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 使用Sring MVC框架的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
headers, HttpStatus.OK);
}
```
能保证下载的文件中文名字
```java
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) throws Exception {
// 指定要下载的文件所在路径
String path = request.getSession().getServletContext().getRealPath("/upload/");
// 创建该文件对象
File file = new File(path + File.separator + filename);
// 对文件名编码,防止中文文件乱码
filename = this.getFilename(request, filename);
// 设置响应头
HttpHeaders headers = new HttpHeaders();
// 通知浏览器以下载的方式打开文件
headers.setContentDispositionFormData("attachment", filename);
// 定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 使用Sring MVC框架的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
headers, HttpStatus.OK);
}
/**
* 根据浏览器的不同进行编码设置,返回编码后的文件名
*/
public String getFilename(HttpServletRequest request,String filename) throws Exception {
// IE不同版本User-Agent中出现的关键词
String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
// 获取请求头代理信息
String userAgent = request.getHeader("User-Agent");
for (String keyWord : IEBrowserKeyWords) {
if (userAgent.contains(keyWord)) {
//IE内核浏览器统一为UTF-8编码显示
return URLEncoder.encode(filename, "UTF-8");
}
}
//火狐等其它浏览器统一为ISO-8859-1编码显示
return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
}
```
### 3.发布项目
用第一个控制器,下载的文件不是中文名称
![image-20220517112749837](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220517112749837.png)
用第二个控制器,下载的文件是中文名称
![image-20220517113013424](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220517113013424.png)

View File

@ -0,0 +1,54 @@
## SpringBoot之项目文件作用
下面是一张SpringBoot的项目文件图其中项目是由`.mvn`、`src`、`target` 文件夹和`.getignore`、`HELP.md`、`mvnw`、`mvnw.cmd`、`pom.xml`、`untitled.iml`组成。(此项目是包含四个模块,模块均相同,不影响文件功能)
![image-20230301205134729](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20230301205134729.png)
### 1、.mvn
`.mvn`是Spring Boot 生成,用于一键通过 **Maven**构建、编译、打包和部署的文件目录。内部结构如下:
![image-20230301205529767](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20230301205529767.png)
### 2、src
![image-20230301205636397](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20230301205636397.png)
```
├── main
│ ├── java
│ │ └── com.yv --- package包名
│ └── resources --- 资源目录
│ ├── static --- 静态资源、js、css等
│ ├── templates --- html前端页面文件等
│ └── application.properites --- spring的配置文件
└── test --- 单元测试所在的目录
```
### 3、target
应用构建时生成,主要存放了源代码编译后的 class 文件,相关的配置文件以及打好的包文件等用于实际执行的文件。
![image-20230301210547502](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20230301210547502.png)
### 4、.getignore
`.gitignore`文件用来忽略被指定的文件或文件夹的改动,被记录在`.gitignore`文件里的文件或文件夹是无法被git跟踪到的即被忽略的文件是不会被放入到远程仓库里的。如果文件已经存在于远程仓库中是无法通过`.gitignore`文件来忽略的。
### 5、HELP.md
项目的帮助文档,比如可以写一些项目架构的说明等内容,删除对项目运行没有影响。
### 6、mvnw和mvnw.cmd
`mvnw`和`mvnw.cmd`有相同的职责,引导.mvn/wrapper/maven-wrapper.jar下载Maven二进制文件mvnw用于Linux系统mvnw.cmd用于Windows系统
### 7、pom.xml
maven的配置文件我们需要依赖的jar包都在这里面配置并下载使用。
### 8、untitled.iml
iml(infomation of module)也就是模块信息。它是我们项目的配置文件存储一些模块配置信息比如Maven组件、模块路径信息。

View File

@ -0,0 +1,65 @@
Spring整合JUnit的制作方式
```java
//加载spring整合junit专用的类运行器
@RunWith(SpringJUnit4ClassRunner.class)
//指定对应的配置信息
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTestCase {
//注入你要测试的对象
@Autowired
private AccountService accountService;
@Test
public void testGetById(){
//执行要测试的对象对应的方法
System.out.println(accountService.findById(2));
}
}
```
Spring整合Mybatis的制作方式yml格式
```yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?useSSL=false
username: root
password: 8520
```
实体类
```JAVA
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}
```
映射接口Dao
```JAVA
@Mapper
public interface BookDao {
@Select("select * from tbl_book where id = #{id}")
public Book getById(Integer id);
}
```
测试类
```JAVA
@SpringBootTest
class Springboot05MybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
System.out.println(bookDao.getById(1));
}
}
```

View File

@ -0,0 +1,60 @@
## 1.整合MyBatis-Plus
1.导入starter
```xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
```
2.配置数据源相关信息
```yaml
#2.配置相关信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: root
```
3.前数据库的表名定义规则是tbl_模块名称为了能和实体类相对应需要做一个配置相关知识各位小伙伴可以到MyBatisPlus课程中去学习此处仅给出解决方案。配置application.yml文件添加如下配置即可设置所有表名的通用前缀名
```yaml
mybatis-plus:
global-config:
db-config:
#设置所有表的通用前缀名称为tbl_
table-prefix: tbl_
```
## 2.整合Druid
1.导入对应的starter
```XML
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
</dependencies>
```
2.修改配置
```YAML
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
```

View File

@ -0,0 +1,94 @@
---
title: Mybaits连接MySQL8.0版本的配置
date: 2022-04-13 00:15:50.985
updated: 2022-09-05 00:15:50.985
url: https://hhdxw.top/archives/36
categories:
- JAVA EE
tags:
- JAVA EE
---
# Mybaits连接MySQL8.0版本的配置问题
## 特别要注意 properties 文件中不能有**任何**错误,以及空格
## 1.更改 maven 文件
```java
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
```
## 2.修改 Maven 配置文件
mysql 8.0 以后的版本驱动为
```java
com.mysql.cj.jdbc.Dirver
```
url 一般为
```java
jdbc:mysql://localhost:3306/mybatis
```
如果不能用的话,添加以下代码
```java
?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&nullCatalogMeansCurrent = true
```
来添加编码集
## 3.使用 xml 配置方式
```java
<environments default="mysql">
<!-- 配置mysql环境-->
<environment id="mysql">
<!-- 配置事务-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT&amp;nullCatalogMeansCurrent = true"/>
<property name="username" value="root"/>
<property name="password" value="8520"/>
</dataSource>
</environment>
</environments>
```
## 4.使用的是 properties 文件的配置方式
```java
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&nullCatalogMeansCurrent = true
jdbc.username=root
jdbc.password=8520
```
```java
<properties resource="db.properties"/>
<!-- 配置环境-->
<environments default="mysql">
<!-- 配置mysql环境-->
<environment id="mysql">
<!-- 配置事务-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
```

View File

@ -0,0 +1,30 @@
---
title: Resource注解无法导入依赖使用
date: 2022-03-15 00:15:53.726
updated: 2022-09-05 00:15:53.726
url: https://hhdxw.top/archives/40
categories:
- JAVA EE
tags:
- JAVA EE
---
最近在学习Spring的过程中遇到了一个棘手的问题使用Resource注解时报错了。
![image-20220315214739187](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315214739187.png)
当时上面的**@Resource**爆红,忘了截图
问题出现了那么怎么解决呢。在百度上找到答案说这是因为没有导入tomcat的包,tomcat里面默认继承了这个包,只要在**pom.xml**增加这个包的依赖,问题就解决了
```java
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
```
![image-20220315215743445](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315215743445.png)
但是我用了这个方法没有用,依旧爆红,后来我换了**JDK**从16171.61.8,在最后**JDK9**能用了

View File

@ -0,0 +1,57 @@
# 关于jdbc连接mysql URL上的常见问题
## 编码问题
在url ?的后面添加如下参数:
```xml
useUnicode=true&amp;characterEncoding=UTF-8
```
## 时区问题
在url ? 的后面添加如下参数
```xml
serverTimezone=UTC
```
```xml
serverTimezone=Asia/Shanghai
```
使用上海的时区也可以使用Hongkong的时区
具体时区可以去/usr/share/zoneinfo里查询。
```xml
serverTimezone=GMT%2B8
```
表示设置MySQL服务器的时区为GMT+8即东八区。
## 零值日期
在url ? 的后面添加如下的参数,会把零值日期转换为 null 值。
```xml
zeroDateTimeBehavior = convertToNull
```
## 密钥问题
在url ? 的后面添加如下的参数,允许从服务器检索公钥以进行密码验证。
```
allowPublicKeyRetrieval=true
```
## SSL协议问题
在url ? 的后面添加如下的参数表示不使用SSL协议进行加密连接。
```xml
useSSL=false
```
##### *注意:参数间使用 & 连接*

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
# ubuntu改中文教程以ubuntu-21.04为例
1.首先进入系统在右上角选择Settings进入设置带setting就是设置
![image-20220316180407286](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316180407286.png)
2.打开 setting 后找到左侧下面的 Language 点击进入后,打开右侧下方 Manage Installed Languages 进入语言添加设置
![image-20220316180503486](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316180503486.png)
3.中途可能让你输入密码,输入密码回车即可
![image-20220316180631585](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316180631585.png)
4.选择下面的 Install/Remove Languages 进入添加语言
![image-20220316180947776](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316180947776.png)
5.选择 Chinese simplified中文简体打上对勾然后点击Apply添加
![image-20220316181016486](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181016486.png)
6.这个过程需要等待,安装可能会失败,重复上面的步骤
![image-20220316181104889](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181104889.png)
7.成功安装后会在上面的灰色栏内有显示需要滚动鼠标往下找
![image-20220316181138956](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181138956.png)
8.然后将中文提到最上面长按托拽点击Close退出
![image-20220316181211560](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181211560.png)
9.下面分别是语言设置,格式设置和输入法 三个依次进行更改
![image-20220316181259764](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181259764.png)
10.首先进入 Language 修改语言,选择 Chinese 然后Select 退出
![image-20220316181334616](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181334616.png)
11.然后进入Formats设置格式选择China然后Done退出
![image-20220316181409005](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181409005.png)
12.然后Restart重新启动系统
![image-20220316181715178](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181715178.png)
13.重启完后选择输入法更改,点击下面的加号(此时已经是中文界面了),点击汉语
![image-20220316181858083](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181858083.png)
14.点击智能拼音,点击添加即可完成操作
![image-20220316181920047](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181920047.png)
15.长按拖拽汉语放到第一个位置
![image-20220316181953722](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316181953722.png)
16.然后Ubuntu的中文设置已经做完了
![image-20220316182042553](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316182042553.png)
以上就是Ubuntu改中文操作教程

View File

@ -0,0 +1,148 @@
# VMware 16PRO虚拟机以及 Ubuntu 系统配置
文件下载链接在文章最后
1.下载三个文件 VMware 16 PRO的安装包、激活码和 Ubuntu.iso 文件,解压后如图
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4930.tmp.jpg)
2.双击安装VMware
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4940.tmp.jpg)
3.点击勾选协议,然后进行下一步操作
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4941.tmp.jpg)
4.点击安装位置后面的更改,进行更改安装路径
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4942.tmp.jpg)
5.将安装路径改到 C 盘以外,防止 C 盘爆红,切记文件夹尽量用全**英文**或者**拼音**,不要用中文容易报错
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4943.tmp.jpg)
6.选择文件夹进行安装,然后确定
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4944.tmp.jpg)
7.取消勾选启用更新和提升计划,然后下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4945.tmp.jpg)
8.创建桌面图标,然后下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4946.tmp.jpg)
9.然后进行安装
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4947.tmp.jpg)
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4948.tmp.jpg)
10.安装完成,选择许可证
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4949.tmp.jpg)
11.然后打开激活密钥文件,三行选一个就行,复制粘贴点击输入
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps494A.tmp.jpg)
12.激活成功
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps494B.tmp.jpg)
13.双击桌面图标打开VMware
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps494C.tmp.jpg)
14.点击帮助框下面关于,检查是否完成激活
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps494D.tmp.jpg)
15.显示永久激活 VMware 完成配置以及激活
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps494E.tmp.jpg)
16.下面开始配置 Ubuntu 系统配置
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps495F.tmp.jpg)
17.选择自定义设置
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4960.tmp.jpg)
18.默认选择硬件,直接下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4961.tmp.jpg)
19.将下载的iso文件放到C盘以外的英文路径文件夹下
![image-20220316155220558](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316155220558.png)
![image-20220316155251010](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316155251010.png)
如上图即完成
安装 Ubuntu 系统,选择安装光盘映像文件(路径尽量为**英文**
![image-20220316155420508](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316155420508.png)
如下图即完成选择
![image-20220316155452680](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220316155452680.png)
20.设置 linux 系统全名,以及用户名和密码(用户名和密码以简单为主,要牢记)
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4963.tmp.jpg)
21.安装虚拟机路径(不要在 **C 盘**,路径尽量为**英文**),然后下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4964.tmp.jpg)
22.默认配置处理器数量,然后下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4965.tmp.jpg)
23.内存一般配置默认(不能超过电脑自身内存的一半)
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4966.tmp.jpg)
24.网络连接类型默认选项,下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4967.tmp.jpg)
25.虚拟磁盘类型默认选项,下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4968.tmp.jpg)
26.磁盘类型默认选项,下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4969.tmp.jpg)
27.创建磁盘方式默认选项,下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps496A.tmp.jpg)
28.磁盘容量默认选项,下一步(要保证自己电脑的磁盘容量大于虚拟机磁盘容量)
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps496B.tmp.jpg)
29.默认选项,下一步
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps496C.tmp.jpg)
30.虚拟机配置总览,点击完成,进行安装
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps496D.tmp.jpg)
31.等待系统安装完成即可,部分电脑安装时间可能比较长,耐心等待即可
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps496E.tmp.jpg)
以上就是VMware 16PRO虚拟机破解安装以及 Ubuntu 系统配置如有其他问题可以QQ私我解决
链接链接https://share.weiyun.com/w0XsEUe9

570
Pychrm/py_基础知识.md Normal file
View File

@ -0,0 +1,570 @@
[TOC]
## python基础
## 1.pip
### 1.1 使用pip管理Python包
```
pip install <包名> 安装指定的包
pip uninstall <包名> 删除指定的包
pip list 显示已经安装的包
pip freeze 显示已经安装的包,并且以指定的格式显示
```
### 1.2 修改pip下载载源
运行pip install 命令会从网站上下载指定的python包默认是从 https://files.pythonhosted.org/ 网站上下
载。这是个国外的网站遇到网络情况不好的时候可能会下载失败我们可以通过命令修改pip现在软件时的
源。 格式:
pip install 包名 -i 国内源地址
示例: pip install ipython -i https://pypi.mirrors.ustc.edu.cn/simple/ 就是从中国科技大学(ustc)的服务器
上下载requests(基于python的第三方web框架)
国内常用的pip下载源列表:
阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
### 1.3 退出python环境
exit()
ctrl + z ==>enter
### 1.4 注释
1.一般注释要写到代码上面。(很少情况写到代码后面)
```python
#单行注释
# CTRL+ ? 或 shift + 3
#一般情况下注释要写到代码上面
print('你是我的宝贝')
#多行注释
'''
你是我的宝贝
print('你是我的宝贝')
'''
```
## 2. 变量的定义以及类型
### 2.1 变量的定义
```python
# 重复的值修改很麻烦
print('你是我的宝贝')
print('你是我的宝贝')
print('你是我的宝贝')
print('你是我的宝贝')
# 定义为变量,便于修改赋值
shuzhi = '你是我的宝贝'
print(shuzhi)
print(shuzhi)
print(shuzhi)
```
![image-20211226143711623](https://gitee.com/hhdxw/tuc/raw/master/img/image-20211226143711623.png)
### 2.2 数据类型
https://www.zhixi.com/view/125e9881
![image-20211226134510431](https://gitee.com/hhdxw/tuc/raw/master/img/image-20211226134510431.png)
| 数据类型 | |
| :------: | :------: |
| int | 整型 |
| float | 长整型 |
| boolean | 布尔型 |
| string | 字符串型 |
| list | 列表 |
| tuple | 元组 |
| dict | 字典 |
1.int
```python
money = 5000
print(money)
```
2.float
```python
money2 = 3.87
print(money2)
```
3.boolean
```python
# 1.流程控制语句
# 2.性别的控制(在实际企业开发中使用的单词 sex gender
# 基本开发中 True 是男False是女
sex = True
sex2 = False
print(sex)
print(sex2)
```
4.string
```python
# 字符串 使用的是 单引号 或者是 双引号 (英文的)
s = '你是我的宝贝'
s2 = "你不是的宝贝"
print(s)
print(s2)
# 不能单双混着写,屌丝写法
# 也不能 双双引号 或者 双单引号的嵌套
s3 = "'你是我的宝贝'"
s4 = '"你是我的宝贝"'
print(s3)
print(s4)
```
5.list
```python
# 应用场景:当获取到很多数据时,可以存储到列表中,然后直接访问。
name_list = ['王','赵']
print(name_list)
```
6.tuple
```python
age_tuple = (0,2,3)
print(age_tuple)
```
7.dict
```python
# 应用场景scrapy框架常用
# 格式:变量名字 = {key:value,key1:value2}
person = {'name':'红浪漫','age':18}
print(person)
```
### 2.3 数据类型的查询
在python中只要定义了一个变量而且它有数据那么它的类型就已经确定了不需要开发者主动的 去说明它的类型,系统会自动辨别。也就是说在使用的时候 变量没有类型,数据才有类型。
```python
# 常用数据类型
# int
# float
# boolean
# string
# list
# tuple
# dict
a = 1
print(a)
print(type(a))
b = 2.12
print(b)
print(type(b))
c = True
print(c)
print(type(c))
d = '中国'
print(d)
print(type(d))
e = [1,2,3,4]
print(e)
print(type(e))
f = (1,2,3,4)
print(f)
print(type(f))
g = {'name':'张三','age':'18'}
print(g)
print(type(g))
```
![image-20211226180652499](https://gitee.com/hhdxw/tuc/raw/master/img/image-20211226180652499.png)
## 3. 标识符和关键字
### 3.1命名规范
计算机编程语言中,标识符是用户编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与 使用之间的关系。
1. 标识符由字母、下划线和数字组成,且数字不能开头。
2. 严格区分大小写。
3. 不能使用关键字。
```python
关键字:
False None True and as assert break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield
```
### 3.2 命名规范
驼峰原则
大驼峰userName常用 第一个单词以小写字母开始;第二个单词的首字母大写
小驼峰UserName 每一个单字的首字母都采用大写字母
下划线: user_name 用下划线将单词相连
## 4. 类型转换
| 函数 | 说明 |
| :------: | :-----------------: |
| int(x) | 将x对象转换为整型 |
| float(x) | 将x对象转换为浮点 |
| str(x) | 将x对象转换为字符串 |
| bool(x) | 将x对象转换为布尔值 |
1.转换为整型
```python
# str --> int
a = '123'
print(type(a))
b = int(a)
# float --> int
# 如果我们将float转为整数 那么会返回的是小数点前面的数据
c = 1.63
d = int(c)
# boolean --> int
# 强制类型转换为谁 就写什么方法
# True ---> 1 False ---> 0
a = False
b = int(a)
```
![image-20211226210240692](https://gitee.com/hhdxw/tuc/raw/master/img/image-20211226210240692.png)
2.转换为浮点型
```python
# 在爬虫时获取的数据大部分是字符串类型,部分数据需要转换为浮点型,例如价格,数量等。
# string --> float
a = '12.34'
b = float(a)
#int -->float
c = 666
d = float(c)
```
![image-20211226205649057](https://gitee.com/hhdxw/tuc/raw/master/img/image-20211226205649057.png)
3.转换为字符串型
```python
#int -->string
a = 80
b = str(a)
# float --> string
a = 12.32
b = str(a)
# bool --> string
a = True
b = str(a)
```
![image-20211226211031791](https://gitee.com/hhdxw/tuc/raw/master/img/image-20211226211031791.png)
4.转换为布尔类型
```python
# int --> bool
# 非零整数转换为bool 0为 False, 其他为True
a = 1
a = -1
a = 0
#float --> bool
# 非零数转换为bool 0为 False, 其他为True
a = 0.0
a = -1.34
a = 1.54
#string --> bool
#非空包括空格返回True空返回False
a = ''
a = ' '
a = '你是我宝贝'
#liat --> bool(列表)
#非空包括空格返回True空返回False (同string)
#tuple --> bool(元组)
#非空包括空格返回True空返回False (同string)
#dict --> bool(字典)
#非空包括空格返回True空返回False (同string)
```
## 5. 运算符
### 5.1 算数运算符
| 运算符 | 描述 | 实例 |
| ------ | ------ | ------------ |
| + | 加 | |
| - | 减 | |
| * | 乘 | |
| / | 除 | 5/2结果为2.5 |
| // | 取证 | 9//2 结果为4 |
| % | 取余 | 9%2结果为1 |
| ** | 指数 | a的b次幂 |
| () | 小括号 | 运算级别 |
优先级 ** 高于 */ % // 高于 + -
```python
#特殊类型
#在python中 + 两端只能是同种类型
#在python中 * 可以重复文本(文本*数量)
```
### 5.2 赋值运算符
```python
# 单个变量赋值
num = 10
# 同时为多个变量赋值(使用等号连接)
a = b = 4
# 多个变量赋值(使用逗号分隔)
num1, f1, str1 = 100, 3.14, "hello"
```
### 5.3 复合赋值运算符
| 运算符 | 描述 | 实例 |
| :----: | :------------: | :---------------------: |
| += | 加法赋值运算符 | c+=a 等效于 c=c+a |
| -= | 减法赋值运算符 | c-=a 等效于 c=c-a |
| *= | 乘法赋值运算符 | c*a 等效于 c=c*a |
| /= | 除法赋值运算符 | c/=a 等效于 c=c/a |
| //= | 取整赋值运算符 | c//=a 等效于 c=c//a |
| %= | 取模赋值运算符 | c%a 等效于 c=c%a |
| **= | 幂赋值运算符 | c**a 等效于 c=c**a |
### 5.4 比较运算符
| 运算符 | 描述 | 实例 |
| :----: | :---------------------------: | :-----------------: |
| == | 等于:比较对象是否相等 | (a == b) 返回 False |
| != | 不等于:比较两个对象是否不相等 | (a != b) 返回 True |
| > | 大于:返回x是否大于y | (a > b) 返回 False |
| \>= | 大于等于:返回x是否大于等于y | (a >= b) 返回 False |
| < | 小于:返回x是否小于y | (a < b) 返回 True |
| <= | 小于等于:返回x是否小于等于y | (a <= b) 返回 True |
### 5.5 逻辑运算符
| 运算符 | 逻辑表达式 | 描述 | 实例 |
| :----: | :---------: | :-------------------------------------: | :------------------------------: |
| and | x and y | 只要有一个运算数是False结果就是False; | True and True and False--> False |
| or | a or y | 只要有一个运算数是True结果就是True; | False or False or True-->True |
| not | not x | 取反 | not True --> False |
## 6. 输入输出
### 6.1 输出
```python
pirnt("我今年10岁")
pirnt("我今年11岁")
age = 10
print("我今年%d岁" % age)
age = 18
name = "红浪漫晶哥"
print("我的姓名是%s, 年龄是%d" % (name, age))
```
### 6.2 输入
```python
password = input("请输入密码:")
print('您刚刚输入的密码是:%s' % password)
```
注意事项:
input()的小括号中放入的是提示信息,用来在获取数据之前给用户的一个简单提示
input()在从键盘获取了数据以后,会存放到等号右边的变量中
input()会把用户输入的任何值都作为字符串来对待
## 7. 流程控制语句
### 7.1 if判断语句
```python
age = 30
if age >= 18:
print("我已经成年了")
```
注意代码的缩进为一个tab键或者4个空格
### 7.2 if else
```python
if
条件: 满足条件时的操作
else:
不满足条件时的操作
age = 18
if age >= 18:
print("我可以去红浪漫了")
else:
print("未成年,不允许去"
```
### 7.3 elif
```python
if xxx1:
事情1
elif xxx2:
事情2
elif xxx3:
事情3
score = 77
if score>=90:
print('本次考试等级为A')
elif score>=80:
print('本次考试等级为B')
elif score>=70:
print('本次考试等级为C')
elif score>=60:
print('本次考试等级为D')
elif score<60:
print('本次考试等级为E')
```
### 7.4 for循环
```python
for 临时变量 in 列表或者字符串等可迭代对象:
循环满足条件时执行的代码
for s in "hello":
print(s)
for i in range(5):
print(i)
```
### 7.5 range
```python
range(开始值,终止值,步长) //左闭右开区间
for x in range(2, 10, 3):
print(x)
```
## 8. 数据类型高级
### 8.1 字符串高级
| | | |
| :-----------------: | :----------: | :----------------------------------------------------------: |
| len | 获取长度 | len函数可以获取字符串的长度。 |
| find | 查找内容 | 查找指定内容在字符串中是否存在,如果存在就返回该内容在字符串中第一次 出现的开始位置索引值,如果不存在,则返回-1. |
| startswith,endswith | 判断 | 判断字符串是不是以谁谁谁开头/结尾 |
| count | 计算出现次数 | 返回 str在start和end之间 在 mystr里面出现的次数 |
| replace | 替换内容 | 替换字符串中指定的内容如果指定次数count则替换不会超过count次 |
| split | 切割字符串 | 通过参数的内容切割字符串 |
| upper,lower | 修改大小写 | 将字符串中的大小写互换 |
| strip | 空格处理 | 去空格 |
| join | 字符串拼接 | 字符串拼接 |
### 8.2列表高级
列表增删改查
| | |
| :----: | :----------------: |
| append | 在末尾添加元素 |
| insert | 在指定位置插入元素 |
| extend | 合并两个列表 |
**append** append会把新元素添加到列表末尾
```python
#定义变量A默认有3个元素
A = ['xiaoWang','xiaoZhang','xiaoHua']
print("添加之前列表A的数据A=%s" % A)
#提示、并添加元素
temp = input('请输入要添加的学生姓名:')
A.append(temp)
print("添加之后列表A的数据A=%s" % A)
```
**insert** insert(index, object) 在指定位置index前插入元素object
```python
#[0,1,2,3]
strs = ['a','b','m','s']
strs.insert(3,'h')
print(strs)
# ['a', 'b', 'm', 'h', 's']
```
**extend** 通过extend可以将另一个列表中的元素逐一添加到列表中
```python
a = ['a','b','c']
b = ['d','e','f']
a.extend(b)
print(a) # ['a', 'b', 'c', 'd', 'e', 'f'] 将 b 添加到 a 里
print(b) # ['d','e','f'] b的内容不变
```

115
TCP概述.md Normal file
View File

@ -0,0 +1,115 @@
面向连接的运输层协议应用程序在使用TCP协议之前必须先建立TCP连接数据传输完毕后必须释放已建立的TCP连接
点对点TCP连接只能有两个端点一对一
可靠通过TCP连接传输的数据无差错、不丢失、不重复、按需到达
全双工通信:连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据
面向字节流:数据通过自己序列发送,发送和接收的字节流顺序必须完全一致
TCP报文段的首部格式
源端口和目的端口各占2个字节
序号占4字节范围是02的32次方减1TCP在传输过字节流的每一个字节都按顺序编号编号循环使用
确认号占4字节期望收到对方下一个报文的数据字节的序号
数据偏移占4位标记报文段的数据起始处距离报文段的起始处的距离
保留占6位
紧急URG当URG为1时表明紧急指针字段有效它告诉接收方此报文段有紧急数据必须优先接收此时该报文不再需需要按照原定的顺序排队直接插入到本报文数据的最前面优先处理比如Control + C命令
确认ACKTCP规定在连接建立后所有传送的报文段都必须把ACK置为1
推送PUSH当输出某些指令后立即需要收到对方响应在这种情况下TCP就可以使用push操作发送方把PUSH置为1并立即创建一个报文发送出去接收方收到PUSH为1的报文段时就立即将缓冲区的报文交付给应用进程而不再等到整个缓冲区都填满后再向上交付
复位RST当RST为1时表明TCP连接中出现严重差错必须释放连接重新建立连接可用于拒绝非法报文或非法连接
同步SYN 在建立连接时用来同步序列号当SYN=1而ACK=0时表明建立连接请求若对方同意建立连接则应该在响应的报文段中使用SYN=1和ACK=1
终止FIN用来释放连接当FIN=1时表示此报文发送方的数据已经发送完毕请求释放TCP连接
窗口占2个字节窗口值作为接收方让发送方设置其发送窗口的依据可靠传输和流量控制都依赖窗口实现后面详细说
检验和计算检验和时要在TCP报文段前面加上伟首部用来检验传输数据是否有错
紧急指针占2个字节在URG=1时才有意义标记紧急报文中的紧急数据的字节数紧急数据结束后就是普通数据。
选项规定每个报文段中的数据字段的最大长度MSS一般在建立连接时双方将自己能够支持的MSS写入选项中以后就按照这个数据传输数据。
数据
报文段首部格式一定要记住,至少要大概理解后,再带着疑问去看下边,否则看下边有可能会一脸懵逼。
TCP可靠传输的实现
TCP的可靠传输通过滑动窗口实现滑动窗口以字节为单位。凡是已发送过的数据在未收到确认之前都必须暂时保留以便在超时重传时使用窗口越大发送方就可以在收到对方确认之前连续发送更多的数据获得更高的传输速率。滑动窗口可以分为四部分
已发送并搜到确认
已发送未收到确认
允许发送但尚未发送
不允许发送
窗口依赖三个指针P1P2和P3小于1的是已经发送并收到确认的字节1和2之间的是已发送但未收到确认的字节2和3之间是允许发送但尚未发送但字节大于3为不允许发送的字节1和3之间的字节数即为接收方规定的滑动窗口大小流量控制。接收方B只能对按需收到的最高序号给出确认当指针2和指针3重合时发送方必须停止发送数据等待接收方的确认为了保证可靠传输A必须等到B的确认才能继续发送数据为了保证发送方不会一直等待到达依赖超时计时器动态计算超时重传时间规定的时间后就重传这部分数据直到收到接收方B的确认。
超时重传时间的选择采用一个自适应算法它会记录一个报文段发出的时间以及收到响应的确认的时间作为往返时间RTT计算为加权平均往返时间RTTsRTTd为RTT的偏差的加权平均值通过这几个值计算得到超时重传时间RTO。计算的规则是报文段每重传一次就把超时重传时间RTO增大一些当不再发生报文段的重传时根据下面公式计算RTO。
RTO = RTTs + 4 * RTTd
TCP的流量控制
流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收,利用滑动窗口实现。发送方的发送窗口不能超过接收方给出的接收窗口大小。当接收方接收能力下降时,会缩小自己的接收窗口,发送方通过报文头部的串口字段告知发送方。
还以上面发送方为A接收方为B作为例子当B的接收缓存满之后将自己的接收窗口置为0通过报文的窗口字段告知发送方A过了一段时间后B的应用程序将接收缓冲区的数据处理了一部分接收窗口又有了空间假设为300此时B向A发送报文告知对方接收窗口为300如果该报文在传输中丢失了A不会一直傻傻地等待在A收到B的0窗口报文后就会开启该连接设定的持续计时器当超过计时器规定的时间后A会向B发送一个0窗口探测报文段B在收到这个探测报文后会重新发送300的窗口报文段。此时有人会问B的接收窗口大小为0了怎么还能接收0窗口探测报文段这里需要记住TCP规定即使接收窗口为0也必须可以接收0窗口探测报文段、ACK=1的报文段和URG=1的报文段
TCP的拥塞控制
TCP进行拥塞控制的算法有4个慢开始、拥塞避免、快重传、快恢复。
慢开始将拥塞窗口大小设置为1个发送方的最大报文段MSS上面说过哈报文首部的选项字段每经过一个传输轮次拥塞窗口就加倍直到达到慢开始门限后开启拥塞避免。
拥塞避免当达到慢开始门限后每收到一次接收方的确认ACK就将拥塞窗口大小+1直到网络出现超时后将慢开始门限调整为原来的一半执行慢开始算法。
快重传快重传算法可以让发送方尽早知道发生了个别报文段的丢失。由于接收方必须对发送方每个报文回复确认ACK假设发送方以此发送M1、M2、M3、M4、M5、M6报文接收方收到1和2后都及时给出了确认由于字节都是连续都假设接收方没有收到3但收到了4此时接收方会在收到4、5、6报文后都发送对2的确认当发送方连续收到3个重复确认时就知道接收方没有收到报文段3此时会立即重传报文3。
快恢复:当发生快重传时,发送方知道现在只是丢失了个别字段,所以不启动慢开始,而是执行快恢复算法,将拥塞窗口调整为慢开始门限的一半,执行拥塞避免算法。
下面通过一道题来理解:
问题设tcp的拥塞窗口的慢开始门限值初始为8,当拥塞窗口上升到12时网络发生超时那么第13次传输时的拥塞窗口大小为多少
解答:
慢开始0->1->2->4->8传输4次
到达慢开始门限8进入拥塞避免 8->9->10->11->12传输4次
增长到12发生超时慢开始门限调整到6慢启动0->1->2->4->6传输4次
6已经达到慢开始门限进入拥塞避免6->7第十三次传输
所以最终答案为7
TCP连接的三次握手
最开始的 Client 和 Server 都是处于 Closed由于服务器端不知道要跟谁建立连接所以其只能被动打开然后监听端口此时 Server 处于 Listen 状态;
而 Client 会主动打开,然后构建好 TCB 「SYN= 1seq = x」发送给服务器端此时 Client 会将状态置为 SYN_SEND 「同步已发送」;
服务器端收到客户端发来的同步请求后,会将状态置为 SYN_RECV「同步已接收」同时会构建好 TCB「SYN = 1seq = yACK = 1ack = x + 1」发送给客户端
客户端接收到了服务器端发来的传输控制块之后,会将自己的状态改为 ESTABLISHED「建立连接」然后发送确认报文ACK= 1seq = x + 1ack = y + 1
服务器端在收到了客户端发来的报文之后,也将状态置为 ESTABLISHED「建立连接」至此三次握手结束当然在这里可以带 tcp 报文段信息过来了,因为此时客户端已经可以保证是可靠的传输了,所以在这一端可以发送报文段了。
题目1为什么A最后还要再发送一次确认
解答为了防止因为网络原因迟来的A连接请求到达BB单方面建立连接浪费B的资源。假如A发送了连接请求但未收到确认于是A又重传了一次连接请求第二个连接请求正常连接并传输数据。此时A的第一个连接没有丢失只是延迟了又到达了BB误以为是A又发送的一次连接假如此时B向A发出确认后A会丢弃B的确认假如没有A最后一次的确认B就会在发送确认后建立连接白白浪费B的资源。
题目2为何不直接在第一次握手就带上报文段消息非要第三次才可以带
解答:因为 TCP 是要保证数据的不丢失且可靠如果在第一次就带上报文段消息此次建立连接很有可能就会失败那么就不能保证数据的不丢失了在不可靠的机制上进行这种操作换来的代价太大每次发送报文段的资源也会增大得不偿失而第三次握手的时候客户端已经知道服务器端准备好了所以只要告诉服务器端自己准备好了就ok了所以此时带上报文段信息没有任何问题。
TCP断开的四次挥手
最开始客户端和服务器端都是 ESTABLISHED 的状态,然后客户端会主动关闭,而服务器端则是被动关闭。(主动关闭的我们认为是客户端)
客户端发送一个 FIN 报文段seq = 结束的报文段序号 + 1「假设为 u」告诉服务器端客户端需要关闭了此时将客户端的状态变为 FIN-WAIT-1等待服务器端的反馈
服务器在接收到了客户端发来的 FIN 包之后,会发一条 ack报文反馈给客户端其中报文中包括 ACK = 1seq = vack = u+1告诉客户端收到了客户端要关闭的消息了同时服务器端会通知应用进程需要关闭连接了并将自己的状态置为 CLOSE-WAIT
由于服务器端可能还有一些数据没处理完,所以需要一段时间的等待,当处理完了之后,会再发一条报文,其中 FIN = 1ACK = 1seq = wack = u+1告知客户端服务器端现在可以关闭了并将服务器端的状态由 CLOSE-WAIT 变为 LAST-ACK
客户端在收到了服务器端发来的消息之后会发一条ack报文「ACK = 1seq = u+1ack = w+1」回去告知服务器端客户端已经知道了你准备好关闭了此时会将客户端的状态由 FIN-WAIT-2 置为 TIME-WAIT在两个最长报文段传输时间过后会自动将客户端的状态由 TIME-WAIT 置为 CLOSED。
服务器端收到消息之后,就将状态由 LAST-ACK 置为了 CLOSED自此四次挥手全部结束。
题目1在B向A发送FIN断开连接的报文后A发送确认后做了什么是马上断开吗为什么要等待2个时间周期
解答图里很明了并不是马上断开而是等待了2个时间周期。原因有2个
为了保证A发送的最后一个ACK报文能到达B在这两个时间周期内如果B收不到A的确认会超时重传这个FIN+ACK的报文A就会收到重传的断开确认报文此时A会重传确认重新启动2MSL计时器。假如A不等待2MSL就不会收到B的重传报文也就不会再发送一次确认报文B就无法按照正常步骤进入CLOSE状态。
A在发送完最后一个ACK报文后经过2MSL就可以使本次连接内产生的所有报文都从网络中消失在下一个新连接中就不会出现旧的连接报文段。
题目2主动关闭方和被动关闭方谁先进入CLOSE状态
解答看图也可以发现是被动关闭方先进入CLOSE状态原因上一题的答案就可以解释明白。
题目3:为何不能三次挥手呢?
解答:首先如果去掉最后一次挥手,那么服务器端就不知道自己要关闭的报文有没有传输成功,可能半路上就失败了,但是此时客户端不知道,导致客户端一直在等待服务器关闭,但是此时服务器端直接就关闭了。

168
c++/小猫钓鱼.md Normal file
View File

@ -0,0 +1,168 @@
---
title: 小猫钓鱼
date: 2022-03-09 00:16:12.409
updated: 2022-09-05 19:38:40.838
url: https://hhdxw.top/archives/74
categories:
- C&C++
tags:
- C&C++
---
# 小猫钓鱼——栈、队列的应用C++
## 一、游戏规则:
将一副扑克牌假设牌面只有1~9平均分成两份每人拿一份。小哼先拿出手中的第一张扑克牌放在桌子上然后小哈也拿出手中的第一张扑克牌放在小哼刚打出的扑克牌的上面就这样两人交替出牌。出牌时如果某人打出的扑克牌与桌面上某张扑克牌的牌面相同即将两张相同的扑克牌及中间所夹的牌全部取走依次放在自己手中牌的末尾。当任意一人手中的牌全部出完时游戏结束对手获胜。
假如游戏开始时小哼手中有6张牌顺序为2、4、1、2、5、6小哈手中也有6张牌顺序为3、1、3、5、6、4最终谁会获胜呢
请编写一个程序来自动判断谁将获胜。
## 二、游戏分析:
1.手中的牌构成一个队列。
2.出牌和赢牌对应出队和入队两个操作。
3.桌子相当于一个栈,每打出一张牌放到桌子上相当于入栈。
#### 游戏开始:
1.小哼先出牌。小哼亮出一张牌t检查桌面上是否存在相同的牌面。若不存在则此轮没有赢牌否则此轮可以赢牌。
用数组book标记桌面上是否存在相同的牌面。
若桌面上不存在相同的牌面则小哼出牌t出队将t放到桌面上入栈进行标记。
若桌面上存在相同的牌面则先把t放到手中牌的末尾先出队再入队然后从桌面上把压在与t相同牌面之上的扑克牌依次取走放入手中牌的末尾最后从桌面上把压在与t相同牌面的牌也收入手中同时进行标记。
2.游戏如何结束。只要两人中有一人的牌用完了,游戏就结束了。
3.输出游戏的获胜者,获胜者手中扑克牌,及桌子上的扑克牌。
## 三、实现代码如下:
```c
#include <bits/stdc++.h>
using namespace std;
//声明全局容器栈以及队列
stack <int> Zhuo;
queue <int> Heng;
queue <int> Ha;
int main()
{
int q;
// book记录桌上牌的数量
int book[10];
for(int i = 1;i <= 9;i++)
book[i] = 0;
cout << "请按顺序输入小哼卡牌的数字" << endl;
int arr[] {2,4,1,2,5,6};
for(int i=0;i<6;i++)
{
// 两种输入方式用数组方便写的时候检查bug
// cin >> q;
// Heng.push(q);
Heng.push(arr[i]);
}
cout << "请按顺序输入小哈卡牌的数字" << endl;
int all[] {3,1,3,5,6,4};
for(int i=0;i<6;i++)
{
// cin >> q;
// Ha.push(q);
Ha.push(all[i]);
}
//检查小哼和小哈是否有人手中无牌,输得比赛
while(Heng.empty() != true && Ha.empty() != true )
{
//将小哼的队列头元素赋值给q用于检测是否有重复
q = Heng.front();
//判断小哼当前打出的牌是否能贏牌
if(book[q] == 0)
{
//小哼输牌
Heng.pop();
Zhuo.push(q);
//调整book中牌的种类
book[q] = 1;
}
else
{
//将打出的牌直接放到牌尾
Heng.pop();
Heng.push(q);
//小哼赢牌
while(Zhuo.top() != q)
{
//调整book中牌的种类
book[Zhuo.top()] = 0;
Heng.push(Zhuo.top());
Zhuo.pop();
}
}
//如果小哼中的牌如果已经打完,游戏结束
if(Heng.empty() == true)
break;
q = Ha.front();
//判断小哈当前打出的牌是否能贏牌
if(book[q] == 0)
{
//小哈输牌
Ha.pop();
Zhuo.push(q);
book[q] = 1;
}
else
{
Ha.pop();
Ha.push(q);
//小哈赢牌
while(Zhuo.top() != q)
{
book[Zhuo.top()] = 0;
Ha.push(Zhuo.top());
Zhuo.pop();
}
}
}
if(Heng.empty() == true)
{
cout << "小哈赢了" << endl;
while(Ha.empty() != true)
{
cout << Ha.front() <<" ";
Ha.pop();
}
}
else
{
cout << "小哼赢了" << endl;
while(Heng.empty() != true)
{
cout << Heng.front() <<"";
Heng.pop();
}
}
cout << endl;
cout << "桌上的牌是:" ;
while (Zhuo.size())
{
printf("%d", Zhuo.top());
Zhuo.pop();
}
}
```
## 四、运行截图
![image-20220309100532330](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220309100532330.png)

View File

@ -0,0 +1,123 @@
---
title: 炸弹人游戏
date: 2022-03-09 00:16:12.441
updated: 2022-09-05 20:04:13.861
url: https://hhdxw.top/archives/75
categories:
- C&C++
tags:
- C&C++
---
## 一、题目:
你只有一枚炸弹,这枚炸弹威力超强(杀伤距离超长,可以消灭杀伤范围内的所有敌人)。请问在哪里放置炸弹可以消灭最多的敌人?最多可以消灭多少敌人?
## 二、注意:
灰色底纹表示墙,炸弹不能穿透。
人脸 表示敌人。
空白位置表示空地。
炸弹只能安放到空地上。
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps1700.tmp.jpg)
## 三、代码实现如下:
```c
#include <bits/stdc++.h>
using namespace std;
int main()
{
//0.墙 1.表示敌人 2.空地
int max = 0,p,q;
int a[13][13] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,2,1,1,1,0,1,1,1,2,0,
0,0,0,2,0,1,0,1,0,1,0,1,0,
0,2,2,2,2,2,2,2,0,2,2,1,0,
0,1,0,2,0,0,0,2,0,1,0,1,0,
0,1,1,2,1,1,1,2,0,2,1,1,0,
0,1,0,2,0,1,0,2,0,2,0,0,0,
0,0,1,2,2,2,1,2,2,2,2,2,0,
0,1,0,2,0,1,0,0,0,2,0,1,0,
0,2,2,2,1,0,1,1,1,2,1,1,0,
0,1,0,2,0,1,0,1,0,2,0,1,0,
0,1,1,2,1,1,1,0,1,2,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,};
// j代表每一列i代表每一行
for(int i = 1;i < 12;i++)
{
for(int j = 1;j < 12;j++)
{
if(a[i][j] == 2)
{
//sum临时计算敌人数量x,y,分别是横纵坐标
int x,y,sum=0;
//向上
x=i;
y=j;
//判断不撞到墙就进入,撞到墙就停止移动
while(a[x][y]!=0)
{
//判断是不是敌人,是,则加一
if(a[x][y]==1)
sum++;
//控制移动炸弹范围
x--;
}
//向下
x=i;
y=j;
while(a[x][y]!=0)
{
if(a[x][y]==1)
sum++;
x++;
}
//向左
x=i;
y=j;
while(a[x][y]!=0)
{
if(a[x][y]==1)
sum++;
y--;
}
//向右
x=i;
y=j;
while(a[x][y]!=0)
{
if(a[x][y]==1)
sum++;
y++;
}
//统计四个方向行走过程中碰到的敌人的数量,并与上一次做比较寻找最大值
if(sum>max)
{
max=sum;
p=i;
q=j;
}
}
}
}
cout << "最多人数是:" << max << "" << endl;
cout << p << "" << q << "" << endl;
return 0;
}
```
## 四、运行结果如下:
![image-20220309101417055](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220309101417055.png)

25
docker.md Normal file
View File

@ -0,0 +1,25 @@
docker镜像配置
```
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"features": {
"buildkit": true
},
"registry-mirrors": [
"https://9kkc1zdn.mirror.aliyuncs.com"
]
}
```
恢复docekr数据
```
docker load -i all_images.tar
```

117
六大设计模式.md Normal file
View File

@ -0,0 +1,117 @@
编程是一个先思考再编码的过程,思考是优于编码技能的,在思考过程中我们会考虑代码的可重用性、可靠性、更容易被他人理解,这时就会使用到[设计模式](https://so.csdn.net/so/search?q=%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F&spm=1001.2101.3001.7020)让代码编写工程化,这篇文章整理了设计模式的六大原则。
# SOLID
[SOLID: The First 5 Principles of Object Oriented Design | DigitalOcean](https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design "SOLID: The First 5 Principles of Object Oriented Design | DigitalOcean")
## 单一职责原则
单一职责原则Single Responsibility Principle
There should never be more than one reason for a class to change.(有且仅有一个原因可以引起类的变更)
不管让我干啥,我都只干一件事,你让我下楼取快递,顺便将垃圾带下去,对不起,我不干,我只取快递。
优点:
- 类的复杂性降低,实现什么职责都有清晰明确的定义;
- 可读性提高,复杂性降低,那当然可读性提高了;
- 可维护性提高,可读性提高,那当然更容易维护了;
- 变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
## 接口隔离原则
接口隔离原则Interface Segregation Principle
1、Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口)
2、The dependency of one class to another one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)
举个例子类A 通过 Interface1 依赖类B方法1方法2方法3类B 通过 Interface1 依赖D方法1方法4方法5看下未使用接口隔离原则和使用了接口隔离原则发生了什么变化。
![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL3N6X21tYml6X3BuZy9nbzlqcEczQnVoVDBRRTJHbXR5Z1VEQ3dpYkliN01DMVNWSWljWnFzQTZRT3BrSG1mUEpnUTczS0picGVCZjRrOEd0dndOSXhyNWVvTmljZlphNFlhYm9JZy82NDA?x-oss-process=image/format,png)
## 依赖倒置原则
依赖倒置原则Dependence Inversion Principle
1、High level modules should not depend upon low level modules.Both should depend upon abstractions. (高层模块不应该依赖低层模块,两者都应该依赖其抽象)
2、Abstractions should not depend upon details. (抽象不应该依赖细节)
3、Details should depend upon abstractions. (细节应该依赖抽象)
举个例子类A 直接依赖 类B假如要将 类A 改为依赖 类C则必须通过修改 类A 的代码来达成。这种场景下类A一般是高层模块负责复杂的业务逻辑类B 和类C 是低层模块负责基本的原子操作假如修改类A会给程序带来不必要的风险。
解决方案:将 类A 修改为依赖 接口Interface1类B 和 类C 各自实现 接口Interface1类A 通过 接口Interface1 间接与 类B 或者 类C 发生联系,则会大大降低修改 类A 的几率。
![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL3N6X21tYml6X3BuZy9nbzlqcEczQnVoVDBRRTJHbXR5Z1VEQ3dpYkliN01DMVM3emUxWURpYTVuUlkzWUZTaWJBc2FrVDlSUmdRUWJPMXhVdFFXNkNraWFzUTNJTGVrS0UydXVza0EvNjQw?x-oss-process=image/format,png)
## 里氏替换原则
里氏替换原则Liskov Substitution Principle
1、If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(如果对每一个类型为 S 的对象o1都有类型为 T 的对象 o2使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 S 是类型 T 的子类型)
2、Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基类的地方必须能透明地使用其子类的对象)
举个例子,有一功能 P1由 类A 完成,现需要将功能 P1 进行扩展,扩展后的功能为 P其中 P 由原有功能 P1 与新功能 P2 组成,新功能 P 由 类A 的 子类B 来完成,则 子类B 在完成新功能 P2 的同时,有可能会导致原有功能 P1 发生故障。
解决方案当使用继承时遵循里氏替换原则。类B 继承 类A 时,除添加新的方法完成新增功能 P2 外,尽量不要重写 父类A 的方法也尽量不要重载父类A的方法。
继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些方法任意修改,就会对整个继承体系造成破坏,而里氏替换原则就是表达了这一层含义。
继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。
优点:
- 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
- 提高代码的重用性,可扩展性。
- 提高产品或项目的开放性。
## 迪米特法则
迪米特法则Law of Demeter
1、Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.(每个单元对于其他的单元只能拥有有限的知识:只是与当前单元紧密联系的单元)
2、Each unit should only talk to its friends; don't talk to strangers.(每个单元只能和它的朋友交谈:不能和陌生单元交谈)
3、Only talk to your immediate friends.(只和自己直接的朋友交谈)
举个例子,我们通过 `手机` 阅读 `微信读书 APP` 内的 `书籍`,如何设计类的编写?
![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL3N6X21tYml6X3BuZy9nbzlqcEczQnVoVDBRRTJHbXR5Z1VEQ3dpYkliN01DMVNpYnQ0a1NsRG12S0t5TWdodmZEekVJVW5WRm44eGxsOFRzZkRmMTNlSGhFZHRZWWpVR1hSb2tnLzY0MA?x-oss-process=image/format,png)
手机类 和 书籍类,这两个不能直接发生调用关系,需要 手机类 和 微信读书 APP 类先发生调用关系,然后微信读书 APP 类 再和 书籍 类可以发生调用关系,这样才遵循迪米特法则。
## 开闭原则
开闭原则Open Closed Principle
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.(软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的)
在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。
解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
## 小结
- 单一职责原则告诉我们实现类要职责单一;
- 接口隔离原则告诉我们在设计接口的时候要精简单一;
- 依赖倒置原则告诉我们要面向接口编程;
- 里氏替换原则告诉我们不要破坏继承体系;
- 迪米特法则告诉我们要降低耦合;
- 开闭原则是总纲,告诉我们要对扩展开放,对修改关闭;

1122
前端/微信小程序.md Normal file

File diff suppressed because it is too large Load Diff

146
安卓/SaveQQ.md Normal file
View File

@ -0,0 +1,146 @@
## 1.页面搭建
首先将背景图`bg`拷贝到`drawable`
![bg](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/bg.png)
然后在`layout`文件下编写页面文件`activity_main.xml`
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg"
android:padding="16dp"
android:orientation="vertical">
<LinearLayout
android:layout_marginTop="130dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓 名 "
android:textSize="18sp" />
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入姓名"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="电 话 "
android:textSize="18sp" />
<EditText
android:id="@+id/et_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入手机号码"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_add"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="2dp"
android:layout_weight="1"
android:background="#B9B9FF"
android:text="添加"
android:textSize="18sp" />
<Button
android:id="@+id/btn_query"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="2dp"
android:layout_weight="1"
android:background="#DCB5FF"
android:text="查询"
android:textSize="18sp" />
<Button
android:id="@+id/btn_update"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="2dp"
android:layout_weight="1"
android:background="#E6CAFF"
android:text="修改"
android:textSize="18sp" />
<Button
android:id="@+id/btn_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ACD6FF"
android:text="删除"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:textSize="20sp" />
</LinearLayout>
```
![image-20221020093735433](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221020093735433.png)
## 2.后端代码编写
### 1.首先创建控件和初始化所有控件并绑定单击事件
```java
private EditText mEtName, mEtPhone;
private TextView mTvShow;
private Button mBtnAdd, mBtnQuery, mBtnUpdate, mBtnDelete;
```
```java
mEtName = (EditText) findViewById(R.id.et_name);
mEtPhone = (EditText) findViewById(R.id.et_phone);
mTvShow = (TextView) findViewById(R.id.tv_show);
mBtnAdd = (Button) findViewById(R.id.btn_add);
mBtnQuery = (Button) findViewById(R.id.btn_query);
mBtnUpdate = (Button) findViewById(R.id.btn_update);
mBtnDelete = (Button) findViewById(R.id.btn_delete);
mBtnAdd.setOnClickListener(this);
mBtnQuery.setOnClickListener(this);
mBtnUpdate.setOnClickListener(this);
mBtnDelete.setOnClickListener(this);
```
### 2.SQLite数据库的创建
```java
//1. 创建数据库
class MyHelper extends SQLiteOpenHelper {
//创建数据库
public MyHelper(@Nullable Context context) {
super(context, "itcast.db", null, 1);
}
//创建表
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String str = "create table information(_id integer primary key autoincrement, name varchar(20), phone varchar(20))";
sqLiteDatabase.execSQL(str);
}
//当数据库版本号发生变化时自动调用的方法
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
```

25
安卓/内容观察者.md Normal file
View File

@ -0,0 +1,25 @@
7.4内容观察者
ContentProvider 内容提供者暴露数据
ContentResolver 操作数据的
ContentObserver 内容观察者观察数据的变化
1.创建Content0 bserver
2.注册Contentobserver
3.取消注册Contentobserver
案例:检测数据的变化
l.创建项目ContentobserverDB
2.复制了图片和布局文件
3.复制创建数据库和表的类
4,创建内容提供者PersonProvider

View File

@ -0,0 +1,24 @@
# 第11章网络编程
## 11.2 WebView控件的使用
1.WebView浏览网页的内容 --> `loadUrl(String Url)`
2.WebView可以解析 HTML 代码 --> `loadDataWithBaseURL()`
3.WebView还可以支持 JS 代码
案例:天气预报
1.创建项目
2.复制图片和布局文件
3.创建assets文件夹复制weather.json
4.创建与JS0N数据匹配的实体类注意实体类的成员变量名要和json数据中的key值保持一致
5.添加Gson库
6.创建工具类JsonParse

View File

@ -0,0 +1,11 @@
## 第七章:检测数据变化
1.创建项目A
2.创建数据库和表
3.创建内容提供者 暴露数据
4.MainActivity 操作数据
1布局文件中添加四个按钮

View File

@ -0,0 +1,718 @@
# 第三章Android常见界面控件
## 3.1简单控件
### 1.TextView显示文本信息
| 属性名称 | 功能描述 |
| :----------------------: | :----------------------------------------------------------: |
| android:layout_width | 设置 TextView控件的宽度 |
| android:layout_height | 设置 TextView控件的高度 |
| androidid | 设置 TextView 控件的唯一标识 |
| android:background | 设置 TextView 控件的背景 |
| android:layout_margin | 设置当前控件与屏幕边界或周围控件、布局的距离 |
| android:padding | 设置 TextView控件与该控件中内容的距离 |
| android:text | 设置文本内容 |
| android:textColor | 设置文字显示的颜色 |
| android:textSize | 设置文字大小,推荐单位为 5p如android:textSize = "15sp" |
| android:gravity | 设置文本内容的位置如设置成“center”文本将居中显示 |
| android:maxLength | 设置文本最大长度超出此长度的文本不显示。如android:maxLength - "10" |
| android:lines | 设置文本的行数,超出此行数的文本不显示 |
| android:maxLines | 设置文本的最大行数,超出此行数的文本不显示 |
| android:ellipsize | 设置当文本超出TextView规定的范围的显示方式。属性值可选为"start”, "middle" 和"end"分别表示当文本超出TextView规定的范围时在文本开始、中间或者末尾显示省略号“----” |
| android:drawableTop | 在文本的顶部显示图像,该图像资源可以放在 res/drawable 相应分辨率的目录下,通过“@drawable/文件名”调用。类似的属性有 android:drawableBottorm、android:drawableLefi、android:drawableRight |
| android:lineSpacingExtra | 设置文本的行间距 |
| android:textStyle | 设置文本样式如bold (租体), italic (斜体), normal (正常) |
### 2.Button按钮
1在布局文件中指定 onClick 属性的方式设置点击事件
```xml
<!-- activity_main.xml 文件-->
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click"
android:text="onClick属性" />
```
```java
// MainActivity.java 文件
public void click(View view) {
System.out.println("我是通过onClick属性完成的单击事件");
}
```
2使用匿名内部类的方式设置点击事件
```xml
<!-- activity_main.xml 文件-->
<Button
android:id="@+id/btn_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="匿名内部类" />
```
```java
// MainActivity.java 文件
public class MainActivity extends AppCompatActivity {
Button btn_two;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_two = findViewById(R.id.btn_two);
btn_two.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.out.println("我是通过匿名内部类完成的单击事件");
}
});
}
}
```
3Activity 实现 OnClickListener 接口的方式设置点击事件
```xml
<!-- activity_main.xml 文件-->
<Button
android:id="@+id/btn_three"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接口实现" />
```
```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btn_three;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_three=findViewById(R.id.btn_three);
btn_three.setOnClickListener(this);
}
@Override
public void onClick(View view) {
System.out.println("我是通过实现接口的方式完成的单击事件");
}
}
```
### 3.EditText编辑框
| 属性姓名 | 功能描述 |
| :------------------------: | :----------------------------------------------------: |
| android:hint | 控件中内容为空时显示的提示文本信息 |
| android:textColorHint | 控件中内容为空时显示的提示文本信息的颜色 |
| android:password | 输人文本框中的内容显示为“-” |
| android:minLines | 设置文本的最小行数 |
| androidiscrollHorizontally | 设置文本信息超出 EdifText 的宽度情况下,是否出现横拉条 |
| android:editable | 设置是否可编辑 |
| android:phoneNumber | 设置输人文本框中的内容只能是数字 |
### 4.Image View图片
| 属性名称 | 功能描述 |
| :-------------------: | :---------------------------------------------: |
| android:layout_width | 设置 ImageView 控件的宽度 |
| android:layout_height | 设置 ImageView控件的高度 |
| android:id | 设置ImageView控件的唯一标识 |
| android:background | 设置 ImageView 控件的背景 |
| android:layout_margin | 设置当前控件与屏幕边界或周围控件的距离 |
| android:src | 设置ImageView控件需要显示的图片资源 |
| android:scaleType | 将图片资源缩放或移动以适应ImageView控件的宽高 |
| android:tint | 将图片渲染成指定的颜色 |
### 5.RadioButton单选按钮
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请选择你的性别" />
<RadioGroup
android:id="@+id/rg"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/rb_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男" />
<RadioButton
android:id="@+id/rb_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女" />
<RadioButton
android:id="@+id/rb_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="保密" />
</RadioGroup>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="此处显示您的性别:" />
</LinearLayout>
```
![image-20220920170834225](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220920170834225.png)
```java
public class MainActivity extends AppCompatActivity {
RadioGroup rg;
RadioButton rb1, rb2;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
// 为单选按钮组添加单击事件
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
// radioGroup 代表的是单选按钮组
// i 代表的是单选按钮
switch (i) {
case R.id.rb_1:
tv.setText("您的性别是:男");
break;
case R.id.rb_2:
tv.setText("您的性别是:女");
break;
case R.id.rb_3:
tv.setText("您的性别是:未知");
break;
}
}
});
}
// 初始化所有的控件
void init() {
rg = findViewById(R.id.rg);
rb1 = findViewById(R.id.rb_1);
rb1 = findViewById(R.id.rb_2);
rb1 = findViewById(R.id.rb_3);
tv = findViewById(R.id.tv);
}
}
```
演示:
![image-20220920170949644](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220920170949644.png)
### 6.CheckBox复选框
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请选择您的爱好:" />
<CheckBox
android:id="@+id/cb_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="看书"/>
<CheckBox
android:id="@+id/cb_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="看视频"/>
<CheckBox
android:id="@+id/cb_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="看文档"/>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="您的爱好是:" />
</LinearLayout>
```
![image-20220920171135978](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220920171135978.png)
```java
public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {
CheckBox cb1, cb2, cb3;
TextView tv;
String hobbys="您的爱好是:";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
// 为每一个复选框添加一个单击事件
cb1.setOnCheckedChangeListener(this);
cb2.setOnCheckedChangeListener(this);
cb3.setOnCheckedChangeListener(this);
}
void init() {
cb1 = findViewById(R.id.cb_1);
cb2 = findViewById(R.id.cb_2);
cb3 = findViewById(R.id.cb_3);
tv = findViewById(R.id.tv);
}
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
// compoundButton 代表的是状态被改变的复选框
// b 代表的是状态 1.选中 2.未选中
String motion = compoundButton.getText().toString();
if (b == true) {
// 如果复选框被选中,需要将复选框中的文本信息添加到 tv 中
if (!hobbys.contains(motion)){
hobbys=hobbys+motion;
tv.setText(hobbys);
}
} else {
// 如果复选框被取消,需要将复选框中的文本信息删除掉
if(hobbys.contains(motion)){
hobbys=hobbys.replace(motion,"");
tv.setText(hobbys);
}
}
}
}
```
演示:
![image-20220920171302035](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220920171302035.png)
### 7.Toast信息提醒机制
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RadioGroup
android:id="@+id/rg"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/rb_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男" />
<RadioButton
android:id="@+id/rb_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女" />
</RadioGroup>
</LinearLayout>
```
![image-20220922091511202](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220922091511202.png)
```java
public class ToastActivity extends AppCompatActivity {
RadioGroup rg;
RadioButton rb1,rb2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 页面关联
setContentView(R.layout.toast);
// 初始化
init();
// 添加事件
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if (i==R.id.rb_1){
Toast.makeText(ToastActivity.this,"您的性别是男",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(ToastActivity.this,"您的性别是女",Toast.LENGTH_LONG).show();
}
}
});
}
void init(){
rg=findViewById(R.id.rg);
rb1=findViewById(R.id.rb_1);
rb2=findViewById(R.id.rb_2);
}
}
```
演示:
![image-20220922091555853](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220922091555853.png)
## 3.2AlertDialog对话框使用
### 3.2.2普通对话框
通过调用 `setMessage()`方法设置
```java
setMessage(ChaeSequence message)
```
```java
public class MainActivity extends AppCompatActivity {
// 重写onBackPressed()----单击回退键时调用的方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onBackPressed() {
// 1.创建静态内部类对象
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 2创建对话框的标题区域----标题图标 标题名称
builder.setTitle("普通对话框");
builder.setIcon(R.mipmap.ic_launcher);
// 3创建对话框的内容区域
builder.setMessage("您确认退出程序吗?");
// 4创建对话框的按钮区域
builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "您单击了确认按钮", Toast.LENGTH_LONG).show();
dialogInterface.dismiss();
MainActivity.this.finish();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "您单击了取消按钮", Toast.LENGTH_LONG).show();
dialogInterface.dismiss();
}
});
// 5创建对话框对象
AlertDialog dialog = builder.create();
// 6显示对话框
dialog.show();
}
}
```
![image-20221006082929853](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221006082929853.png)
### 3.2.3单选对话框
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="今天课程真好"
android:textSize="20sp" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="设置字体大小" />
</LinearLayout>
```
```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// 2.定义成员变量
Button btn;
TextView tv;
int textSize = 1;
int[] textsizeArr = {10, 20, 30, 40, 50};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1.初始化
init();
// 3.为控件绑定事件
btn.setOnClickListener(this);
}
void init() {
tv = findViewById(R.id.tv);
btn = findViewById(R.id.btn);
}
@Override
public void onClick(View view) {
// 创建对话框
// 1.创建静态内部类对象
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 2.创建标题
builder.setTitle("单选对话框");
builder.setIcon(R.mipmap.ic_launcher);
// 3.创建内部区域
builder.setSingleChoiceItems(new String[]{"小号", "默认", "中等", "大号", "超大号"}, textSize, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
textSize = i;
Toast.makeText(MainActivity.this, "您单击了按钮", Toast.LENGTH_LONG).show();
}
});
// 4.创建按钮区域
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
tv.setTextSize(textsizeArr[textSize]);
dialogInterface.dismiss();
}
});
builder.setNegativeButton("取消", null);
// 5.创建对话框
AlertDialog dialog = builder.create();
// 6.显示对话框
dialog.show();
}
}
```
![image-20221006082632884](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221006082632884.png)
### 3.2.4多选对话框
```xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请选择爱好"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
```
```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
String[] str = {"看代码", "敲代码", "改代码"};
boolean[] str1 = {false, true, false};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn).setOnClickListener(this);
}
@Override
public void onClick(View view) {
// 创建对话框
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("多选对话框")
.setIcon(R.mipmap.ic_launcher)
.setMultiChoiceItems(str, str1, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i, boolean b) {
str1[i] = b;
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
StringBuffer stringBuffer = new StringBuffer();
for (int j = 0; j < str1.length; j++) {
if (str1[j]) {
stringBuffer.append(str[j]).append("");
}
}
if (stringBuffer != null) {
Toast.makeText(MainActivity.this, stringBuffer, Toast.LENGTH_SHORT).show();
}
}
})
.setNegativeButton("取消", null)
.create();
dialog.show();
}
}
```
![image-20221006083710559](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221006083710559.png)
## 3.3 ListView的使用
```xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ImageView
android:id="@+id/iv"
android:layout_width="120dp"
android:layout_height="90dp"
android:layout_centerVertical="true" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/iv">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="桌子"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
android:layout_marginTop="10dp"
android:text="价格:"
android:textColor="#FF8F03"
android:textSize="20sp" />
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/tv_price"
android:text="1000"
android:textColor="#FF8F03"
android:textSize="20sp" />
</RelativeLayout>
</RelativeLayout>
```
```java
public class MainActivity extends AppCompatActivity {
// 1.准备数据
int[] icons = {R.drawable.apple, R.drawable.cake, R.drawable.kiwifruit, R.drawable.scarf, R.drawable.table, R.drawable.wireclothes};
String[] titles = {"苹果", "蛋糕", "猕猴桃", "围巾", "桌子", "毛衣"};
String[] prices = {"320元", "10元/kg", "300元", "10元/kg", "2800元", "1600元"};
// 2.准备控件
TextView textView;
ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.lv);
MyAdapter myAdapter = new MyAdapter();
listView.setAdapter(myAdapter);
}
class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return titles.length;
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
// 找控件
if (view == null) {
view = View.inflate(MainActivity.this, R.layout.list_item, null);
holder = new ViewHolder();
holder.title = view.findViewById(R.id.title);
holder.price = view.findViewById(R.id.price);
holder.iv = view.findViewById(R.id.iv);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// 为控件设置内容
holder.title.setText(titles[i]);
holder.price.setText(prices[i]);
holder.iv.setBackgroundResource(icons[i]);
return view;
}
}
class ViewHolder {
TextView title, price;
ImageView iv;
}
}
```
![image-20221006083432016](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221006083432016.png)

View File

@ -0,0 +1,27 @@
输入流:从文件中 读 到程序中
输出流:从程序中 写 到文件中
数据源 目的地
```java
1. b.txt 写 hello 输出
// bytes 数据源 fos.write() b.txt目的地
File file=new File("E:/b.txt");
FileOutputStream fos=new FileOutputStream(file);
String str="hello"; //数据源
byte[] bytes = str.getBytes();
fos.write(bytes);
fos.close();
// 2.b.txt 读 输入
FileInputStream fis=new FileInputStream(file);
byte[] bytes1=new byte[fis.available()];
fis.read(bytes1);
System.out.println(new String(bytes1));
fis.close();
```

View File

@ -0,0 +1,196 @@
# 第九章:服务
## 9.1 服务概述
Android的四大组件Activity ContentProvider BroadcastReceiver Service
Service 服务:长时间在后台运行,而且没有用户界面
## 9.2 服务的创建
包上右键单击new -->Service-->Service
清单文件中产生一段代码,用来注册服务的
```xml
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
```
## 9.3 服务的生命周期方法
启动服务的方式有两种: startService() bindService()
关闭服务的方法有两种: stopService() unbindService()
服务的生命周期方法: onCreate() onCreate()
onStartCommand() onBind() onUnbind()
onDestroy() onDestroy()
## 9.4 服务的启动方式
### 案例一:
演示startService() stopService() 开启和关闭服务
1创建项目StartService
2复制图片和布局文件
3创建服务重写服务的三个生命周期方法
4MainActivity作为启动服务的组件
收获:
1.startService()开启的服务,其生命周期方法有三个
2.生命周期方法何时被调用
### 案例二:
演示通过bindService方法启动服务
1创建项目BindService
2复制图片和布局文件
3创建服务重写四个生命周期方法
4MainActivity作为启动服务的组件
收获
1. 通过bindService方法启动服务时会回调服务中的onCreate onBind 两个生命周期方法
2. 通过unbindService方法关闭服务时会回调服务中的onUnbind onDestroy两个生命周期方法
总结:
启动服务的两种方式startServive() bindService()
两种方式的不同bindService()方式启动的服务,组件和服务之间可以进行通信
> 如何通信?
> 启动服务的组件MainActivity
> 服务MyService
```java
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return new MyBinder();
}
```
> onBind方法返回值是IBinder接口对象通过该接口对象可以实现组件和服务之间的通信。
>
> onBind方法的返回值返回到哪里去了返回给了onServiceConnected方法的IBinder iBinder形参
```java
class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
```
总结:
1.留下1Bug当解绑服务之后不能再调用服务中的方法了
2.服务Service
1创建Service
2启动服务的两种方式startService bindService
3启动服务的两种方式之间的不同重点
生命周期方法不同
bindService启动的服务启动服务的组件和服务之间可以通信。
如何通信?
## 9.5服务的通信
### 案例 MusicPlayer
1.创建项目
2.res-new-Directory-rawmusic,mp3复制
3.复制图片和布局文件
4.创建按钮的背景选择器 drawable --> new --> Drawable Resource file --> btn_bg_selector
启动服务的组件MainActivity 服务MusicService播放、暂停、继续播放、拉动进度条
5.创建服务MusicService
6.MainActivity绑定服务bindService()
### 案例问答:
1.MainActivity和MusicSerivce之间如何进行通信(MainActivity如何调用MusicSerivce的方法)
MusicService.MusicControl control:
2.MusicService.MusicControl control如何完成初始化
答:
```java
class Myconn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
control = (MusicService.MusicControl) iBinder;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
```
3.
```java
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
control = (MusicService.MusicControl) iBinder;
}中IBinderiBinder对应的实参是什么
```
答:
```java
@Override
public IBinder onBind(Intent intent) {
return new MusicControl();
}
```
4.服务中的音乐总时长和当前进度是如何传递给MainActivity?
Hanler对象
5.进度条跑起来的代码在哪里?
```java
seekBar,setMax(duration);
seekBar.setProgress(currentPosition);
```
6.完成进度条拖动的代码在哪里?
答:在进度条的单击事件中
```java
int progress:=seekBar,getProgress();
control.seekTo(progress);
```
7.如何设置当音乐播放完之后,动画也停止?
答:在进度条的单击事件中
```java
if (i == seekBar.getMax()) {
animator.pause();
}
```

View File

@ -0,0 +1,102 @@
ViewGroup 和View
ViewGroup是布局类似我们家的布局哪里是厨房哪里是卧室……
View是控件类似于家具哪里放沙发哪里放电视……
字体大小使用sp
五种布局都继承与ViewGroup
res 文件夹中有drawable 和 mipmap 开头的多个文件夹,是用来存放图片资源的
分辨率不同设备会自动匹配相应的 drawable 和 mipmap 文件夹中的图片资源
## 通用属性
| 属性名称 | 功能描述 |
| :-------------------: | :--------------------------------------: |
| android:id | 设置布局的标识 |
| android:layout_width | 设置布局的宽度 |
| android:layout_height | 设置布局的高度 |
| android:background | 设置布局的背景 |
| android:layout_margin | 设置当前布局与屏幕边界或与周围控件的距离 |
| android:padding | 设置当前布局与该布局中控件的距离 |
## RelativeLayout 相对布局
| 属性名称 | 功能描述 |
| :------------------------------: | :--------------------------------------: |
| android:layout_centerInParent | 设置当前控件位于父布局的中央位置 |
| android:layout_centerVertical | 设置当前控件位于父布局的垂直居中位置 |
| android:layout_centerHorizontal | 设置当前控件位于父控件的水平居中位置 |
| android:layout_above | 设置当前控件位于某控件上方 |
| android:layout_below | 设置当前控件位于某控件下方 |
| android:layout_toLeftOf | 设置当前控件位于某控件左侧 |
| android:layout_toRightOf | 设置当前控件位于某控件右侧 |
| android:layout_alignParentTop | 设置当前控件是否与父控件顶端对齐 |
| android:layout_alignParentLeft | 设置当前控件是否与父控件左对齐 |
| android:layout_alignParentRight | 设置当前控件是否与父控件右对齐 |
| android:layout_alignParemtBottom | 设置当前控件是否与父控件底端对齐 |
| android:layout_alignTop | 设置当前控件的上边界与某控件的上边界对齐 |
| android:layout_alignBottom | 设置当前控件的下边界与某控件的下边界对齐 |
| android:layout_alignLeft | 设置当前控件的左边界与某控件的左边界对齐 |
| android:layout_alignRight | 设置当前控件的右边界与某控件的右边界对齐 |
## LinearLayout 线性布局
| 属性名称 | 功能描述 |
| :-------------------: | :----------------------------------------------------------: |
| android:oriemtation | 设置布局内控件的排列顺序写在LinearLayout标签里面的 |
| android:layout_weight | 在布局内设置控件权重,属性值可直接写 int 值需要把控件的宽度设置成0dp |
## TableLayout 表格布局
三个布局属性:
| 属性名称 | 功能描述 |
| :---------------------: | :----------------------------------------------------------: |
| android:stretchColumns | 设置可被拉伸的列。如android:stretchColumns="0",表示第 1 列可被拉伸 |
| android:shrinkColumns | 设置可被收缩的列。如android:shrinkColumns="1,2"表示23列可收缩 |
| android:collapseColumns | 设置可被隐藏的列。如android:collapscColumns="0",表示第 1 列可被隐藏 |
二个控件属性:
| 属性名称 | 功能描述 |
| :-------------------: | :----------------------------------------------------------: |
| android:layout_column | 设置该控件显示的位置如android:layout_colum="1"表示在第2个位置显示 |
| android:layout_span | 设置该控件占据几行默认为1行 |
## FraameLayout 帧布局
| 属性名称 | 功能描述 |
| :-----------------------: | :----------------------------------------------: |
| android:foreground | 设置帧布局容器的前景图像(始终在所有子控件之上) |
| android:foregroundGravity | 设置前景图像显示的位置 |
## ConstraintLayout 约束布局
| 属性名称 | 功能描述 |
| :------------------------------------: | :------------------------------------: |
| layout_constraintLeff_toLeffor | 控件的左边与另外一个控件的左边对齐 |
| layout_constraintLeft_toRightof | 控件的左边与另外一个控件的右边对齐 |
| layout_constraintRight_toLefiof | 控件的右边与另外一个控件的左边对齐 |
| layout_constraintRight_toRightof | 控件的右边与另外一个控件的右边对齐 |
| layout_constraintTop_toTopof | 控件的上边与另外一个控件的上边对齐 |
| layout_constraintTop_toBottomof | 控件的上边与另外一个控件的底部对齐 |
| layout_constraintBaseline_toBaselineOf | 控件间的文本内容基齐 |
| layout_constraintStart_toEndor | 控件的起始边与另外一个控件的尾部对齐 |
| layout_constraintStart_toStartor | 控件的起始边与另外一个控件的起始边对齐 |
| layout_constraintEnd_toStartof | 控件的尾部与另外一个控件的起始边对齐 |
| layout_constraintEnd_toEndor | 控件的尾部与另外一个控件的尾部对齐 |
倾向属性
| 属性名称 | 功能描述 |
| :------------------------------: | :--------: |
| layout_constraintHorizontal_bias | 横向的倾向 |
| layout_constraintVertical_bias | 纵向的倾向 |

View File

@ -0,0 +1,90 @@
## 第8章广播机制
1.广播是一种不同组件之间进行通信的机制
2.Android系统的四大组件`Activity` `ContentProvider` `BroadcastReceiver` `Service`
3.广播机制的实现流程
广播发送者 AMS 广播接收者
4.(掌握)广播接受者的创建 new other BroadcastReceiver
5.(掌握)广播接收者的注册:动态注册 静态注册
案例ForHelp
1创建项目
2复制照片和布局文件
3创建广播接收者new--other--BroadcastReceiver
清单文件中静态注册广播接收者的代码:
```xml
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true"></receiver>
```
4MainActivity中
发送广播
动态注册广播接收者
取消注册广播接收者
## 广播的类型
1.无序广播 所有的广播接收者都能接收广播但是接受的顺序不确定。ForHelp
核心功能:
发送广播 sendBroadcast(intent)
注册广播接收者 registerReceiver(receiver,intentFilter)
2.有序广播 优先级较高的接收者先接收广播,如果该接收者对广播进行拦截,后面的接收者就接收不到广播了
核心功能:
发送广播 sendOrderedBroadcast(intent)
注册广播接收者 registerReceiver(receiver,intentFilter)
设置广播接收者的优先级 intentFilter.setPriority(1000)
拦截广播 abortBoradcast();
案例2
1创建项目
2复制图片和布局文件
3创建三个广播接收者
4MainActivity组件中
发送有序广播
动态注册三个广播接收者
设置某个广播接收者一定能接收到广播
sendOrderedBroadcast(intent,null,new MyReceiver3(),null,0,null,null);
当没有设置广播接收者优先级的时候,是按照注册的顺序来接收的。

View File

@ -0,0 +1,48 @@
## 第十章Android 事件处理
1.事件分为:键盘事件、触摸事件
2.处理事件的两种方式:
1.基于回调机制
回调on开头的方法返回值true,代表事件处理完毕;
2.基于监听接口
10.4 手势
案例一:创建并保存手势
1.创建项目并复制布局文件
案例:手势识别
1.创建项目 `AddGesture`
2.将 `AddGesture` 中的 `mygestur` 放到 `GestureRecognition` 项目下的 `res` --> `raw `
3.布局文件
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="手势"
android:textColor="@android:color/black"
android:textSize="20dp" />
<android.gesture.GestureOverlayView
android:id="@+id/gestures"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0" />
</LinearLayout>
```
方法2直接在SD卡里面试别

View File

@ -0,0 +1,394 @@
## 4.1 Activity生命周期
### 4.1.1 生命周期状态
**启动**状态
`Activity` 的启动状态很短暂,一般情况下,当 `Activity` 启动之后便会进入运行状态。
**运行**状态
`Activity` 在此状态时处于界面最前端,它是可见、有焦点的,可以与用户进行交互,如点击界面中的按钮和在界面上输入信息等。
**暂停**状态
在某些情况下, `ActiVity` 对用户采说仍然可见,但它无法状取集点,用户对它操作没有响应,此时它就处于暂停状态。
**停止**状态
`Activity` 完全不可见时,它就处于停止状态。
**销毁**状态
`Activity` 处于销毁状态时,将被清理出内存。
### 4.1.2 生命周期方法
(1) onCreate(): Activity创建时调用通常做一些初始化设置。
(2) onStart(): Activity即将可见时调用。
(3) onResume(): Activity获取焦点时调用。
(4) onPause(): 当前Activity被其他Activity覆盖或屏幕锁屏时调用。
(5) onStop(): Activity对用户不可见时调用。
(6) onDestroy(): Activity销毁时调用。
(7) onRestart(): Activity从停止状态到再次启动时调用。
横竖屏切换会调用 `onDestroy()` 销毁 `Activity`,重新调用 `onCreate()` 方法重建Activity。
通过 `configChanges` 属性进行设置就不会清除输入的信息
```xml
<activity android:name=".MainActivity"
android:configChanges="orientationIkeyboardHidden">
```
当`configChanges`属性设置完成之后,打开程序时同样会调用`onCreate()`,`onStar()`、`onResume()`方法,但是当进行横竖屏切换时不会再执行其他的生命周期方法。
如果希望某一个界面一直处于竖屏或者横屏状态,不随手机的晃动而改变,可以在清单文件中通过设置`Activity`的`screenOrientation`属性完成,示例代码如下:
```xml
竖屏android:screenOrientation="portrait"
横屏android:screenOrientation="landscape"
```
## 4.2 Activity的创建、配置、开启和关闭
### 4.2.1 创建 Activity
在包上右击选择
![image-20221004104302195](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221004104302195.png)
一个页面对应一个布局文件 xml
![image-20221004104505572](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221004104505572.png)
### 4.2.2 配置Activity
清单文件`AndroidManifest.xml`中会创建对应的 xml ,表示程序页面首选项
```xml
<activity
android:name=".MyActivity"
android:exported="false" />
```
### 4.2.3 开启和关闭Activity
(1)在 `activity_main.xml` 中添加按钮组件
```xml
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="单击跳转MyActivity" />
```
(2)在 `MainActivity` 中为按钮添加单击事件让其跳转到MyActivity页面
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 跳转到MyActivty
Intent intent= new Intent(MainActivity.this,MyActivity.class);
startActivity(intent);
}
});
}
```
(3)在 `activity_my.xml` 中添加按钮组件
```xml
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="关闭当前页面" />
```
(4)在 `MyActivity` 中为按钮添加单击事件,让其关闭当前页面
```java
public class MyActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
findViewById(R.id.btn).setOnClickListener(this);
}
@Override
public void onClick(View view) {
// 关闭当前页面
finish();
}
}
```
## 4.3 Intent与IntentFilter
首先创建三个页面 A 、B、C
在`A`页面中填写两个`Button`按钮,分别通过`显示`、`隐示`跳转至其他页面
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".A">
<Button
android:id="@+id/b"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示跳转页面B" />
<Button
android:id="@+id/c"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="隐示跳转页面C" />
</LinearLayout>
```
![image-20221006123245336](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221006123245336.png)
```java
public class A extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
findViewById(R.id.b).setOnClickListener(this);
findViewById(R.id.c).setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.b:
// 显示跳转到B
Intent intent = new Intent(A.this, B.class);
startActivity(intent);
break;
case R.id.c:
// 隐式跳转到C
Intent intent1 = new Intent();
intent1.setAction("a");
startActivity(intent1);
break;
}
}
}
```
更改app入口页面
```xml
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">
<activity
android:name=".C"
android:exported="false" >
<intent-filter>
<action android:name="a" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".B"
android:exported="false" />
<activity
android:name=".A"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
```
![image-20221006123256251](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221006123256251.png)
## 4.4 Activity之间的跳转
### 4.4.2 Activity之间的数据传递
在首页创建两个按钮
```xml
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用 putExtra 传递数据" />
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用 Bundle 传递数据" />
```
方法
```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btn1, btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = findViewById(R.id.btn1);
btn1.setOnClickListener(this);
btn2 = findViewById(R.id.btn2);
btn2.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn1:
// 使用 putExtra 传递数据
Intent intent = new Intent(MainActivity.this, FirstActivity.class);
intent.putExtra("name", "王小明");
intent.putExtra("age", 12);
intent.putExtra("isPassed", true);
startActivity(intent);
break;
case R.id.btn2:
// 使用 Bundle 传递数据
Intent intent1 = new Intent(MainActivity.this, SecondActivity.class);
// 创建 Bundle 对象
Bundle bundle = new Bundle();
bundle.putString("name","王小明");
bundle.putInt("age",12);
intent1.putExtras(bundle);
startActivity(intent1);
break;
}
}
}
```
另外两个页面
```xml
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接收 putExtra 传递的数据" />
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
```
```xml
<Button
android:id="@+id/btn4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接收 Bundle 传递的数据" />
<TextView
android:id="@+id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
```
接收方法
```java
public class FirstActivity extends AppCompatActivity {
Button btn3;
TextView text1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
text1=findViewById(R.id.text1);
btn3=findViewById(R.id.btn3);
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 接收数据并显示在text1
Intent intent=getIntent();
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age",0);
boolean isPassed = intent.getBooleanExtra("isPassed",true);
text1.setText(name+":"+age+":"+isPassed);
}
});
}
}
```
```java
public class SecondActivity extends AppCompatActivity {
Button btn4;
TextView text2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
text2 = findViewById(R.id.text2);
btn4 = findViewById(R.id.btn4);
btn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 接收数据并显示在text2
Bundle bundle = getIntent().getExtras();
String name = bundle.getString("name");
int age = bundle.getInt("age");
text2.setText(name + ":" + age);
}
});
}
}
```
![image-20221011112153331](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20221011112153331.png)
### 4.4.2 Activity之间的数据回传

View File

@ -0,0 +1,658 @@
# Docker 的基本命令
## 1、简单运用
#### 1获取 Docker 镜像
```shell
docker pull [IMAGE_NAME:TAG]
```
通过该命令,可以从 Docker Hub 或其他镜像源获取指定名称和标签的 Docker 镜像。例如,执行以下命令可以获取 Docker 官方的 Nginx 镜像
```shell
docker pull nginx:latest
```
#### 2运行 Docker 容器
```shell
docker run [OPTIONS] IMAGE_NAME [COMMAND] [ARG...]
```
该命令用于在 Docker 中运行一个容器。其中IMAGE_NAME 是要使用的 Docker 镜像名称,而 OPTIONS 则为可选的参数,常用的参数包括
- `-d`以守护进程方式运行容器。
- `-p`将主机端口映射到容器端口。
- `--name`为容器指定一个名称。
- `-v`挂载主机目录到容器中。
- `--restart`设置容器退出时的重启策略等。
COMMAND 和 ARG... 则为可选的命令和参数。例如,运行一个名为 myapp 的容器,使用的镜像为 myimage80表示容器内部要映射的端口号主机上要映射到容器内部端口的端口号。可以执行以下命令
```shell
docker run -d -p 80:90 --name myapp myimage
```
#### 3查看当前所有正在运行的容器
```shell
docker ps
```
该命令用于列出当前所有正在运行的 Docker 容器,包括容器 ID、名称、所使用的镜像、状态等基本信息。
如果要查看所有容器,包括已经停止的容器,可以添加 `-a` 选项
```shell
docker ps -a
```
#### 4查看本地镜像列表
```shell
docker images
```
该命令用于列出本地已经保存的 Docker 镜像列表,包括镜像名称、标签、镜像 ID、大小等基本信息。
如果要查看某个特定镜像的详细信息,可以执行以下命令
```shell
docker images [IMAGE_NAME]
```
其中IMAGE_NAME 为要查看信息的镜像名称。
#### 5停止运行中的容器
```shell
docker stop [CONTAINER_ID/CONTAINER_NAME]
```
该命令用于停止指定 ID 或名称的 Docker 容器。例如,停止容器 ID 为 `1234567890ab` 的容器,可以执行以下命令
```shell
docker stop 1234567890ab
```
如果需要停止多个容器,可以依次添加多个容器的 ID 或名称,例如
```shell
docker stop container1 container2 ...
```
#### 6强制终止运行中的容器
```shell
docker kill [CONTAINER_ID/CONTAINER_NAME]
```
该命令用于强制终止运行中的容器。与 `docker stop` 命令不同,`docker kill` 命令会直接杀死容器进程,不会给容器发送停止信号。例如,强制终止名为 myapp 的容器,可以执行以下命令
```shell
docker kill myapp
```
#### 7删除已经停止的容器
```shell
docker rm [CONTAINER_ID/CONTAINER_NAME]
```
该命令用于删除指定 ID 或名称的停止状态 Docker 容器。例如,删除名称为 myapp 的容器,可以执行以下命令
```shell
docker rm myapp
```
如果需要批量删除已停止的容器,可以依次添加多个容器的 ID 或名称,例如
```shell
docker rm container1 container2 ...
```
#### 8删除不再使用的镜像
```shell
docker rmi [IMAGE_ID/IMAGE_NAME]
```
该命令用于删除本地不再需要使用的 Docker 镜像。其中IMAGE_ID/IMAGE_NAME 为要删除的镜像的 ID 或名称。例如,删除镜像 ID 为 `0123456789ab` 的 Docker 镜像,可以执行以下命令
```shell
docker rmi 0123456789ab
```
如果需要删除某个名称的所有镜像,也可以通过名称来删除镜像,例如
```shell
docker rmi myimage
```
如果要删除本地所有不再使用的镜像,可以执行以下命令
```shell
docker rmi $(docker images -f "dangling=true" -q)
```
#### 9进入正在运行的容器
```shell
docker exec -it [CONTAINER_ID/CONTAINER_NAME] /bin/bash
```
该命令用于进入正在运行的 Docker 容器中。其中,`-it` 选项表示以交互式终端方式进入容器,`/bin/bash` 则是指定进入容器后要执行的命令。
例如,进入容器 ID 为 `0123456789ab` 的容器,可以执行以下命令
```shell
docker exec -it 0123456789ab /bin/bash
```
#### 10查看容器日志
```shell
docker logs [CONTAINER_ID/CONTAINER_NAME]
```
该命令用于查看指定 ID 或名称的 Docker 容器的日志输出。例如,查看名称为 myapp 的容器的日志输出,可以执行以下命令
```shell
docker logs myapp
```
## 2、详细命令
### 1、镜像管理
#### 1查看镜像
```shell
docker image is
```
```shell
docker images
```
#### 2检索镜像
```shell
docker search [image]
```
例子
```shell
docker search negix
```
#### 3拉取镜像
```shell
docker pull [image]
```
#### 4上传镜像
```shell
docker push [image]
```
例子
```shell
docker push yovinchen/docker-test:latest
```
#### 5保存镜像
```shell
docker save [image] -o FILE/
```
```shell
docker save [image] >FILE
```
例子
```shell
docker save yovinchen/docker-test:latest >docker-test.tar
```
#### 6导入镜像
```shell
docker load -i FILE
```
例子
```shell
docker load -i hello-docker.tar
```
#### 7查看历史镜像
```shell
docker history [image]
```
#### 8删除镜像
```shell
docker rmi [image]
```
```shell
docker image rm [imaeg]
```
#### 9删除不再使用的镜像
```shell
docker image prune
```
#### 10将文件系统导入为镜像
```shell
docker import [URL/FILE]
```
#### 11从容器创建镜像
```shell
docker commit [container][image]
```
### 2、网络管理
#### 1列出可⽤⽹络
```shell
docker network ls
```
#### 2查看⽹络详细信息
```shell
docker network inspect [network]
```
#### 3创建⼀个新的⽹络
```shell
docker network create [network]
```
#### 4删除⼀个⽹络
```shell
docker network rm [network]
```
#### 5将容器连接到⽹络
```shell
docker network connect [network] [container]
```
#### 6将容器从⽹络断开
```shell
docker network disconnect [network] [container]
```
### 3、插件管理
#### 1列出插件
```shell
docker plugin ls
```
#### 2安装插件
```shell
docker plugin install [plugin]
```
#### 3启⽤插件
```shell
docker plugin enable [plugin]
```
#### 4禁⽤插件
```shell
docker plugin disable [plugin]
```
#### 5卸载插件
```shell
docker plugin rm [plugin]
```
### 4、容器管理
#### 1创建容器仅创建不运行
```shell
docker create [image]
```
#### 2创建并运行容器
```shell
docker run [image]
```
#### 3启动容器
```shell
docker start [container]
```
#### 4停止容器
```shell
docker stop [container]
```
#### 5重启容器
```shell
docker restart [container]
```
#### 6列出正在运行的容器
```shell
docker ps
docker container ls
```
#### 7列出所有容器
```shell
docker ps -a
```
```shell
docker container ls -a
```
#### 8以交互模式进入容器
```shell
docker exec -it [container] bash
```
```shell
docker attach [container]
```
#### 9导出容器快照到文件
```shell
docker export [container] -o FILE
```
```shell
docker export [container] > FILE
```
#### 10导入容器快照
```shell
docker import FILE
```
#### 11查看容器日志
```shell
docker logs [container]
```
#### 12删除容器
```shell
docker rm [container]
```
```shell
docker container rm [container]
```
#### 13查看容器端口映射
```shell
docker port [container]
```
#### 14显示容器内进程
```shell
docker top [container]
```
#### 15复制本地文件到容器内指定路径
```shell
docker cp [FILE] [container]:[PATH]
```
#### 16显示容器内的变化
```shell
docker diff [container]
```
#### 17显示容器资源使用情况
```shell
docker stats [container]
```
### 5、数据卷管理
#### 1创建一个数据卷
```shell
docker volume create [volume]
```
#### 2查看数据卷列表
```shell
docker volume ls
```
#### 3查看数据卷详细信息
```shell
docker volume inspect [volume]
```
#### 4删除数据卷
```shell
docker volume rm [volume]
```
#### 5删除所有未使用的数据卷
```shell
docker volume prune
```
### 6、日常操作
#### 1查看Docker系统信息
```shell
docker info
```
#### 2查看Docker版本
```shell
docker version
```
#### 3查看Docker帮助文档
```shell
docker --help
```
#### 4查看Docker命令帮助
```shell
docker [command] --help
```
#### 5登录DockerHub
```shell
docker login
```
#### 6退出DockerHub
```shell
docker logout
```
### 7、容器运行
语法格式
```shell
docker run [options] image [command] [arg...]
```
#### 1创建运行并命名容器
```shell
shell复制代码docker run --name [name] [image]
```
#### 2创建一个容器并后台运行
```shell
shell复制代码docker run -d [image]
```
#### 3创建一个容器并指定端口映射
```shell
shell复制代码docker run -p [hostPort]:[containerPort] [image]
```
#### 4创建一个容器并随机分配端口映射
```shell
shell复制代码docker run -P [image]
```
#### 5创建一个容器并指定环境变量
```shell
shell复制代码docker run -e [key=value] [image]
```
#### 6创建一个容器并指定工作目录
```shell
shell复制代码docker run -w [PATH] [image]
```
#### 7创建一个容器并指定容器名称
```shell
shell复制代码docker run --name [name] [image]
```
#### 8创建一个容器并在容器中执行命令交互模式
```shell
shell复制代码docker run [image] [command]
```
#### 9创建一个容器并指定容器名称、后台运行、端口映射、环境变量、工作目录
```shell
shell复制代码docker run -d -p [hostPort]:[containerPort] -e [key=value] -w [PATH] --name [name] [image]
```
#### 10使用镜像nginx:latest来启动一个容器并在容器内执行交互式bash shell
```shell
shell复制代码docker run -it nginx:latest /bin/bash
```
#### 11创建一个MySQL容器后台模式启动将主机的80端口映射到容器的80端口将主机的/data目录映射到容器的/data目录
```shell
shell复制代码docker run -it -p 3316:3306 -v /data:/data -d mysql:latest
```
### 8、常用Dockerfile指令
#### 1指定基础镜像必须为Dockerfile的第⼀条指令
```shell
FROM [base_image]
```
#### 2⽤于将⽂件复制到镜像中源可以使URL或者本地⽂件也可以⼀个压缩⽂件⾃动解压
```shell
ADD
```
#### 3⽤于将⽂件拷⻉到镜像中源只能是本地⽂件
```shell
COPY [--chown=<user>:<group>] [源路径] [⽬标路径]
```
#### 4⽤于指定⼯作⽬录可以使⽤多个WORKDIR指令如果使⽤相对路径则是相对于上⼀条WORKDIR指令所指定的⽬录
```shell
WORKDIR [PATH]
```
#### 5⽤于设置环境变量
```shell
ENV <key> <value>
```
```shell
ENV <key1>=<value1> <key2>=<value2> ...
```
#### 6⽤于指定默认的容器主进程每个Dockerfile中只能有⼀条CMD指令如果有多条则只有最后⼀条会⽣效
```shell
CMD <命令>
```
```shell
CMD ["可执⾏⽂件", "参数1", "参数2" ...]
```
#### 7⽤于定义匿名卷持久化⽬录
```shell
VOLUME <路径>
```
```shell
VOLUME ["路径1", "路径2"...]
```

View File

@ -0,0 +1,370 @@
# git基本命令
### 1初始化
初始化设置用户名和邮箱
```shell
git config --global user.name "Your Name"
git config --global user.email email@email.com
git config --global credential.helper store
```
### 2创建仓库
创建一个新的本地仓库(省略<project-name>将在当前目录下创建仓库)
```shell
git init <project-name>
```
下载一个远程仓库
```shell
git clone <url>
```
### 3Git的四个区域
工作区 (working Directory):就是你在电脑⾥能看到的目录
暂存区 (Stage/Index⼀般存放在 .git ⽬录下的index ⽂件,所以我们把暂存区有时也叫作索引 (index)
本地仓库 (Repository⼯作区有⼀个隐藏⽬录git这个不算⼯作区⽽是Git的版本库
远程仓库 (Renote托管在远程服务器上的仓库
### 4Git的三种状态
已修改(nodified):修改了⽂件,但没保存到暂存区
已暂存 (staged把修改后的⽂件放到暂存区
已提交 (Committed):把暂存区的⽂件提交到本地仓库
### 5基本概念
main默认主分⽀
origin默认远程仓库
HEAD :指向当前分⽀的指针
HEAD~:上⼀个版本
HEAD~4上4个版本
### 6特殊文件
.git Git仓库的元数据和对象数据库
.gitignore忽略⽂件不需要提交到仓库的⽂件
.gitattributes指定⽂件的属性⽐如换⾏符
.gitkeep使空⽬录被提交到仓库
.gitmodules记录⼦模块的信息
.gitconfig记录仓库的配置信息
### 7添加和提交
添加一个文件到仓库
```shell
git add <file>
```
添加所有文件到仓库
```shell
git add .
```
提交所有暂存区的文件到仓库
```shell
git commit -m "message"
```
提交已修改的文件到仓库
```shell
git commit -am "message"
```
### 8分支
看所有本地分⽀,当前分⽀前⾯会有⼀个`*``-r`查看远程分⽀,`-a`查看所有分⽀
```shell
git branch
```
创建一个新分支
```shell
git branch <branch-name>
```
切换到制定分支,并更新工作区
```shell
git checkout <branch-name>
```
创建一个新分支,并切换到该分支
```shell
git checkout -b <branch-name>
```
删除一个已经合并的分支
```shell
git branch -d <branch-name>
```
删除一个分支,不管是否合并
```shell
git branch -D <branch-name>
```
给当前的提交打上标签,通常用于版本发布
```shell
git tag <tag-name>
```
### 9合并分支
合并分支a到分支b`-no-ff` 参数表示禁用Fast forward模式合并后的历史有分支能看出曾经做过合并而`-ff`参数表示使用Fast forward模式合井后的历史会变成一条直线
```shell
git merge --no-ff -m "message" <branch-name>
```
```shell
git merge --ff -m "message" <branch-name>
```
合并&squash所有提交到⼀个提交
```shell
git merge --squash <branch-name>
```
ebase不会产⽣新的提交⽽是把当前分⽀的每⼀个提交都 • 复制"到⽬标分⽀上然后再把当前分⽀指向⽬标分⽀⽽merge会产生一个新的提交这个提交有两个分支的所有修改。
### 10Rebase
Rebase操作可以把本地未push的分 叉提交历史整理成直线,看起来更直观。但是,如果多⼈协作时,不要对已经推送到 远程的分⽀执⾏Rebase操作。
```shell
git checkout <dev>
git rebase <main>
```
### 11移动
移动一个文件到新的位置
```shell
git mv <file> <new-file>
```
### 12删除
从工作区和暂存区中删除一个文件,然后暂存删除操作
```shell
git rm <file>
```
只从暂存区中还是拿出一个文件,工作区中的文件没有变化
```shell
git rm --cached <file>
```
### 13撤销
恢复一个文件到之前的版本
```shell
git checkout <file> <commit-id>
```
创建一个新的提交用来撤销指定的提交,后者的所有变化都将被前者抵消,并且应用到当前分支
```shell
git revert <commit-id>
```
重置当前分⽀的HEAD为之前的某个提交并且删除所有之后的提交。`--hard`参数表示重置⼯作区和暂存区,`--soft`参数表示重置暂存区,`--mixed`参数表示重置⼯作区(一般使用之前都先去查询操作查询到需要的`commit-id`才回去进行插销等操作,例如查询操作日志`git reflog`
```shell
git reset --mixed <commit-id>
```
```shell
git reset --hard <commit-id>
```
```shell
git restore --stanged <file>
```
### 14查看
列出还未提交的新的或修改的文件
```shell
git status
```
查看提交历史,`--oneline`可省略
```shell
git log --oneline
```
查看为暂存的文件更新了哪些部分
```shell
git diff
```
查看两个提交之间的差异
```shell
git diff <commit-id> <commit-id>
```
### 15Stash
stash操作可以把当前⼯作现场“储藏"起来,等以后恢复现 场后继续⼯作。`-u`参数表⽰把所有未跟踪的⽂件也⼀并存 `-a`参数表示把所有未跟踪的⽂件和忽略的⽂件也⼀并存储save参数表示存储的信息可以不写。
```shell
git stash save "message"
```
查看所有stash
```shell
git stash list
```
恢复最近一次的stash
```shell
git stash pop
```
恢复指定的stash`stash@{2}`表示第三个stash`stash@{0}`表示最近的stash
```shell
git stash pop stash@{2}
```
重新接受最近一次stash
```shell
git stash apply
```
`pop`和`apply`的区别是,`pop`会把`stash`内容删除,⽽`apply`不会。可以⽤ `git stash drop`来删除 `stash`
```shell
git stash drop stash@{2}
```
删除所有stash
```shell
git stash clear
```
### 16远程仓库
添加远程仓库
```shell
git remote add <remote-name> <remote-url>
```
查看远程仓库
```shell
git remote -v
```
删除远程仓库
```shell
git remote rm <remote-name>
```
重命名远程仓库
```shell
git remote rename <old-name> <new-name>
```
从远程仓库拉取代码
```shell
git pull <remote-name> <branch-name>
```
fetch默认远程仓库origin当前分支的代码然后合并到本地分支
```shell
git pull
```
将本地改动的代码Rebase到远程长裤最新的代码上为了有一个干净的、线性的提交历史
```shell
git pull -rebase
```
推送到远程仓库(然后再发起`pull request`
```shell
git push <remote-name> <branch-name>
```
获取所有远程分支
```shell
git fetch <remote-name>
```
查看远程分支
```shell
git branch -r
```
fetch某一个特定的远程分支
```shell
git fetch <remote-name> <branch-name>
```
### 17Git Flow
GitFlow 是⼀种流程模型,⽤于在 Git 上管理软件开发项⽬。
主分支 (master):代表了项目的稳定版本,每个提交到主分支的代码都应该是经过测试和审核的。
开发分支 (develop):用于日常开发。所有功能分支、发布分支和修补分支都应该从 develop 分支派生。
功能分支 (feature):用于开发单独的功能或特性。每个功能分支应该从 develop 分支派生,并在开发完成后合并回 develop 分支。
发布分支 (release):用于准备项目发布。发布分支应该从 develop 分支派生井在准备好发布版本后合井回master 和develop分支。
修补分支hotfix用于修复主分支上的紧急问题。修补分支应该从 master 分支派生,并在修复完成后合并回 master 和 develop 分支。

View File

@ -0,0 +1,194 @@
# Node 基本命令
### 镜像源
1、查看当前 npm 配置信息。
```shell
npm config list
```
2、查看当前 npm 镜像源地址。
```shell
npm config get registry
```
3、设置 npm 镜像源为指定的地址。其中,`<registry_url>` 为镜像源地址。
```shell
npm config set registry <registry_url>
```
4、设置 npm 镜像源为淘宝镜像源。
```shell
npm config set registry https://registry.npm.taobao.org/
```
5、设置 npm 镜像源为官方源(默认源)。
```shell
npm config set registry https://registry.npmjs.org/
```
6、恢复 npm 镜像源为默认地址。
```shell
npm config delete registry
```
### Node.js
1、查看当前安装的 Node.js 版本号。
```shell
node -v
```
2、运行名为 "app.js" 的 JavaScript 文件(如果文件名不同,则将其替换为相应的文件名)。
```shell
node app.js
```
3、创建一个新的 Node.js 项目。
```shell
npm init
```
4、安装指定名称的软件包。
```shell
npm install <package_name>
```
5、卸载指定名称的软件包。
```shell
npm uninstall <package_name>
```
6、更新所有已安装的软件包。
```shell
npm update
```
7、检查哪些软件包需要更新。
```shell
npm outdated
```
8、列出所有已安装的软件包包括其版本号和依赖项。
```shell
npm list
```
9、启动应用程序。
```shell
npm start
```
10、运行测试该测试通常包含在 package.json 文件中。
```shell
npm test
```
### Vue.js
1、查看当前安装的 Vue.js 版本号。
```shell
vue --version
```
2、创建新的 Vue.js 项目。
```shell
vue create <project_name>
```
3、添加指定插件到 Vue.js 项目中。
```shell
vue add <plugin_name>
```
4、使用图形用户界面管理 Vue.js 项目。
```shell
vue ui
```
5、在开发环境中启动 Vue.js 应用程序并实时重新加载更改。
```shell
vue serve
```
6、生成生产版本的 Vue.js 应用程序。
```shell
vue build
```
7、检查 Vue.js 项目的 webpack 配置。
```shell
vue inspect
```
8、执行 "serve" 命令并启动开发服务器。
```shell
npm run serve
```
9、执行 "build" 命令并生成生产版本的应用程序。
```shell
npm run build
```
10、执行静态代码分析工具 Eslint 进行代码校验。
```shell
npm run lint
```
11、将 Vue CLI 的全局包更新到最新版本。
```shell
vue upgrade
```
12、显示有关本地环境和全局包的详细信息。
```shell
vue info
```
13、使用模板初始化新的 Vue.js 项目。
```shell
vue init
```
14、在文件更改时持续构建应用程序。
```shell
vue build --watch
```
15、启动开发服务器并自动打开浏览器。
```shell
vue serve --open
```

View File

@ -0,0 +1,25 @@
在 HomeBrew 中启动 Redis
```shell
brew services start redis
```
在 HomeBrew 中关闭Redis
```shell
brew services node redis
```
进入 Redis 命令行工具
```shell
redis-cli
```
退出 Redis 命令工具
```shell
quit
```
切换数据库
```sql
select 序号;

View File

@ -0,0 +1,68 @@
# Docker 安装 Mongo
首先安装`Dcoker`没有安装可以参考这篇文章[Docker基本命令](https://blog.hhdxw.top/archives/235)
### 1、查看可用的 Mongo 版本
访间问 Mongo 镜像库地址https://hub.docker.com
也可以用命令来查看
```bash
docker search mongo
```
### 2、拉取指定版本的 Mongo 镜像
这里用最新版
```bash
docker pull mongo:latest
```
### 3、查看本地镜像
用以下命令查看是否安装了Mongo
```bash
docker images
```
### 4、运行容器
```bash
docker run -itd --name mongo -p 27017:27017 mongo
```
- `docker run`:启动一个新的容器。
- `-d`:在后台运行容器。
- `--name mongo`:为容器命名为 `mongo`,以便在进一步操作时可以直接使用这个名称而不是 ID。
- `-p 27017:27017`:将主机的 27017 端口映射到容器内的 27017 端口。
- `mongo:latest`:使用最新版本的 Mongo 镜像。
### 5、安装成功
最后我们可以通过查看运行项
```bash
docker ps
```
命令查看容器的运行信息
### 6、测试
使用
### 7、停止容器
```bash
docker stop mongo
```
### 8、关闭容器
```bash
docker rm mongo
```

View File

@ -0,0 +1,119 @@
# Docker 安装 Mysql
首先安装`Dcoker`没有安装可以参考这篇文章[Docker基本命令](https://blog.hhdxw.top/archives/235)
### 1、查看可用的 Mysql 版本
访间问 Mysql 镜像库地址https://hub.docker.com
也可以用命令来查看
```bash
docker search mysql
```
### 2、拉取指定版本的 Mysql 镜像
这里用最新版
```bash
docker pull mysql:latest
docker pull mysql:8
```
### 3、查看本地镜像
用以下命令查看是否安装了Mysql
```bash
docker images
```
### 4、运行容器
```bash
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:latest
```
- `docker run`:启动一个新的容器。
- `--name mysql`:为容器命名为 `mysql`,以便在进一步操作时可以直接使用这个名称而不是 ID。
- `-p 3306:3306`:将主机的 3306 端口映射到容器内的 3306 端口。
- `-e MYSQL_ROOT_PASSWORD=root`:设置 MySQL 的 root 用户的密码为 `root`。这个设置会被传递给容器内部,并通过环境变量 `MYSQL_ROOT_PASSWORD` 进行读取。
- `-d mysql:latest`:使用 MySQL 的最新版本镜像,并在后台运行容器。
### 5、安装成功
最后我们可以通过查看运行项
```bash
docker ps
```
命令查看容器的运行信息
### 6、开启远程访问
进入容器
```bash
docker exec -it 容器名称|容器id bin/bash
```
登录mysql打开远程访问
1.登录mysql
```bash
mysql -uroot -p
```
2.进行授权
```bash
GRANT ALL ON *.* TO 'root'@'%';\
```
3.刷新权限
```bash
flush privileges;
```
4.加密规则
```bash
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER;
```
5.更新root密码
```bash
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
```
6.刷新权限
```bash
flush privileges;
```
### 6、测试
在 docker 可视化工具里可以直接访问 msyql
例如:[Docker Desktop](https://www.docker.com/products/docker-desktop/)、Docker中的[portainer](https://www.portainer.io/)
或者使用数据库管理工具访问mysql
例如:[Navicat](https://www.navicat.com.cn/)、[WorkBench](https://dev.mysql.com/downloads/workbench/)
### 7、停止容器
```bash
docker stop mysql
```
### 8、关闭容器
```bash
docker rm mysql
```

View File

@ -0,0 +1,78 @@
# Docker 安装 Nginx
首先安装`Dcoker`没有安装可以参考这篇文章[Docker基本命令](https://blog.hhdxw.top/archives/235)
### 1、查看可用的 Nginx 版本
访间问 Nginx 镜像库地址https://hub.docker.com
也可以用命令来查看
```bash
docker search nginx
```
### 2、拉取指定版本的 Nginx 镜像
这里用最新版
```bash
docker pull nginx:latest
```
### 3、查看本地镜像
用以下命令查看是否安装了Nginx
```bash
docker images
```
### 4、运行容器
```bash
docker run -d --name nginx -p 8084:80 nginx
```
- `docker run`:启动一个新的容器。
- `-d`:在后台运行容器。
- `--name nginx`:为容器命名为 `nginx`,以便在进一步操作时可以直接使用这个名称而不是 ID。
- `-p 8084:80`:将主机的 8084 端口映射到容器内的 80 端口。
- `nginx:latest`:使用最新版本的 Nginx 镜像。
### 5、安装成功
最后我们可以通过查看运行项
```bash
docker ps
```
命令查看容器的运行信息
### 6、测试
使用命令
```bash
curl http://localhost:8084/
```
或者在浏览器直接访问
```bash
http://localhost:8084/
```
### 7、停止容器
```bash
docker stop nginx
```
### 8、关闭容器
```bash
docker rm nginx
```

View File

@ -0,0 +1,67 @@
# portainer Docker 可视化工具
首先安装`Dcoker`没有安装可以参考这篇文章[Docker基本命令](https://blog.hhdxw.top/archives/235)
### 1、查看可用的 portaioner 版本
访间问 portaioner 镜像库地址https://hub.docker.com
也可以用命令来查看
```shell
docker search portainer
```
### 2、拉取镜像
```shell
docker pull portainer/portainer
```
### 3、查看本地镜像
```shell
docker images
```
### 4、运行镜像
```she l
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
```
1. `-d` 表示在后台以守护进程的方式运行容器。
2. `-p 8000:8000 -p 9000:9000` 将主机的 8000 和 9000 端口分别映射到容器中的同样的端口让主机可以通过这些端口来访问容器中运行的应用。其中8000 端口是 Portainer 的 Web 界面端口9000 端口是 Portainer API 的端口。
3. `--name=portainer` 指定容器的名称为 portainer方便后面进行管理和操作。
4. `--restart=always` 指定当容器退出时自动重启容器,并且一直保持重启状态,确保容器一直运行。
5. `-v /var/run/docker.sock:/var/run/docker.sock` 把主机上的 Docker sock 文件挂载到容器的同样位置,让端口为 9000 的 Portainer API 可以连接到主机的 Docker 引擎,对 Docker 环境进行管理。
6. `portainer/portainer` 是要运行的镜像名称和版本。
该命令的作用就是在 Docker 中启动一个名为 `portainer` 的容器,然后将主机的端口 8000 和 9000 映射到容器的同样端口,让主机可以通过这些端口来访问运行在容器中的 Portainer Web 界面和 API。而 Portainer 则通过挂载主机上的 Docker sock 文件来获取对 Docker 引擎的访问权限,以便管理 Docker 环境下的容器、镜像和网络等。
### 5、安装成功
最后我们可以通过查看运行项
```bash
docker ps
```
命令查看容器的运行信息
### 6、访问本地链接测试
[localhost:9000](http://localhost:9000/#/auth)
### 7、停止容器
```bash
docker stop portainer/portainer
```
### 8、关闭容器
```bash
docker rm portainer/portainer
```

View File

@ -0,0 +1,102 @@
# RabbitMQ
### 1.查看仓库
```shell
docker search rabbitmq
```
### 2.安装RabbitMQ
```shell
docker pull rabbitmq
```
### 3.启动RabbitMQ
```shell
docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq
```
### 4.安装插件
找到镜像ID
```shell
docker ps
```
进入容器
```shell
docker exec -it 镜像ID /bin/bash
```
安装插件
```shell
rabbitmq-plugins enable rabbitmq_management
```
ctrl+p+q退出当前容器
访问地址
http://服务器IP:15672用户名密码都是`guest`
### 5.踩坑
进入rabbitmq容器
```shell
docker exec -it {rabbitmq容器名称或者id} /bin/bash
```
进入容器后cd到以下路径
```shell
cd /etc/rabbitmq/conf.d/
```
修改 management_agent.disable_metrics_collector = false
```shell
echo management_agent.disable_metrics_collector = false > management_agent.disable_metrics_collector.conf
```
退出容器
```shell
exit
```
重启rabbitmq容器
```shell
docker restart {rabbitmq容器id}
```
### 6.rabbit 创建用户授权
添加用户用户名为root,密码为123456
```shell
rabbitmqctl add_user admin admin
```
赋予root用户所有权限
```shell
rabbitmqctl set_permissions -p / root ".*" ".*" ".*"
```
赋予root用户administrator角色
```shell
rabbitmqctl set_user_tags root administrator
```
查看所有用户
```shell
rabbitmqctl list_users
```

View File

@ -0,0 +1,66 @@
# Docker 安装 Redis
首先安装`Dcoker`没有安装可以参考这篇文章[Docker基本命令](https://blog.hhdxw.top/archives/235)
### 1、查看可用的 Redis 版本
访问 Redis 镜像库地址https://hub.docker.com
也可以用命令来查看
```bash
docker search redis
```
### 2、拉取指定版本的 Redis 镜像,这里安装最新版
```bash
docker pull redis:latest
```
### 3、查看本地镜像
使用以下命令来查看是否已安装了 Redis:
```bash
docker images
```
### 4、运行容器
```bash
docker run -itd --name redis -p 6379:6379 redis
```
- `docker run`:启动一个新的容器。
- `-itd`:在后台运行容器,并开启交互式终端(保持与容器的连接)。
- `--name redis`:为容器命名为 `redis`,以便在进一步操作时可以直接使用这个名称而不是 ID。
- `-p 6379:6379`:将主机的 6379 端口映射到容器内的 6379 端口。
- `redis`:使用 Redis 镜像。
### 5、安装成功
最后我们可以通过查看运行项
```bash
docker ps
```
命令查看容器的运行信息
### 6、客户端链接测试
Redis可视化工具[AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesktopManager/releases)
### 7、停止容器
```bash
docker stop redis
```
### 8、关闭容器
```bash
docker rm redis
```

View File

@ -0,0 +1,71 @@
# Docker 安装 Tomcat
首先安装`Dcoker`没有安装可以参考这篇文章[Docker基本命令](https://blog.hhdxw.top/archives/235)
### 1、查看可用的 Tomcat 版本
访问 Redis 镜像库地址https://hub.docker.com
也可以用命令来查看
```bash
docker search tomcat
```
### 2、拉取指定版本的 Tomcat 镜像,这里安装最新版
```bash
docker pull tomcat:latest
```
### 3、查看本地镜像
使用以下命令来查看是否已安装了 Tomcat:
```bash
docker images
```
### 4、运行容器
```bash
docker run -itd --name my-tomcat -p 8083:8080 tomcat:latest
```
- `docker run`:启动一个新的容器。
- `-itd`:在后台运行容器,并开启交互式终端(保持与容器的连接)。
- `--name tomcat`:为容器命名为 `my-tomcat`,以便在进一步操作时可以直接使用这个名称而不是 ID。
- `-p 8083:8080`:将主机的 8083 端口映射到容器内的 8080 端口。
- `tomcat:latest`:使用 Tomcat 的最新版本镜像。
### 5、安装成功
最后我们可以通过查看运行项
```bash
docker ps
```
命令查看容器的运行信息
### 6、测试
```bash
docker exec -it tomcat /bin/bash
cp -r webapps.dist/* webapps
cd webapps
ls
```
### 7、停止容器
```bash
docker stop tomcat
```
### 8、关闭容器
```bash
docker rm tomcat
```

41
教程/mac命令.md Normal file
View File

@ -0,0 +1,41 @@
| mkdir | 创建一个目录 | mkdir dirname |
| ------ | -------------------- | ---------------- |
| rmdir | 删除一个目录 | rmdir dirname |
| mvdir | 移动或重命名一个目录 | mvdir dir1 dir2 |
| cd | 改变当前目录 | cd dirname |
| pwd | 显示当前目录的路径名 | pwd |
| ls | 显示当前目录的内容 | ls -la |
| dircmp | 比较两个目录的内容 | dircmp dir1 dir2 |
| cat | 显示或连接文件 | cat filename |
| ---- | ---------------------- | ------------------------------------- |
| pg | 分页格式化显示文件内容 | pg filename |
| more | 分屏显示文件内容 | more filename |
| od | 显示非文本文件的内容 | od -c filename |
| cp | 复制文件或目录 | cp file1 file2 |
| rm | 删除文件或目录 | rm filename |
| mv | 改变文件名或所在目录 | mv file1 file2 |
| ln | 联接文件 | ln -s file1 file2 |
| find | 使用匹配表达式查找文件 | find . -name “*.c” -print |
| file | 显示文件类型 | file filename |
| open | 使用默认的程序打开文件 | open filename open . 打开当前目录) |
| head | 显示文件的最初几行 | head -20 filename |
| ----- | ------------------------------ | ---------------------------- |
| tail | 显示文件的最后几行 | tail -15 filename |
| cut | 显示文件每行中的某些域 | cut -f1,7 -d: /etc/passwd |
| colrm | 从标准输入中删除若干列 | colrm 8 20 file2 |
| paste | 横向连接文件 | paste file1 file2 |
| diff | 比较并显示两个文件的差异 | diff file1 file2 |
| sed | 非交互方式流编辑器 | sed “s/red/green/g” filename |
| grep | 在文件中按模式查找 | grep “^[a-zA-Z]” filename |
| awk | 在文件中查找并处理模式 | awk {print 111} filename |
| sort | 排序或归并文件 | sort -d -f -u file1 |
| uniq | 去掉文件中的重复行 | uniq file1 file2 |
| comm | 显示两有序文件的公共和非公共行 | comm file1 file2 |
| wc | 统计文件的字符数、词数和行数 | wc filename |
| nl | 给文件加上行号 | nl file1 >file2 |
mac 快捷键
command + shift + 。 显示隐藏文件夹

View File

@ -0,0 +1,25 @@
# aaPanel-宝塔面板国际版安装教程(宝塔海外版)
## 一、SSH登录至VPS
## 二、执行以下命令安装aaPanel
### CentOS:
```xml
yum install -y wget && wget -O install.sh http://www.aapanel.com/script/install_6.0_en.sh && bash install.sh aapanel
```
### Ubuntu/Deepin
```xml
wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && sudo bash install.sh aapanel
```
### Debian
```xml
wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && bash install.sh aapanel
```
## 三、使用外网面板

View File

@ -0,0 +1,20 @@
![image-20220301090701033](https://gitee.com/hhdxw/tuc/raw/master/img/image-20220301090701033.png)
![image-20220301090804530](https://gitee.com/hhdxw/tuc/raw/master/img/image-20220301090804530.png)
![image-20220301090922200](https://gitee.com/hhdxw/tuc/raw/master/img/image-20220301090922200.png)
![image-20220301091118193](https://gitee.com/hhdxw/tuc/raw/master/img/image-20220301091118193.png)
![image-20220301091611250](https://gitee.com/hhdxw/tuc/raw/master/img/image-20220301091611250.png)
[灰灰](http://localhost:4000/)

View File

@ -0,0 +1,227 @@
services.msc
## mysql无大小写区分
安装目录C:\Program Files\MySQL\MySQL Server 8.0\bin
### 登录命令:
```mysql
mysql -h localhost -u root -p
-h 服务器地址
-u 登录数据库用户名root 管理员)
-p 密码
也可
mysql -u root -p
```
passWord8520
### 展示已存在数据库
```mysql
show databases;
```
### 创建数据库
```mysql
create database jwxt;
```
### 改数据库支持中文字符集
```mysql
set character_set_database='gbk';
set character_set_server='gbk';
```
### 删除数据库(不可恢复,删除之后就没了)
```mysql
drop database 教务系统;
```
### 判断是否执行操作
```mysql
create database if not exists jwxt;
```
### 进入数据库
```mysql
use jwxt;
```
### 字段
```
create table(
ID char(6) not null primary key,
);
字段名 ID
数据类型 char(6)
```
### 联合主键(设置两个以上主键):
```
primary key( stID,kcID )
```
### 约束条件:
| | |
| --------------------------------------------- | -------------- |
| 主键 | primary key, |
| 不允许为空 | null |
| 唯一(设置内容不能重复) | unique |
| 外键 | |
| 自增第一个为1以后自增一般主键设置整数 | auto_increment |
| 默认值 (后面跟默认值) | defult |
### 从表(自表)的外键做为主表(父表)的主键
```mysql
foreign key (从表的外键字段名)
references 主表(字段)
```
### 给外键起名字
```mysql
constraint 名字
```
### 查看表
```mysql
SHOW COLUMNS FROM 表名;
describe 表名;
```
### 创建表
```mysql
create table salary(
employeeid char(6) not null primary key,
income float(8) not null,
outcome float(8) not null
);
```
### 1.修改表名rename
```mysql
alter table salary rename salary2
salary 修改前
salary2 修改后
```
### 2.修改字段的数据类型modify
```mysql
alter table employees modify name varchar(20);
employees 表名
name 字段名
varchar(20) 数据类型
```
### 3.修改字段名change
```mysql
alter table employees change name employees_name varchar(20);
employees 表名
name 修改前字段名
employees_name 修改后字段名
varchar(20) 数据类型
//数据类型不能为空,但是可以和修改前一样,也可同时修改
```
说明change 也可以指修改数据类型,实现和 modify 相同的效果,方法是将 sql 语句中的新字段名和旧字段名设置为相同的名称,只修改数据类型。
### 4.添加字段add
```mysql
alter table salary add shuishou float(8) not null first;
salary 添加的表名
shuishou 添加的字段
float(8) 添加自段的类型
not null 约束条件(包括外键,主键等等)
first 添加表的位置 (可选项)
after 字段名 在字段名之后添加
```
### 5.删除字段 drop
```mysql
alter table salary drop shuishou;
salary 表名
shuishou 字段名
```
### 6.修改字段排列顺序modify
```mysql
alter table salary modify shuishou float after income;
salary 表名
shuishou float 需修改顺序的字段名以及数据类型
income 目标字段之后first最前面
```
### 7.添加外键约束add
```mysql
alter table salary add foreign key (employeeid) references employees (employeeid);
salary 修改表
(employeeid) 字段名
employees 参考主表
(employeeid) 参考主表字段名
```
### 8.添加主键约束add
```
alter table salary add primary key (employeeid) references employees (employeeid);
salary 修改表
(employeeid) 字段名
employees 参考主表
(employeeid) 参考主表字段名
```
### 9.修改表的存储引擎 默认为InnoDB
```mysql
alter table 表名 engine=更改后存储引擎名;
```
注意:外键不能跨引擎使用
### 10.删除外键约束
```mysql
alter table salary drop foreign key 外键名字;
```
若没有命名外键名,则课可以先使用**show create table 表名**查询表的默认外键名,此命令不仅可以查询外键名,还可以查询表的结构、存储引擎、编码方式等信息
查询到默认外键名后再用drop删除即可即 alter table 表名 drop foreign key 查询到的默认外键名;
### 11.删除数据表
```mysql
drop table 表名;
```
**注意:当存在外键约束时,主表不能直接删除,需要先删除外键约束再删表**
### 12.清空表
```
delete from 表名;
```
select * from tmp3

View File

@ -0,0 +1,216 @@
## 一、数据库的操作
首先检查是否有相同名字的数据库,展示数据库中的所含有的数据库的名称
```mysql
show databases;
```
![image-20220308081529937](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308081529937.png)
有名为yggl 的数据库了于是创建名为yggl2 的数据库来完成以下操作。
创建名为yggl2 的数据库
```mysql
create database yggl2;
```
进入数据库 yggl2
```mysql
use yggl2
```
![image-20220308081928547](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308081928547.png)
首先创建主表 departments涉及到外键所以先创建
```mysql
create table departments(
departmentid char(3) not null primary key,
departmentname char(20) not null,
note text(16) null
);
```
如下图,创建完成主表 departments
![image-20220308083216423](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308083216423.png)
然后检查是否创建成功表
```mysql
show tables;
```
![image-20220308083338984](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308083338984.png)
查看 departments 中各字段的内容
```mysql
describe departments;
//也可
desc departments;
```
![image-20220308083540263](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308083540263.png)
创建从表 employees (day中不允许写长度)
```mysql
create table employees(
employeeid char(6) not null primary key,
name char(10) not null,
education char(4) not null,
birthday date not null,
sex char(2) not null,
workyear tinyint(1) null,
address varchar(20) null,
phonenumber char(12) null,
departmentid char(3) not null,
constraint fr_deptid foreign key(departmentid) references departments(departmentid) );
//字段名可以不同,但是数据类型必须一致
//给外键起的名字fr_deptid
```
创建完成如下图:
![image-20220308085743344](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308085743344.png)
创建表 salary
```mysql
create table salary(
employeeid char(6) not null primary key,
income float(8) not null,
outcome float(8) not null
);
```
如图创建成功
![image-20220308090204366](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308090204366.png)
## 二、方法
### 1.修改表名rename
```mysql
alter table salary rename salary2
salary 修改前
salary2 修改后
```
![image-20220308090629743](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308090629743.png)
### 2.修改字段的数据类型modify
```mysql
alter table employees modify name varchar(20);
employees 表名
name 字段名
varchar(20) 数据类型
```
![image-20220308091240600](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308091240600.png)
### 3.修改字段名change
```mysql
alter table employees change name employees_name varchar(20);
employees 表名
name 修改前字段名
employees_name 修改后字段名
varchar(20) 数据类型
//数据类型不能为空,但是可以和修改前一样,也可同时修改
```
![image-20220308094202062](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308094202062.png)
说明change 也可以指修改数据类型,实现和 modify 相同的效果,方法是将 sql 语句中的新字段名和旧字段名设置为相同的名称,只修改数据类型。
### 4.添加字段add
```mysql
alter table salary add shuishou float(8) not null first;
salary 添加的表名
shuishou 添加的字段
float(8) 添加自段的类型
not null 约束条件(包括外键,主键等等)
first 添加表的位置 (可选项)
after 字段名 在字段名之后添加
```
![image-20220308094307879](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308094307879.png)
### 5.删除字段 drop
```mysql
alter table salary drop shuishou;
salary 表名
shuishou 字段名
```
![image-20220308094428794](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308094428794.png)
### 6.修改字段排列顺序modify
```mysql
alter table salary modify shuishou float after income;
salary 表名
shuishou float 需修改顺序的字段名以及数据类型
income 目标字段之后first最前面
```
![image-20220308094400851](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308094400851.png)
### 7.添加外键约束add
```mysql
alter table salary add foreign key (employeeid) references employees (employeeid);
salary 修改表
(employeeid) 字段名
employees 参考主表
(employeeid) 参考主表字段名
```
### 8.添加主键约束add
```
alter table salary add primary key (employeeid) references employees (employeeid);
salary 修改表
(employeeid) 字段名
employees 参考主表
(employeeid) 参考主表字段名
```
### 9.修改表的存储引擎 默认为InnoDB
```mysql
alter table 表名 engine=更改后存储引擎名;
```
注意:外键不能跨引擎使用
### 10.删除外键约束
```mysql
alter table 表名 drop foreign key 外键名字;
```
若没有命名外键名,则课可以先使用**show create table 表名**查询表的默认外键名,此命令不仅可以查询外键名,还可以查询表的结构、存储引擎、编码方式等信息
查询到默认外键名后再用drop删除即可即 alter table 表名 drop foreign key 查询到的默认外键名;
![image-20220308110246033](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308110246033.png)
### 11.删除数据表
```mysql
drop table 表名;
```
**注意:当存在外键约束时,主表不能直接删除,需要先删除外键约束再删表**
![image-20220308110515138](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308110515138.png)

View File

@ -0,0 +1,105 @@
## 数据类型
### 一、数值类型
整形 int(3) ,3表示最多显示的数字个数
浮点型 float(5,1)共有五位有效数字小数点后一位double(5,1)、
定点型decimal(5,1),精度
```mysql
create table tmpl(
x float(5,1),
y double(5,1),
z decimal(5,1)
);
```
### 二、日期时间类型
#### 1year一个字节范围1901-2155
1.四位串或四位数字都可以表示year
2.以两位或一位串表示year'0'-69表示2000-2069年'70'-'99'表示1970-1999年
3.以两位(或一位)数字表示串:**0表示0000**1-69表示2001-2069年70-99表示1970-1999年
#### 2time三个字节范围-838:59:59~+838:59:59
1.HH:MM:SS
2.D HH:MM:SS(D的范围是0-34)
有冒号时:从左向右解释
无冒号时:从右向左解释
按照 天 小时 分钟 秒
3.插入当前时间
```mysql
insert into 表名 values (current_time);
//now 获取日期和时间
insert into 表名 values (now());
```
#### 3date三个字节
1.'YYYY-MM-DD'
2.'YY-MM-DD'
3.YYYYMMDD或者YYMMDD 注意:不能加分隔符
4.当前日期current_date 和now()
#### 4datetime:八个字节
1.'YYYY-MM-DD HH:MM:SS'或者'YYYYMMDDHHMMSS'字符串
2.'YY-MM-DD HH:MM:SS'或者'YYMMDDHHMMSS'字符串
3.YYYYMMDDHHMMSS或者YYMMDDHHMMSS字符串
4.当前日期和时间 now()
#### 5timestamp在 datetime 下增加时区(东八区中国)
```mysql
set time_zone='+10:00';
```
### 三、字符串类型
1.char 和 varchar
char 固定长度字符串,当检索时,尾部的空格会被删除掉
varchar 长度可变的字符串,当检索时,尾部的空格会保留
char(4)内存固定分配四个字节
varchar(4),根据存储内容变化最大为4
2.text:文章内容,评论
3.enum
4.set自动删除重复的
### 四、二进制类型

View File

@ -0,0 +1,235 @@
## 实机操作
进入名为 sys 数据库
```mysql
use sys;
```
创建表 person
```mysql
create table person(
id int not null primary key auto_increment,
name char(40) not null default '',
age int not null default 20,
info char(5) null
);
```
查看数据
```mysql
desc person;
```
![image-20220315081824424](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315081824424.png)
查看表内数据
```mysql
select * from person;
```
![image-20220315082028785](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315082028785.png)
插入数据
```mysql
insert into person (id,name,age,info)
values(1,'Green',21,'lar');
```
查看数据
![image-20220315082524826](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315082524826.png)
插入数据
```mysql
insert into person (id,age,name,info) values(2,22,'su','do');
```
查看数据
![image-20220315082918594](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315082918594.png)
插入数据
```mysql
insert into person values(3,'wang',23,'ji');
```
查看数据
![image-20220315083226414](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315083226414.png)
插入数据
```mysql
insert into person (age,name,info) values(32,'xu','deo');
```
查看数据
![image-20220315083745218](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315083745218.png)
插入指定字段
```mysql
insert into person (age,name,info) values(32,'xu','deo');
insert into person (name,age)values('wan',23);
insert into person (name)values('win');
```
![image-20220315084255104](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315084255104.png)
插入多条数据
```mysql
insert into person (age,name,info)
values(26,'xi','dreo'),
(22,'ju','do'),
(39,'vheng','dxu');
```
![image-20220315085241890](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315085241890.png)
创建新表
```mysql
create table person2(
id int not null primary key auto_increment,
name char(40) not null default '',
age int not null default 20,
info2 char(5) null
);
```
将查询结果插入到表中
```mysql
insert into person2 (id,name,age,info2)
select * from person;
```
![image-20220315090756156](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315090756156.png)、
更新数据
```mysql
update person set age=15,name='liming' where id=9;
```
![image-20220315092323856](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315092323856.png)
查询语句限制
```mysql
select * from person where id=9;
*是指泛指
select name from person where id=9;
```
![image-20220315092608371](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315092608371.png)
![image-20220315092645199](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315092645199.png)
查询年龄在19到25之间的人
```mysql
select * from person where age between 19 and 25;
```
![image-20220315092906118](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315092906118.png)
删除表中 id 为9的人
```mysql
delete from person where id=9;
```
![image-20220315093201546](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315093201546.png)
删除所有表中数据
```mysql
delete from person;
```
![image-20220315093559445](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315093559445.png)
## 一、插入数据
### 1.为表的所有字段插入数据
```mysql
insert into 表名 (字段名,字段名,字段名)
values(对应字段的值,对应字段的值,对应字段的值);
```
备注:允许字段名顺序与建表时顺序不同,不需要按照表定义的顺序插入,只要保证值的顺序和前面字段名的顺序相同即可。
insert into person (id,age,name,info) values(2,22,'su','do');
备注2使用insert语句插入数据时允许将字段名省略此时注意值列类表需要为表中的每一个字段赋值并且值的顺序必须与建表时各个字段的顺序相同。
insert into person (id,age,name,info) values(2,22,'su','do');
### 2.为表指定字段插入数据
为表的指定字段插入数据,就是在 insert 语句中指向部分字段插入值,而其他字段的值为表定义时的默认值。
insert into person (age,name,info) values(32,'xu','deo');
insert into person (name,age)values('wan',23);
insert into person (name)values('win');
备注:要保证每个插入值的类型和对应字段的数据类型保持一致,否则报错
### 3.同时插入多条数据
insert into 表名 (各个字段名) values(第一条记录的值列表), (第二条记录的值列表), (第三条记录的值列表)
例:
```mysql
insert into person (age,name,info)
values(26,'xi','dreo'),
(22,'ju','do'),
(39,'vheng','dxu');
```
### 4.将查询结果插入到表中
语法insert into 新表名(字段名)查询语句;**此处没有values**
注意:两个表的数据类型必须一致,字段个数也要一致。
insert into person2 (id,name,age,info2)select * from person;
## 二、更新数据
update 表名 set 需要更新字段名1=值,需要更新的字段名2=值 where 条件;
补充select 字段名 from 表名 where 条件;
select * from person where age between 19 and 25;
## 三、删除数据(删除操作是不可逆的删除时一点要小心)
1.有选择删除
语法delete from 表名 where 限定条件;
delete from person where id=9;
2.删除表中所有数据
语法delete from 表名;

View File

@ -0,0 +1,616 @@
# 查询数据
## 一、单表查询
### 1.查询所有字段
#### 1在 select 语句中使用 * 查询所有字段
语法select * from 表名;
#### 2在 select 语句中指定所有字段(字段名可以变换顺序)
语法select f_id,s_id,f_name,f_price from fruits;
### 2.查询指定字段
#### 1查询单个字段
语法select f_name from fruits;
#### 2查询多个字段
语法select f_id,s_id,f_name,f_price from fruits;
### 3.查询指定记录where
可以跟 =,>,<,<>,!=,<=,>=,between,and
查询 f_name 是 xxxx 的字段
语法select f_name,f_price from fruits where f_name='xxxx';
查询 f_price 不等于 10.2 的字段
语法select f_name,f_price from fruits where f_price<>10.2;
查询 f_price 在5和10之间的字段
语法select f_name,f_price from fruits where f_price between 5 and 10;**(包含端点值)**
查询 f_price 不在5和10之间的字段
语法select f_name,f_price from fruits where f_price not between 5 and 10;**(不包含端点值)**
### 4.使用in关键字查询
使用 in 关键字将检索条件括起来,检索条件之间用逗号隔开,只需要满足条件范围内一个值即为匹配项。
语法select s_id,f_name,f_price from fruits where s_id in(101,102);
**可以使用关键字 not in 检索不在条件范围内的记录**
语法select s_id,f_name,f_price from fruits where s_id not in(101,103);
### 5.带 like 的字符匹配查询( % _
#### 1%匹配任意长度的字符包括0个字符
以b开头字符查询
语法select f_name,f_price from fruits where f_name like 'b%';
查询水果名中包含p字符的记录
语法select f_name,f_price from fruits where f_name like '%p%';
查询以b开头以y结尾
语法select f_name,f_price from fruits where f_name like 'b%y';
查询以y结尾且y的前面有且仅有4个字母的记录
语法select f_name,f_price from fruits where f_name like '____y';
### 6.查询空值is 【not】null
查询 f_name 为空
语法select f_name,f_price from fruits where f_name is null;
查询 f_name 不为空
语法select f_name,f_price from fruits where f_name is not null;
### 7.带 and 的多条件查询(相当于‘与’,同时满足多个条件)
查询id为101同时价格大于等于5的字段
语法select f_name,f_price from fruits where s_id=101 and f_price>=5;
语法select s_id,f_name,f_price from fruits where s_id=101 and f_price>=5 and f_name like 'a%';
### 8.带 or 的多条件查询(相当于‘或’,满足一个条件即可)
查询i为101或者103的字段
语法select s_id,f_name,f_price from fruits where s_id=101 or s_id=103;
语法select s_id,f_name,f_price from fruits where s_id in(101,103);
这里可以用**in**操作符实现相同功能
**and 的优先级高于 or**
**在实际开发中使用 in 操作符开发语句,更加简单明了,并且 in 执行速度要快于 or ,更重要的是使用 in 操作符,可以执行更加复杂的嵌套查询**
### 9.查询结果不重复distinct
查询 id 不重复
语法select distinct s_id from fruits ;
### 10.对查询结果排序(默认升序【asc】降序【desc】)
#### 1单列排序
升序
语法: select distinct s_id from fruits order by s_id;
降序
语法select distinct s_id from fruits order by s_id desc;
语法select s_id,f_name from fruits order by f_name;
#### 2多列排序
升序
语法select s_id,f_name from fruits order by s_id,f_name;
先按照 s_id 排序, s_id 相同时再按照 s_name 排序
降序
语法select s_id,f_name from fruits order by s_id desc,f_name desc;
### 11.分组查询group by通常和集合函数配合使用
#### 1创建分组
语法select s_id,count(*) from fruits group by s_id;
语法select s_id,count(*) as total from fruits group by s_id;
as 后面是别名
若查看每个供应商提供的水果种类名称可以在group by中使用group_concat()函数,将每个分组中各
个字段的值列举出来例如语法select s_id,group_concat(f_name) from fruits group by s_id;
语法select s_id,group_concat(f_name) as names from fruits group by s_id;
#### 2使用having过滤分组
语法select s_id,group_concat(f_name) as names from fruits group by s_id having count(f_name)>1;、
分组后过滤用having分组前用where进行分组
select s_id,group_concat(f_name) as names from fruits where s_id>=104 group by s_id having count(f_name)>1;
#### 3在group by子句中使用 with rollup
在查出所☐一条记录,该记录出的所有记录的总和
语法: select s_id,count(*) from fruits group by s_id with rollup;
**注意: with rollup和order by不能同时使用互斥**
#### 4多字段分组
语法select s_id,f_name,count(*) from fruits group by s_id,f_name;
#### 5group by 和 order by一起使用
语法select s_id,count(*) from fruits group by s_id order by s_id;
先分组再排序
### 12.使用limit限制查询结果数量
语法select * from fruits limit 4,3;
语法select * from fruits limit 3 offset 4;
4代表是起始位置3是指三条记录
语法: select * from fruits limit 3;
第一个参数(位置偏移量)可以省略不写,表示返回前三条记录
## 二、使用集合函数查询
### 1.count()函数
1select count (*) as name from 表名;
计算表中总行数不管是不是空值
2count(字段名)
计算指定列下的总行数,忽略空值
3和group by关键字一起使用
语法select o_num,count(*) from orderitems group by o_num;
select sum(quantity) from orderitems where o_num=3005;
### 2.sum()函数(求和)
语法select o_num,sum(quantity) from orderitems group by o_num;
### 3.avg()函数(平均值)
语法select o_num,avg(item_price) from orderitems group by o_num;
### 4.max()函数(最大值)
select o_num,max(item_price) from orderitems group by o_num;
### 5.min()函数(最小值)
select o_num,min(item_price) from orderitems group by o_num;
max和min不仅可以对数值类型也可对字符类型求最大最小
## 三、连接查询
语法:
select 查询的列 from 表名 连接类型 表名2 on 连接条件
【where 筛选条件】【group by 分组字段having分组后筛选条件】【order by 排序字段】
### 1.内连接查询inner join=join
不满足 on 后连接条件的会直接过滤掉
select student.name,class.name from student join class on student.class_id=class.id where student.name like '%小%';
也可以自连接
### 2.外连接查询
分为一个主表和一个从表
外连接的查询结果为主表中的所有记录
如果从表中有和它匹配的,则显示匹配结果
如果从表中没有和它匹配的则显示null
#### 1左外连接left outer join=left join
select *from student left join class on student.class_id=class.id;//以左表为主若没有与它匹配的是空
#### 2右外连接right outer join=right join
select *from student right join class on student.class_id=class.id;//以右表为主若没有与它匹配的是空
### 3.符合条件连接查询
select student.name,class.name from student join class on student.class_id=class_id where student.name like "%小%
等价于
select student.name,class.name from student, class where student.class_id=class_id and student.name like %小%
等价于
select student.name,class.name from student join class on student.class_id-class_id and student.name like %小%
seletc * from student as s1 join student as s2 on s1.id=s2.id//自连接
## 四、子查询
## 五、合并查询结果
## 六、为表和字段取别名
## 七、使用正则表达式查询
## 八、综合案例讲解
## 上课代码
```mysql
show database;
use text2;
```
![image-20220317091555230](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317091555230.png)
```mysql
create table fruits(
f_id char(10) not null primary key,
s_id int not null,
f_name char(25) not null,
f_price decimal(8,2) not null
);
desc fruits;
```
![image-20220317091623241](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317091623241.png)
```mysql
insert into fruits
values('a1',101,'apple',10.2),
('b1',101,'blackberry,',5.2),
('bs1',102,'orange',11.2),
('bs2',105,'melon',8.2),
('t1',102,'banana',10.3),
('t2',102,'grape',5.3),
('o2',103,'cocount',9.2),
('c0',101,'chaerry',3.2),
('a2',103,'apricot',2.2),
('i2',104,'lemon',6.2),
('d2',104,'berry',7.6),
('m1',106,'mango',15.6),
('m2',105,'xbabay',2.6),
('t4',107,'xbababa',3.6),
('m3',105,'xxtt',11.6),
('b5',107,'xxx',3.6);
```
![image-20220317092658984](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317092658984.png)
```mysql
select * from fruits;
```
![image-20220317092752192](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317092752192.png)
```mysql
select f_id,s_id,f_name,f_price from fruits;
```
![image-20220317093016313](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317093016313.png)
```mysql
select f_name,f_price from fruits where f_price=10.2;
select f_name,f_price from fruits where f_price>10.2;
select f_name,f_price from fruits where f_price<>10.2;
```
![image-20220317095505644](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317095505644.png)
```mysql
select f_name,f_price from fruits where f_name='xxtt';
```
![image-20220317105627492](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317105627492.png)
```mysql
select f_name,f_price from fruits where f_price between 5 and 10;
```
![image-20220317105740906](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317105740906.png)
```mysql
select s_id,f_name,f_price from fruits where s_id in(101,102);
```
![image-20220317110130236](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317110130236.png)
```mysql
select s_id,f_name,f_price from fruits where s_id not in(101,103);
```
![image-20220317110406931](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317110406931.png)
```mysql
select f_name,f_price from fruits where f_price not between 5 and 10;
```
![image-20220317110825756](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317110825756.png)
```mysql
select f_name,f_price from fruits where f_name like 'b%';
```
![image-20220317111434067](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317111434067.png)
```mysql
select f_name,f_price from fruits where f_name like 'b%y';
```
![image-20220317111958464](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317111958464.png)
```mysql
select f_name,f_price from fruits where f_name like '____y';
```
![image-20220317112329201](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317112329201.png)
```mysql
select f_name,f_price from fruits where f_name is not null;
```
![image-20220317112617170](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317112617170.png)
```mysql
select f_name,f_price from fruits where s_id=101 and f_price>=5;
```
![image-20220317113118208](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317113118208.png)
```mysql
select s_id,f_name,f_price from fruits where s_id=101 and f_price>=5 and f_name like 'a%';
```
![image-20220317113224608](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317113224608.png)
```mysql
select s_id,f_name,f_price from fruits where s_id=101 or s_id=103;
```
![image-20220317113342578](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317113342578.png)
```mysql
select distinct s_id from fruits ;
```
![image-20220317114237840](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317114237840.png)
```mysql
select distinct s_id from fruits order by s_id asc;
select distinct s_id from fruits order by s_id desc;
```
![image-20220317114647937](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317114647937.png)
```mysql
select s_id,f_name from fruits order by f_name;
```
![image-20220317114832832](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220317114832832.png)
```mysql
select s_id,f_name from fruits order by s_id,f_name;
```
![image-20220322072823107](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322072823107.png)
```mysql
select s_id,count(*) from fruits group by s_id;
```
![image-20220322073454144](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322073454144.png)
```mysql
select s_id,count(*) as total from fruits group by s_id;
```
![image-20220322073607034](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322073607034.png)
```mysql
select s_id,group_concat(f_name) from fruits group by s_id;
```
![image-20220322074058744](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322074058744.png)
```mysql
select s_id,group_concat(f_name) as names from fruits group by s_id;
```
![image-20220322074217309](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322074217309.png)
```mysql
select s_id,group_concat(f_name) as names from fruits group by s_id having count(f_name)>1;
```
![image-20220322074314665](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322074314665.png)
```mysql
select s_id,group_concat(f_name) as names from fruits where s_id>=104 group by s_id having count(f_name)>1;
```
![image-20220322075000501](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322075000501.png)
```mysql
select s_id,count(*) from fruits group by s_id with rollup;
```
![image-20220322080606749](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322080606749.png)
```mysql
select s_id,f_name,count(*) from fruits group by s_id,f_name;
```
![image-20220322080806489](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322080806489.png)
```mysql
select s_id,count(*) from fruits group by s_id order by s_id;
```
![image-20220322081315975](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322081315975.png)
```mysql
select * from fruits limit 4,3;
```
![image-20220322081421227](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322081421227.png)
```mysql
create table orderitems(
o_num int not null,
o_item int not null,
f_id char(10) not null,
quantity int not null,
item_price decimal(8,2) not null,
primary key(o_num,o_item)
);
```
![image-20220322083305461](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322083305461.png)
```mysql
insert into orderitems
values(3001,1,'a1',10,5.20),
(3001,2,'b2',3,7.60),
(3001,3,'bs1',5,11.20),
(3001,4,'bs2',15,9.20),
(3002,1,'b3',2,20.00),
(3003,1,'c0',100,10.00),
(3004,1,'o2',50,2.50),
(3005,1,'c0',5,10.00),
(3005,2,'b1',10,8.99),
(3005,3,'a2',10,2.20),
(3005,4,'m1',5,14.99);
```
![image-20220322084023365](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220322084023365.png)
```mysql
create table customers(
c_id int not null auto_increment,
c_name char(50) not null,
c_address char(50) null,
c_city char(50) null,
c_zip char(50) null,
c_contact char(50) null,
c_email char(255) null,
primary key(c_id)
);
```
![image-20220324071225242](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324071225242.png)
```
insert customers values
(1001,'Redhook','200 Street','Tianjin','300000','Liming','Lming@163.com'),
(1002,'Stars','333 Fromage lane','Dalian','116000','Zhangbo','Jerry@hotmail.com'),
(1003,'Netbhood','1 Sunny place','Qingdao','266000','Luocong',''),
(1004,'J0t0','829 Riverside drive','Haikou','570000','Yangshan','sam@hotmail.com')
;
```
![image-20220324071230024](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324071230024.png)
```mysql
select o_num,count(*) from orderitems group by o_num;
```
![image-20220324072908786](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324072908786.png)
```mysql
select sum(quantity) from orderitems where o_num=3005;
```
![image-20220324073307965](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324073307965.png)
```mysql
select o_num,sum(quantity) from orderitems group by o_num;
```
![image-20220324073723595](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324073723595.png)
```mysql
select o_num,avg(item_price) from orderitems group by o_num;
```
![image-20220324074043677](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324074043677.png)
```mysql
select o_num,max(item_price) from orderitems group by o_num;
```
![image-20220324074223916](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324074223916.png)
```mysql
select o_num,min(item_price) from orderitems group by o_num;
```
![image-20220324074228364](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324074228364.png)
```mysql
select min(f_name) from fruits;
```
![image-20220324074524338](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324074524338.png)
```mysql
在fruits中查询不同供应商供应的价格最低的水果
select s_id,min(f_price) from fruits group by s_id;
```
![image-20220324074936488](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324074936488.png)
```mysql
select s_id,min(f_price) from fruits group by s_id order by s_id desc;
```
![image-20220324075020970](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220324075020970.png)
# 底部

View File

@ -0,0 +1,153 @@
# 视图
## 一、视图概述
虚拟表,是从数据库中一个或多个表中导出来的
简单,安全性,权限限制
## 二、创建视图create view
```mysql
create view 视图名 as 查询语句;
示例:
create view vt as select quantity,price,quantity*price from t;
```
![image-20220405082050293](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405082050293.png)
```mysql
create view 视图名(表中列新名称) as 查询语句;
示例:
create view vt2(qty,p,total) as select quantity,price,quantity*price from t;
```
![image-20220405082320391](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405082320391.png)
```mysql
在多个表中创建视图
create view vt4 as select stu.s_id,name,glass from stu join info on stu.s_id=info.a_id;
```
## 三、查看视图
### 1.describe查看视图基本信息
```mysql
desc vt4;
```
![image-20220405084010690](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405084010690.png)
### 2.show table status like'视图名'语句查看视图的基本信息
查询视图信息:
```mysql
show table status like 'vt4';
```
![image-20220405085355433](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405085355433.png)
查询结果comment值为view说明该为视图其他大部分信息为null说明是一个虚表
查询表信息:
```mysql
show table status like'stu';
```
![image-20220405085422810](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405085422810.png)
查询结果包含了存储引擎、行数等信息comment信息为空这是表和视图查询结果的区别
### 3.show create view 视图名:语句查看视图的详细信息(视图名、创建视图的语句等信息)
```mysql
show create view vt4;
```
![image-20220405090735295](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405090735295.png)
### 4.在views表中查询所有视图
```mysql
select * from information_schema.views;
```
## 四、修改视图
### 1.create ro replace view
```mysql
create ro replace view 视图名 as 查询语句;
示例:
create ro replace view vt as select * from t;
```
![image-20220405091444983](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405091444983.png)
### 2.alter view
```mysql
alter view 视图名 as 查询语句;
示例:
alter view vt as select price from t;
```
![image-20220405091450188](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405091450188.png)
###
## 五、更新视图(相当于更新基本表)
# 1.update
```mysql
update 视图名 set 字段名=新值;
示例:(表中数据跟随更改)
update vt set price=30;
```
![image-20220405091758090](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405091758090.png)
### 2.insert
```mysql
insert into 视图名 values(数据);
示例:
insert into vt values(80);
```
![image-20220405092415253](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405092415253.png)
### 3.delect
```mysql
delete from 视图名 where 条件;
示例:
delete from vt where price=80;
```
![image-20220405092640643](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405092640643.png)
## 六、删除视图
```mysql
drop view 视图名;
添加判断
drop view if exists vt;
```
![image-20220405093346162](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405093346162.png)
## 七、综合案例

View File

@ -0,0 +1,150 @@
# 索引
## 一、创建索引
### 1、创建表的同时创建索引
```mysql
create table 表名(
列名 数据类型,
列名 数据类型,
......
[unique/fulltext/spatial] + [index/key] (索引名) (列名[长度]) [ASC/DESC]
)
```
#### (1)普通索引
```mysql
create table book(
bookid int not null,
bookname varchar(255) not null,
author varchar(255) not null,
info varchar(255),
comment varchar(255),
year_publication year not null,
index (year_publication)
//index/key(列名)
);
```
```mysql
show create table book;
```
![image-20220407081946290](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407081946290.png)
```mysql
explain select * from book where year_publication=1990;
//使用explain查看索引是否正在使用重点观察结果中的possible keys和key的值此处都为year_publication说明执行此查询语句时使用了索引
```
![image-20220407082155889](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407082155889.png)
#### (2)唯一索引
```mysql
create table t1(
id int not null,
name char(30) not null,
unique index udid(id)
//unique index 索引名(列名)
//索引名可省略默认名可show create table 展示
);
```
```mysql
show create table t1;
```
![image-20220407082821945](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407082821945.png)
#### (3)组合索引
```mysql
create table t3(
id int not null,
name char(30) not null,
age int not null,
info varchar(255),
index (id,name,age)
);
```
```mysql
explain select * from t3 where id=1 and name='joy';
explain select * from t3 where name='joy';
//查询时,必须遵从最左索引前缀原则
```
![image-20220407084307684](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407084307684.png)
#### (4)全文索引 只为字符charvarchartext索引
```mysql
create table t4(
id int not null,
name char(30),
age int not null,
info varchar(255),
fulltext index (info)
);
```
```mysql
show create table t4;
```
![image-20220407091100882](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407091100882.png)
#### (5)空间索引ENGIN=MyISAM
```mysql
create table t5(
g geometry not null,
spatial index(g)
//只能对一些图形等使用
);
```
### 2、在已经存在的表上创建索引
#### (1)使用alter table
```mysql
alter table 表名 add index【索引名】(列名);
//索引名可以省略,默认为列名
alter table book add index(bookname);
//查询索引
show index from 表名;
```
![image-20220407091751882](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407091751882.png)
#### (2)使用create index
```mysql
create index [索引名] on 表名(列名);
```
## 二、删除索引
### 1、使用alter table
```mysql
alter table 表名 drop index 索引名;
alter table book drop index id;
```
![image-20220407093356011](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407093356011.png)
### 2、使用drop index
```mysql
drop index 索引名 on 表名;
drop index bookname on book;
```
![image-20220407093437374](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407093437374.png)

View File

@ -0,0 +1,76 @@
# 存储过程
## 一、创建存储过程create procedure
### 1.创建无参的存储过程
```mysql
delimiter //
create procedure proc()
begin
select from fruits;
end //
```
```mysql
修改数据库命令结束标志
delimiter //
end //
```
### 2.带输出参数的存储过程
```mysql
delimiter $$
create procedure proc1(out num int)
begin
select count(*)into num from fruits;
end $$
```
### 3.创建带输入输出参数的存储过程
```mysql
delimiter $$
create procedure proc2(in sid int,out n int)
begin
select count(*)into n from fruits where s id=sid;
end$$
```
## 二、调用存储过程call
### 1.调用无参的存储过程
```mysql
call proc();
```
### 2.带输出参数的存储过程
```mysql
call proc(@num);$$
select @num; $$
```
### 3.调用带输入输出参数的存储过程
```mysql
call proc2(101,@n);$$
select @n;$$
```
## 三、删除存储过程
```mysql
drop procedure 存储名
```

View File

@ -0,0 +1,350 @@
# 一、填空题
1. 关系型数据库的标准语言是 **SQL语言**
2. 概念模型中的3种基本联系分别是 **一对一****一对多****多对多**
3. MySQL数据类型中存储整数数值并且占用字节数最小的是 **tinyint**
4. 在 MySql 命令中用于切换到 test 数据库的命令是 **use test**
5. 数据表中字段的主键约束是通过 **primary key** 关键字定义的。
6. 在E-R图中实体使用 **矩形** 图形来表示。
7. 多数据插入时VALUE后的多个值列表之间使用 **,** 分隔。
8. “LIMIT 3,5”表示从第 **3** 条记录开始获取5条记录。
9. 在 WHERE 子句中,关系运算符“<>”与关系运算符 **!=** 等价。
10. 手动刷新权限表的语句是 **flush privileges**
# 二、解答题
### 1.简述关系模型中的表、记录、码、主码的关系。
> 关系模型以二维表存放数据,表中的行称为一个记录、列称为一个字段,如果一个或几个字段组合的值可唯一标识其对应记录,则称该字段或字段组合为码。一个表可能有多个码,通常指定一个码为“主码”。
### 2.为什么需要系统数据库?用户是否可以删除系统数据库?
> 系统数据库是MySQL服务正常运行所依赖的内部库,其中存放有MySQL系统管理的重 要配置信息,若删了它们MySQL服务将无法正常启动和运行,所以用户使用时必须十分小心 避免删除和修改系统数据库。
### 3.简述select语句的from、where、group by及order by子句的作用。
> From 是从哪个表获取数据
>
> Where 数据库操作时添加的条件
>
> Group by 将上面过滤出的数据分组
>
> Order by 用于根据指定的列对结果集进行排序, 默认按照升序对记录进行排序
### 4.索引有哪几类?各类索引的特点是什么?
> 普通索引 没有唯一性之类的限制
>
> 唯一性索引 索引列的值都只能出现一次
>
> 主键索引 只能在主键中创建
>
> 全文索引 只能在字符中使用
>
> 哈希索引 当根据一个值获取一个特定的行时哈希索引非常快
### 5.为什么要在MySQL中设置备份与恢复功能
> 备份和恢复的目的就是将数据库中的数据进行导出,生成副本,然后在系统发生故障后能够恢复全部或部分数据。数据备份就是制作数据库结构、对象和数据的拷贝,以便在数据库遭到破坏时,或因需求改变而需要把数据还原到改变以前时能够恢复数据库。数据恢复就是指将数据库备份加载到系统中。数据备份和恢复可以用于保护数据库的关键数据。在系统发生错误或者因需求改变时,利用备份的数据可以恢复数据库中的数据。
>
> 在数据库遭到破坏时能够修复数据库,也可以用于其他目的。
# 三、设计题
假设有一个企业员工管理的数据库数据库名为yggl包含三个数据表emp(员工表)、dept(部门表)、sal (员工薪水表)。三个数据表的表结构如表1.1、表1.2、表1.3所示数据如表2.1、表2.2、表2.3所示。
用SQL语句完成如下题目。
表1.1emp(员工表)表结构
| 字段名 | 类型(长度) | 是否允许为空值 | 描述 |
| -------- | -------------- | -------------- | ---- |
| 员工编号 | char(6) | × | 主键 |
| 姓名 | char(10) | × | |
| 性别 | tinyint(1) | × | |
| 出生日期 | date(系统默认) | × | |
| 电话号码 | char(12) | √ | |
| 部门编号 | char(3) | × | 外键 |
表1.2dept部门表表结构
| 字段名 | 类型(长度) | 是否允许为空值 | 描述 |
| -------- | ------------ | -------------- | ---- |
| 部门编号 | char(3) | × | 主键 |
| 部门名 | char(20) | × | |
| 备注 | text(16) | √ | |
表1.3sal (员工薪水表)表结构
| 字段名 | 类型(长度) | 是否允许为空值 | 描述 |
| -------- | ------------ | -------------- | ---- |
| 员工编号 | char(6) | × | 主键 |
| 收入 | float(8) | × | |
| 支出 | float(8) | × | |
表2.1emp (员工表)表数据
| 员工编号 | 姓名 | 性别 | 出生日期 | 电话号码 | 部门编号 |
| -------- | ------ | ---- | ---------- | ----------- | -------- |
| 201801 | 王林 | 1 | 1988-09-24 | 15578065678 | 1 |
| 201802 | 张燕 | 0 | 1987-02-26 | 17735468065 | 2 |
| 202003 | 李丽 | 0 | 1990-05-06 | 15133558809 | 3 |
| 202004 | 林涛 | 1 | 1991-02-18 | 18255648765 | 4 |
| 202105 | 王琳琳 | 0 | 1992-05-30 | 15230687685 | 1 |
| 202106 | 李名誉 | 0 | 1992-06-24 | 17335678745 | 3 |
| 202107 | 林_樊 | 1 | 1993-06-20 | 13967094563 | 2 |
| 202108 | 刘明 | 1 | 1993-10-12 | 15587906523 | 4 |
表2.2dept部门表表数据
| 部门编号 | 部门名 | 备注 |
| -------- | ------ | ---- |
| 1 | 财务部 | Null |
| 2 | 人事部 | Null |
| 3 | 行政部 | Null |
| 4 | 科技部 | Null |
表2.3sal (员工薪水表)表数据
| 员工编号 | 收入 | 支出 | 员工编号 | 收入 | 支出 |
| -------- | ---- | ---- | -------- | ---- | ---- |
| 201801 | 2600 | 600 | 202105 | 2600 | 1000 |
| 201802 | 3800 | 1000 | 202106 | 3800 | 1000 |
| 202003 | 2800 | 800 | 202107 | 2800 | 1200 |
| 202004 | 5000 | 1200 | 202108 | 5000 | 1500 |
## SQL语句题目如下
### 1.创建数据库yggl1分
```mysql
create database yggl;
```
### 2.选择数据库yggl1分
```mysql
use yggl;
```
### 3.创建以上三个数据表因为有外键存在注意建表顺序3分
```mysql
create table dept(
部门编号 char(3) not null,
部门名 char(20) not null,
备注 text(16) null,
primary key(部门编号)
);
create table emp(
员工编号 char(6) not null,
姓名 char(10) not null,
性别 tinyint(1) not null,
出生日期 date not null,
电话号码 char(12) null,
部门编号 char(3) not null,
primary key(员工编号),
foreign key(部门编号) references dept(部门编号)
);
create table sal(
员工编号 char(6) not null,
收入 float(8) not null,
支出 float(8) not null,
primary key(员工编号)
);
```
### 4.插入表中所有记录因为有外键存在注意添加数据的顺序3分
```mysql
insert into dept (部门编号,部门名,备注)values
(1,"财务部",Null),
(2,"人事部",Null),
(3,"行政部",Null),
(4,"科技部",Null);
insert into emp (员工编号,姓名,性别,出生日期,电话号码,部门编号)values
(201801,"王林",1,'1988-09-24',15578065678,1),
(201802,"张燕",0,'1987-02-26',17735468065,2),
(202003,"李丽",0,'1990-05-06',15133558809,3),
(202004,"林涛",1,'1991-02-18',18255648765,4),
(202105,"王琳琳",0,'1992-05-30',15230687685,1),
(202106,"李名誉",0,'1992-06-24',17335678745,3),
(202107,"林_樊",1,'1993-06-20',13967094563,2),
(202108,"刘明",1,'1993-10-12',15587906523,4);
insert into sal (员工编号,收入,支出)values
(201801,2600,600),
(202105,2600,1000),
(201802,3800,1000),
(202106,3800,1000),
(202003,2800,800),
(202107,2800,1200),
(202004,5000,1200),
(202108,5000,1500);
```
### 5.数据查询
1查询emp表中所有的记录。2分
```mysql
select * from emp;
```
2查询emp表中的部门编号要求使用distinct消除重复行。2分
```mysql
select distinct 部门编号 from emp;
```
3查询emp表中男员工的姓名和出生日期要求将姓名列显示为name出生日期列显示为birthday。2分
```mysql
select 姓名 as name,出生日期 as birthday from emp where 性别=1;
```
4在sal表中查询收入高于3000的员工号码。2分
```mysql
select 员工编号 from sal where 收入>3000;
```
5查询员工的姓名、收入3000元以下显示为低收入3000~4000元显示为中等收入4000元以上显示为高收入。3分
```mysql
select emp.姓名,sal.收入,
case
when sal.收入<3000 then "低收入"
when sal.收入>=3000 and sal.收入<=4000 then "中等收入"
when sal.收入>4000 then "高收入"
end as "收入等级"
from emp,sal where emp.员工编号=sal.员工编号;
```
6计算所有员工的总支出以及收入的均值。2分
```mysql
select sum(支出),avg(收入) from sal;
```
7查找员工编号倒数第三个数字为1的姓名和电话号码。2分
```mysql
select 姓名,电话号码 from emp where 员工编号 like '%1__';
```
8查找员工的部门编号为2或3的员工的号码。2分
```mysql
select 员工编号,姓名,电话号码 from emp where 部门编号 in(2,3);
```
9查找姓名中含有特殊符号_的学生的基本情况。2分
```mysql
select * from emp where 姓名 like '%\_%';
需要转义字符
select * from emp where 姓名 like '%#_%' escape '#';
```
10将员工的基本信息按年龄从小到大排序。2分
```mysql
select distinct * from emp order by 出生日期 desc;
```
11用子查询的方法查找所有收入在4000元以下的员工的基本情况。3分
```mysql
select * from emp where 员工编号 in(select 员工编号 from sal where 收入<4000);
```
12按部门列出部门名及在该部门工作的员工的人数。3分
```mysql
select dept.部门名,count(emp.部门编号) from dept,emp where dept.部门编号=emp.部门编号 group by emp.部门编号;
```
13查找在科技部的员工的姓名以及收入支出情况。3分
```mysql
select emp.姓名,sal.收入,sal.支出 from emp join sal on emp.员工编号=sal.员工编号 where emp.部门编号=(select 部门编号 from dept where 部门名="科技部");
select emp.姓名,sal.收入,sal.支出 from emp,sal where emp.员工编号=sal.员工编号 and emp.部门编号=(select 部门编号 from dept where 部门名="科技部");
```
### 6.更新数据
1在emp表中将姓名中含有 _ 的学生姓名,去掉 _2分
```mysql
update emp set 姓名="林樊" where 姓名="林_樊";
```
2向dept表中添加记录5,’销售部’,负责推销产品2分
```mysql
insert into dept (部门编号,部门名,备注) values(5,'销售部','负责推销产品');
```
3删除sal表中员工编号 =202004的记录。1分
```mysql
delete from sal where 员工编号=202004;
```
### 7.创建存储过程、调用存储过程
1创建查看emp表中全部信息的存储过程。2分
```mysql
delimiter //
create procedure proc_emp ()
begin
select * from emp;
end //
```
2调用该存储过程。1分
```mysql
call proc_emp;//
```
### 8.创建视图
1在emp表上创建视图view_emp该视图只查看emp表中出生日期在1990年之前的员工的记录。2分
```mysql
create view view_emp as select * from emp where 出生日期<'1990-01-01';
```
2查看视图view_emp的创建语句。1分
```mysql
show create view view_emp;
```
3删除视图view_emp。1分
```mysql
drop view if exists view_emp;
```

View File

@ -0,0 +1,354 @@
# 一、填空题
1.DBMS的中文含义 **数据库管理系统**
2.数据库系统中常用的三种数据模型有: **层次模型,关系模型,网状模型**
3.图书与读者之间是 **多对多** 关系。
4.在 MySql 命令中用于显示xs表表结构的命令是 **desc xs;**
5.Select查询条件可以通过 **where** 控制。
6.数据表中字段的替代键约束是通过 **unique** 关键字定义的。
7.创建索引的三种方式: **创建表时创建****在已有表上创建索引****使用 alter table 语句创建索引**
8.“LIMIT 5,5”表示从第 **6** 条记录开始获取5条记录。
9.在ORDERBY子句中 **asc** 关键字表示升序,是默认值, **desc** 关键字表示降序。
10.SQL语言中用**commit** 语句提交事务,用 **rollback** 语句回滚事务。
# 二、解答题
### 1.简述什么是数据模型?关系模型的特点是什么?
> 数据模型是数据库管理系统对数据库中数据进行存储和管理所依据的逻辑模型。
>
> 关系模型的特点是以记录组或二维数据表的形式组织数据。
### 2.什么是数据库管理系统?
> 数据库管理系统简称DBMS,是指数据库系统中对数据进行管理的软件系统。
### 3.实体间的联系有哪些?请举例说明。
> 一对一、一对多、多对多;
>
> 乘客和座位、班主任和学生、学生和课程。
### 4.举例说明为什么需要视图。
> 提高了安全性能。可以对不同的用户,设定不同的视图。
>
> 例如某用户只能获取user表的name和age数据不能获取sex数据。则可以这样创建视图。
### 5.简述索引的概念与作用。
> 索引是一种使记录有序化的技术,它从逻辑上而不是物理上对记录进行排序。
>
> 索引的主要作用是加快数据查找速度。
>
# 三、设计题
假设有一个学生成绩管理的数据库数据库名为XSCJ包含三个数据表xs(学生表)、kc(课程表)、cj (成绩表)。三个数据表的表结构如表1.1、表1.2、表1.3所示数据如表2.1、表2.2、表2.3所示。
用SQL语句完成如下题目。
表1.1xs(学生表)表结构
| 字段名 | 类型(长度) | 是否允许为空值 | 描述 |
| -------- | -------------- | -------------- | ---- |
| 学生编号 | char(3) | × | 主键 |
| 姓名 | char(10) | × | |
| 性别 | tinyint(1) | × | |
| 出生日期 | date(系统默认) | × | |
表1.2kc课程表表结构
| 字段名 | 类型(长度) | 是否允许为空值 | 描述 |
| -------- | ------------ | -------------- | ---- |
| 课程编号 | char(3) | × | 主键 |
| 课程名 | char(20) | × | |
表1.3cj (成绩表)表结构
| 字段名 | 类型(长度) | 是否允许为空值 | 描述 |
| -------- | ------------ | -------------- | ---- |
| 学生编号 | char(3) | × | 主键 |
| 课程编号 | char(3) | × | 主键 |
| 分数 | float(8) | × | |
表2.1xs (学生表)表数据
| 学生编号 | 姓名 | 性别 | 出生日期 |
| -------- | ---- | ---- | ---------- |
| 01 | 赵雷 | 1 | 2000-01-01 |
| 02 | 钱电 | 1 | 2000-12-01 |
| 03 | 孙风 | 1 | 1999-08-06 |
| 04 | 李云 | 1 | 1999-03-01 |
| 05 | 周梅 | 0 | 2001-05-20 |
| 06 | 吴兰 | 0 | 1998-07-01 |
| 07 | 郑竹 | 0 | 2002-12-21 |
| 08 | 王菊 | 0 | 2000-01-20 |
表2.2kc课程表表数据
| 课程编号 | 课程名 | 课程编号 | 课程名 |
| -------- | ------------- | -------- | ---------- |
| 01 | C语言程序设计 | 05 | 操作系统 |
| 02 | Web应用基础 | 06 | 数据结构 |
| 03 | MySQL数据库 | 07 | 计算机原理 |
| 04 | 离散数学 | 08 | 计算机网络 |
表2.3cj (成绩表)表数据
| 学生编号 | 课程编号 | 分数 | 学生编号 | 课程编号 | 分数 |
| -------- | -------- | ---- | -------- | -------- | ---- |
| 01 | 01 | 90 | 05 | 02 | 87 |
| 01 | 02 | 99 | 06 | 01 | 31 |
| 01 | 03 | 70 | 06 | 04 | 45 |
| 02 | 01 | 80 | 07 | 02 | 89 |
| 02 | 02 | 60 | 07 | 04 | 67 |
| 03 | 01 | 80 | 08 | 02 | 87 |
| 03 | 03 | 80 | 08 | 04 | 88 |
## SQL语句题目如下
### 1.创建数据库XSCJ1分
```mysql
create database XSCJ;
```
### 2.选择数据库XSCJ1分
```mysql
use XSCJ;
```
### 3.创建以上三个数据表3分
```mysql
create table xs(
学生编号 char(3) not null,
姓名 char(10) not null,
性别 tinyint(1) not null,
出生日期 date not null,
primary key (学生编号)
);
create table kc(
课程编号 char(3) not null,
课程名 char(10) not null,
primary key (课程编号)
);
create table cj(
学生编号 char(3) not null,
课程编号 char(3) not null,
分数 float(8) not null,
primary key (学生编号,课程编号)
);
```
### 4.插入表中所有记录3分
```mysql
insert into xs (学生编号,姓名,性别,出生日期) values
(01,'赵雷',1,'2000-01-01'),
(02,'钱电',1,'2000-12-01'),
(03,'孙风',1,'1999-08-06'),
(04,'李云',1,'1999-03-01'),
(05,'周梅',0,'2001-05-20'),
(06,'吴兰',0,'1998-07-01'),
(07,'郑竹',0,'2002-12-21'),
(08,'王菊',0,'2000-01-20');
insert into kc (课程编号,课程名) values
(01,'C语言程序设计'),
(02,'Web应用基础'),
(03,'MySQL数据库'),
(04,'离散数学'),
(05,'操作系统'),
(06,'数据结构'),
(07,'计算机原理'),
(08,'计算机网络');
insert into cj (学生编号,课程编号,分数) values
(01,01,90),
(01,02,99),
(01,03,70),
(02,01,80),
(02,02,60),
(03,01,80),
(03,03,80),
(05,02,87),
(06,01,31),
(06,04,45),
(07,02,89),
(07,04,67),
(08,02,87),
(08,04,88);
```
### 5.数据查询
1查询xs表中所有的记录。2分
```mysql
select * from xs;
```
2查询xs表中性别为男的学生姓名和出生日期要求将姓名列显示为name出生日期列显示为birthday。2分
```mysql
select 姓名 as name ,出生日期 as birthday from xs where 性别=1;
```
3统计学生的总人数显示为学生总数。2分
```mysql
select count(学生编号) as 学生总数 from xs;
```
4查询男生、女生人数。2分
```mysql
select 性别,count(性别) from xs group by 性别;
```
5求选修了01号课程的学生的最高分和最低分。2分
```mysql
select max(分数) as 最高分,min(分数) as 最低分 from cj where 课程编号 = 01;
```
6查询2000年出生的学生名单。2分
```mysql
select 姓名,出生日期 from xs where 出生日期 < '2000-01-01';
```
7查询名字中含有“风”字的学生信息。2分
```mysql
select * from xs where 姓名 like '%风%';
```
8在cj表中查询学生均分高于80分的学生编号。2分
```mysql
select 学生编号,avg(分数) from cj group by 学生编号 having avg(分数) > 80;
```
9查询cj表中学生的学生编号平均分对平均分按如下规则进行替换均分低于60分的显示为不及格在60-70分的显示为及格在70-80分的显示为中等在80-90分的显示为良好90分以上的显示为优秀。3分
```mysql
select 学生编号,
case
when avg(分数)<60 then "不及格"
when avg(分数)>=60 and avg(分数)<70 then "及格"
when avg(分数)>=70 and avg(分数)<80 then "中等"
when avg(分数)>=80 and avg(分数)<90 then "良好"
when avg(分数)>=90 then "优秀"
end as "平均分"
from cj group by 学生编号;
```
10求每门课程的学生人数。2分
```mysql
select kc.课程名,count(cj.学生编号) from kc,cj where kc.课程编号=cj.课程编号 group by cj.课程编号;
```
11查找课程不同、分数相同的学生编号、课程号和分数。3分
```mysql
select c1.* from cj as c1 join cj as c2 on c1.学生编号 = c2.学生编号 and c1.课程编号 != c2.课程编号 and c1.分数 = c2.分数;
select distinct c1.* from cj as c1 join cj as c2 on c1.课程编号 != c2.课程编号 and c1.分数 = c2.分数 ;
```
12查找选修了04号课程的学生姓名和分数。3分
```mysql
select xs.姓名,cj.分数 from xs,cj where cj.课程编号=04 and cj.学生编号=xs.学生编号;
```
13查找选修了课程的学生的学生编号和姓名。3分
```mysql
select distinct cj.学生编号,xs.姓名 from cj,xs where cj.学生编号=xs.学生编号;
```
### 6.更新数据
1在xs表中将周梅的出生日期改为2000-05-202分
```mysql
update xs set 出生日期='2000-05-20' where 姓名='周梅';
```
2向cj表中添加记录04,02,902分
```mysql
insert into cj (学生编号,课程编号,分数) values (04,02,90);
```
3删除kc表中课程编号为0708的记录。1分
```mysql
delete from kc where 课程编号=07 or 课程编号=08;
delete from kc where 课程编号 in (07,08);
```
### 7.创建存储过程、调用存储过程
1创建查看xs表中全部信息的存储过程。2分
```mysql
delimiter //
create procedure proc_xs ()
begin
select * from xs;
end //
```
2调用该存储过程。1分
```mysql
call proc_xs();//
```
### 8.创建视图
1在xs表上创建视图view_xs该视图只查看xs表中出生日期在2000年之前的员工的记录。2分
```mysql
create view view_xs as select * from xs where 出生日期<'2000-01-01';
```
2查看视图view_xs的创建语句。1分
```mysql
show create view view_xs;
```
3删除视图view_xs。1分
```mysql
drop view view_xs;
```

View File

@ -0,0 +1,211 @@
# 综合案例1——数据表的基本操作
在全面介绍了MySQL中数据表的各种操作如创建表、添加各类约束查看表结构以及修改和删除表同学们应该掌握这些基本操作为以后的学习打下坚实的基础。在这里给出一个综合案例让同学们全面回顾一下本章的知识要点并通过这些操作来检验自己是否已经掌握了数据表的常用操作。
## 1、案例目的
创建、修改和删除表,掌握数据表的基本操作。
创建数据库company按照表1和表2给出的表结构在company数据库中创建两个数据表offices和employees按照操作过程完成对数据表的基本操作。
### 表1 offices表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
| ---------- | ------------- | ---- | ---- | ---- | ---- | ---- |
| officecode | int10 | 是 | 否 | 是 | 是 | 否 |
| city | int11 | 否 | 否 | 是 | 否 | 否 |
| address | varchar50 | 否 | 否 | 否 | 否 | 否 |
| country | varchar50 | 否 | 否 | 是 | 否 | 否 |
| postalcode | varchar25 | 否 | 否 | 否 | 是 | 否 |
### 表2 employees表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
| -------------- | -------------- | ---- | ---- | ---- | ---- | ---- |
| employeenumber | int11 | 是 | 否 | 是 | 是 | 是 |
| lastname | varchar50 | 否 | 否 | 是 | 否 | 否 |
| firstname | varchar50 | 否 | 否 | 是 | 否 | 否 |
| mobile | varchar25 | 否 | 否 | 否 | 是 | 否 |
| officecode | int10 | 否 | 是 | 是 | 否 | 否 |
| jobtitle | varchar50 | 否 | 否 | 是 | 否 | 否 |
| birth | datetime | 否 | 否 | 是 | 否 | 否 |
| note | varchar255 | 否 | 否 | 否 | 否 | 否 |
| sex | varchar5 | 否 | 否 | 否 | 否 | 否 |
## 2、案例操作过程
### 1登录MySQL数据库。
```mysql
mysql -h local -u root -p
```
截图:
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wpsD882.tmp.jpg)
### 2创建数据库company并选择使用此数据库。
```mysql
create database company;
use company;
```
截图:
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wpsD883.tmp.jpg)
### 3创建表offices创建成功后用desc查看表结构。
```mysql
create table offices(
officecode int(10) not null unique primary key,
city int(11) not null ,
address varchar(50) null ,
country varchar(50) not null,
postalcode varchar(25) null unique
);
desc offices;
```
截图:
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wpsD884.tmp.jpg)
### 4创建表employees创建成功后用desc查看表结构。
```mysql
create table employees(
employeenumber int(11) not null unique auto_increment primary key,
lastname varchar(50) not null,
firstname varchar(50) not null,
mobile varchar(25) null unique,
officecode int(10) not null ,
birth datetime not null,
note varchar(255) null,
sex varchar(5) null,
foreign key(officecode) references offices(officecode)
);
```
截图:
![image-20220308170243379](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308170243379.png)
### 5使用show tables命令查看数据库中的表。
```mysql
show tables
```
截图:
![image-20220308170414341](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308170414341.png)
### 6将表employees的mobile字段修改到officecode字段后面成功后使用desc查看修改后的表结构。
```mysql
alter table employees modify mobile varchar(25) after officecode;
desc employees;
```
截图:
![image-20220308170720963](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308170720963.png)
### 7将表employees的birth字段名改为employee_birth成功后使用desc查看修改后的表结构。
```mysql
alter table employees change birth employees_birth datetime;
desc employees;
```
截图:
![image-20220308171008325](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308171008325.png)
### 8修改sex字段数据类型为char(1)非空约束成功后使用desc查看修改后的表结构。
```mysql
alter table employees modify sex char(1) not null;
desc employees;
```
截图:
![image-20220308171528384](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308171528384.png)
### 9删除字段note成功后使用desc查看修改后的表结构。
```mysql
alter table employees drop note;
desc employees;
```
截图:
![image-20220308171326509](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308171326509.png)
### 10增加字段名favoriate_activity数据类型为varchar(100) 成功后使用desc查看修改后的表结构。
```mysql
alter table employees add favoriate_activity varchar(100);
desc employees;
```
截图:
![image-20220308171746485](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308171746485.png)
### 11删除表offices操作成功后用show tables查看数据库中的表。
```mysql
drop table offices;
alter table employees drop foreign key employees_ibfk_1;
drop table offices;
show tables;
```
截图:
![image-20220308172132982](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308172132982.png)
### 12修改表employees存储引擎为myisam执行成功后用show create table语句查看表结构。
```mysql
alter table employees engine = myisam;
show create table employees;
```
截图:
![image-20220308172645359](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308172645359.png)
### 13将表employees名称修改为employees_info执行成功后用show tables查看数据库中的表。
```mysql
alter table employees rename employees_info;
show tables;
```
截图:
![image-20220308172838692](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220308172838692.png)

View File

@ -0,0 +1,191 @@
# 综合案例2-记录的插入、更新和删除
本部分内容重点介绍了数据表中数据的插入、更新和删除操作。MySQL中可以灵活的对数据进行插入与更新MySQL中对数据的操作没有任何提示因此在更新和删除数据时一定要谨慎小心查询条件一定要准确避免造成数据的丢失。此综合案例包含了对数据表中数据的基本操作包括记录的插入、更新和删除。
## 1、案例目的
创建表books对数据表进行插入、更新和删除操作掌握表数据的基本操作。books表结构以及表中的记录如表1和表2所示
表1 books表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 | 字段说明 |
| ------- | -------------- | ---- | ---- | ---- | ---- | ---- | -------- |
| b_id | int11 | 是 | 否 | 是 | 是 | 否 | 书编号 |
| b_name | varchar50 | 否 | 否 | 是 | 否 | 否 | 书名 |
| authors | varchar100 | 否 | 否 | 是 | 否 | 否 | 作者 |
| price | float | 否 | 否 | 是 | 否 | 否 | 价格 |
| pubdate | year | 否 | 否 | 是 | 是 | 否 | 出版日期 |
| note | varchar100 | 否 | 否 | 否 | 否 | 否 | 说明 |
| num | int11 | 否 | 否 | 是 | 否 | 否 | 库存量 |
表2 books表中的记录
| b_id | b_name | authors | price | pubdate | note | num |
| ---- | ------------- | --------------- | ----- | ------- | -------- | ---- |
| 1 | Tale of AAA | Dickes | 23 | 1995 | novel | 11 |
| 2 | EmmaT | Jane lura | 35 | 1993 | joke | 22 |
| 3 | Story of Jane | Jane Tim | 40 | 2001 | novel | 0 |
| 4 | Lovey Day | George Byron | 20 | 2005 | novel | 30 |
| 5 | Old Land | Honore Blade | 30 | 2010 | law | 0 |
| 6 | The Battle | Upton Sara | 30 | 1999 | medicine | 40 |
| 7 | Rose Hood | Richard Haggard | 28 | 2008 | cartoon | 28 |
## 2、案例操作过程
1登录MySQL数据库。
```mysql
mysql -h localhost -u root -p
```
截图:
![img](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/wps4BC6.tmp.jpg)
2创建数据库M_BOOK并选择使用此数据库。
```mysql
create database M_BOOK;
desc M_BOOK;
```
截图:
![image-20220315141208398](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315141208398.png)
3按照表1创建表books创建成功后用desc查看表结构。
```mysql
create table books(
b_id int(11) not null unique,
b_name varchar(50) not null,
authors varchar(100) not null,
price float not null,
pubdate year not null unique,
note varchar(100) null,
num int(11) not null,
primary key(b_id)
);
```
截图:
![image-20220315142332615](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315142332615.png)
4使用select语句查询表中的数据此处查询结果应为空
```mysql
select * from books;
```
截图:
![image-20220315142310880](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315142310880.png)
5将表2中的记录插入到books表中分别使用不同的方法插入记录。
①指定所有字段名插入第1行记录插入后用select语句查询插入结果
```mysql
insert into books (b_id,b_name,authors,price,pubdate,note,num) values(1,'Tale of AAA','DIckes',23,1995,'novel',11);
select * from books;
```
截图:
![image-20220315142912049](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315142912049.png)
②不指定字段名插入第2行记录插入后用select语句查询插入结果
```mysql
insert into books values(2,'EmmaT','Jane lura',35,1993,'joke',22);
select * from books;
```
截图:
![image-20220315143315288](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315143315288.png)
③同时插入第3~7行记录插入后用select语句查询插入结果
```mysql
insert into books (b_id,b_name,authors,price,pubdate,note,num)
values (3,'Story of Jane','Jane Tim',40,2001,'novel',0),
(4,'Lovey Day','George Byron',20,2005,'novel',30),
(5,'Old Land','Honore Blade',30,2010,'law',0),
(6,'The Battle','Upton Sara',30,1999,'medicine',40),
(7,'Rose Hood','Richard Haggard',28,2008,'cartoon',28);
```
截图:
![image-20220315144009242](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315144009242.png)
6使用select语句查询小说类型novel的书的所有信息。
```mysql
select * from books where note='novel';
```
截图:
![image-20220315144355595](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315144355595.png)
7将小说类型novel的书的价格都增加5并在更新后使用select语句查询小说类型novel的书的所有信息
```mysql
update books set price=price+5 where note='novel';
select * from books where note='novel';
```
截图:
![image-20220315145957535](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315145957535.png)
8使用select语句查看书名为EmmaT的信息
```mysql
select * from books where b_name='EmmaT';
```
截图:
![image-20220315150138907](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315150138907.png)
9将名为EmmaT的书价格改为40并使用select语句查询更新后的该书信息。
```mysql
update books set price=40 where b_name='EmmaT';
select * from books where b_name='EmmaT';
```
截图:
![image-20220315150252053](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315150252053.png)
10查询库存量为0的书的所有信息。
```mysql
select * from books where num=0;
```
截图:
![image-20220315150322666](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315150322666.png)
11删除库存量为0的书的所有信息并使用select语句查询库存量为0的书的所有信息此处应为空
```mysql
delete from books where num=0;
select * from books where num=0;
```
截图:
![image-20220315150431488](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220315150431488.png)

View File

@ -0,0 +1,291 @@
# 综合案例3——数据表查询操作
SQL语句可以分为两部分一部分用来创建数据库对象另一部分用来操作这些对象本部分内容详细介绍了操作数据库对象的数据表查询语句。通过部分内容的介绍同学们可以了解到SQL中的查询语言功能的强大用户可以根据需要灵活使用。此综合案例将回顾这些查询语句。
## 1、案例目的
根据不同条件对表进行查询操作掌握数据表的查询语句。employee、dept表结构以及表中的记录如表1~表4所示。
表1 employee表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 | 字段说明 |
| -------- | ------------- | ---- | ---- | ---- | ---- | ---- | -------- |
| e_no | int11 | 是 | 否 | 是 | 是 | 否 | 员工编号 |
| e_name | varchar50 | 否 | 否 | 是 | 否 | 否 | 员工姓名 |
| e_gender | char2 | 否 | 否 | 否 | 否 | 否 | 员工性别 |
| dept_no | int11 | 否 | 是 | 是 | 否 | 否 | 部门编号 |
| e_job | varchar50 | 否 | 否 | 是 | 否 | 否 | 职位 |
| e_salary | int11 | 否 | 否 | 是 | 否 | 否 | 薪水 |
| hiredate | date | 否 | 否 | 是 | 否 | 否 | 入职日期 |
表2 dept表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 | 字段说明 |
| ---------- | -------------- | ---- | ---- | ---- | ---- | ---- | -------- |
| d_no | int11 | 是 | 否 | 是 | 是 | 是 | 部门编号 |
| d_name | varchar50 | 否 | 否 | 是 | 否 | 否 | 部门姓名 |
| d_location | varchar100 | 否 | 否 | 否 | 否 | 否 | 部门地址 |
表3 employee表中的记录
| e_no | e_name | e_gender | dept_no | e_job | e_salary | hiredate |
| ---- | ------ | -------- | ------- | --------- | -------- | ---------- |
| 1001 | Smith | m | 20 | clerk | 800 | 2005-11-12 |
| 1002 | Allen | f | 30 | salesman | 1600 | 2003-05-12 |
| 1003 | Ward | f | 30 | salesman | 1250 | 2003-05-12 |
| 1004 | Jones | m | 20 | manager | 2975 | 1998-05-18 |
| 1005 | Martin | m | 30 | salesman | 1250 | 2001-06-12 |
| 1006 | Blake | f | 30 | manager | 2850 | 1997-02-15 |
| 1007 | Clark | m | 10 | manager | 2450 | 2002-09-12 |
| 1008 | Scott | m | 20 | analyst | 3000 | 2003-05-12 |
| 1009 | King | f | 10 | president | 5000 | 1995-01-01 |
| 1010 | Turner | f | 30 | salesman | 1500 | 1997-10-12 |
| 1011 | Adams | m | 20 | clerk | 1100 | 1999-10-05 |
| 1012 | James | f | 30 | clerk | 950 | 2008-06-15 |
表4 dept表中的记录
| d_no | d_name | d_location |
| ---- | ---------- | ---------- |
| 10 | accounting | ShangHai |
| 20 | research | BeiJing |
| 30 | sales | ShenZhen |
| 40 | operations | FuJian |
## 2、案例操作过程
1登录MySQL数据库。
```mysql
mysql -h localhost -u root -p
```
截图:
![image-20220329093954268](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329093954268.png)
2创建数据库MANGER并选择使用此数据库。
```mysql
create database MANGER;
use MANGER;
```
截图:
![image-20220329094314369](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329094314369.png)
3按照表1、表2创建表employee和dept创建成功后用desc查看表结构。
```mysql
create table dept(
d_no int(11) not null unique auto_increment,
d_name varchar(50) not null,
d_location varchar(100) null,
primary key(d_no)
);
desc dept;
```
```mysql
create table employee(
e_no int(11) not null unique,
e_name varchar(50) not null,
e_gender char(2) null,
dept_no int(11) not null,
e_job varchar(50) not null,
e_salary int(11) not null,
hiredate date not null,
primary key(e_no),
foreign key (dept_no)references dept(d_no)
);
desc employee;
```
截图:
![image-20220329094933122](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329094933122.png)
![image-20220329101229507](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329101229507.png)
4将表3、表4的记录分别插入两个表中。
```mysql
insert into dept (d_no,d_name,d_location)
values(10,'accounting','ShangHai'),
(20,'research','BeiJing'),
(30,'sales','ShenZhen'),
(40,'operations','FuJian');
```
```mysql
insert into employee (e_no,e_name,e_gender,dept_no,e_job,e_salary,hiredate)
values(1001,'Smith','m',20,'clerk',800,'2005-11-12'),
(1002,'Allen','f',30,'salesman',1600,'2003-05-12'),
(1003,'Ward','f',30,'salesman',1250,'2003-05-12'),
(1004,'Jones','m',20,'manager',2975,'1998-05-18'),
(1005,'Martin','m',30,'salesman',1250,'2001-06-12'),
(1006,'Blake','f',30,'manager',2850,'1997-02-15'),
(1007,'Clark','m',10,'manager',2450,'2002-09-12'),
(1008,'Scott','m',20,'analyst',3000,'2003-05-12'),
(1009,'King','f',10,'president',5000,'1995-01-01'),
(1010,'Turner','f',30,'salesman',1500,'1997-10-12'),
(1011,'Adams','m',20,'clerk',1100,'1999-10-05'),
(1012,'James','f',30,'clerk',950,'2008-06-15');
```
截图:
![image-20220329155245302](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329155245302.png)
![image-20220329155332888](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329155332888.png)
5在employee表中查询所有记录的e_no、e_name和e_salary字段值。
```mysql
select e_no,e_name,e_salary from employee;
```
截图:
![image-20220329155628020](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329155628020.png)
6在employee表中查询dept_no等于10和20的所有记录。
```mysql
select * from employee where dept_no=10 or dept_no=20;
```
截图:
![image-20220329155759471](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329155759471.png)
7在employee表中查询工资范围在800~2500之间的员工信息。
```mysql
select * from employee where e_salary>=800 and e_salary<=2500;
```
截图:
![image-20220329155930614](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329155930614.png)
8在employee表中查询部门编号为20的部门中的员工所有信息。
```mysql
select * from employee where dept_no=20;
```
截图:
![image-20220329160154098](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329160154098.png)
9在employee表中查询每个部门最高工资的员工信息。
```mysql
select *,max(e_salary) from employee group by dept_no;
```
截图:
![image-20220329160825143](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329160825143.png)
10查询员工Blake所在部门编号和部门所在地。
```mysql
select d_name,d_location from dept as de where de.d_no=(select dept_no from employee where e_name='Blake');
```
截图:
![image-20220329164419168](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329164419168.png)
11使用连接查询查询所有员工的部门和和部门信息。
```mysql
select * from employee as em,dept as de where de.d_no=em.dept_no;
```
截图:
![image-20220329163914411](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329163914411.png)
12在employee表中计算每个部门各有多少名员工。
```mysql
select count(e_name),dept_no from employee group by dept_no;
```
截图:
![image-20220329164610824](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329164610824.png)
13在employee表中计算不同类型职工的总工资数。
```mysql
select e_job,sum(e_salary) from employee group by e_job;
```
截图:
![image-20220329161757013](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329161757013.png)
14在employee表中计算不同部门的平均工资。
```mysql
select dept_no,avg(e_salary) from employee group by dept_no;
```
截图:
![image-20220329162920630](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329162920630.png)
15在employee表中查询工资低于1500的员工信息。
```mysql
select * from employee where e_salary<1500;
```
截图:
![image-20220329163014313](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329163014313.png)
16在employee表中将查询记录先按部门编号由高到低排列若部门相同再按员工工资由高到低排列。
```mysql
select * from employee order by dept_no desc,e_salary desc;
```
截图:
![image-20220329165111978](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329165111978.png)
17在employee表中查询员工姓名以字母A或S开头的员工信息。
```mysql
select * from employee where e_name like 'A%' or e_name like 'S%';
```
截图:
![image-20220329163253424](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329163253424.png)
18在employee表中查询到目前为止工龄大于等于20年的员工信息。
```mysql
select * from employee as em where (select year(now())-(select year(em.hiredate)))>20;
```
截图:
![image-20220329165903364](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220329165903364.png)

View File

@ -0,0 +1,230 @@
# 综合案例4——视图应用
本部分介绍了MySQL数据库中视图的含义和作用并且讲解了创建视图、修改视图和删除视图的方法。创建视图和修改视图是重点希望同学们认真学习这两部分内容并在计算机上进行操作。同学们在创建视图后一定要查看视图的结构确保创建的视图是正确的修改视图后也要查看视图的结构保证修改是正确的。
## 1、案例目的
掌握视图的创建、查询、更新和删除操作。
假如河南河北有三个学生参加了清华、北大的自学考试现在需要用数据对其考试结果进行查询和管理清华的分数线是40北大的分数线是41.学生表包含了学生的学号、姓名、家庭地址和电话号码报名表包含学号、姓名、所在学校和报名的学校表结构以及表中的内容分别如表1~表6所示。
表1 stu表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
| ------ | ------------- | ---- | ---- | ---- | ---- | ---- |
| 序号 | int11 | 是 | 否 | 是 | 是 | 否 |
| 姓名 | varchar20 | 否 | 否 | 是 | 否 | 否 |
| 地址 | varchar50 | 否 | 否 | 是 | 否 | 否 |
| 电话 | varchar50 | 否 | 否 | 是 | 否 | 否 |
表2 sign表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
| -------- | ------------- | ---- | ---- | ---- | ---- | ---- |
| 序号 | int11 | 是 | 否 | 是 | 是 | 否 |
| 姓名 | varchar20 | 否 | 否 | 是 | 否 | 否 |
| 学校 | varchar50 | 否 | 否 | 是 | 否 | 否 |
| 报名学校 | varchar50 | 否 | 否 | 是 | 否 | 否 |
表3 stu_mark表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
| ------ | ------------- | ---- | ---- | ---- | ---- | ---- |
| 序号 | int11 | 是 | 否 | 是 | 是 | 否 |
| 姓名 | varchar20 | 否 | 否 | 是 | 否 | 否 |
| 分数 | int11 | 否 | 否 | 是 | 否 | 否 |
表4 stu表内容
| 序号 | 姓名 | 地址 | 电话 |
| ---- | ---- | ---- | ------------- |
| 1 | 小王 | 河南 | 0317-12345678 |
| 2 | 小李 | 河北 | 13889072345 |
| 3 | 小田 | 河南 | 0317-12345670 |
表5 sign表内容
| 序号 | 姓名 | 学校 | 报名学校 |
| ---- | ---- | ----- | -------- |
| 1 | 小王 | 中学1 | 北大 |
| 2 | 小李 | 中学2 | 清华 |
| 3 | 小田 | 中学3 | 清华 |
表6 stu_mark表中的记录
| 序号 | 姓名 | 分数 |
| ---- | ---- | ---- |
| 1 | 小王 | 80 |
| 2 | 小李 | 71 |
| 3 | 小田 | 70 |
## 2、案例操作过程
1登录MySQL数据库。
```mysql
mysql -u root -p
```
截图:
![image-20220405094500300](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405094500300.png)
2创建数据库stu_exam并选择使用此数据库。
```mysql
create database stu_exam;
use stu_exam;
```
截图:
![image-20220405094539472](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405094539472.png)
3按照表1、表2、表3创建表创建成功后用desc查看表结构。
```mysql
create table stu(
序号 int(11) not null unique,
姓名 varchar(20) not null,
地址 varchar(50) not null,
电话 varchar(50) not null,
primary key(序号)
);
```
```mysql
create table sign(
序号 int(11) not null unique,
姓名 varchar(20) not null,
学校 varchar(50) not null,
报名学校 varchar(50) not null,
primary key(序号)
);
```
```mysql
create table stu_mark(
序号 int(11) not null unique,
姓名 varchar(20) not null,
分数 int(11) not null,
primary key(序号)
);
```
截图:
![image-20220405160214782](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405160214782.png)
4将表4、表5、表6的记录分别插入三个表中。
```mysql
insert into stu values
(1,'小王','河南','0317-12345678'),
(2,'小李','河北','13889072345'),
(3,'小田','河南','0317-12345670');
```
```mysql
insert into sign values
(1,'小王','中学1','北大'),
(2,'小李','中学2','清华'),
(3,'小田','中学3','清华');
```
```mysql
insert into stu_mark values
(1,'小王',80),
(2,'小李',71),
(3,'小田',70);
```
截图:
![image-20220405161410429](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405161410429.png)
5创建考上北大的学生视图视图中包含序号、姓名、分数和报名学校
```mysql
create view 北大
(序号,姓名,分数,报名学校) as
select stu_mark.序号,stu_mark.姓名,stu_mark.分数,sign.报名学校
from stu_mark,sign
where stu_mark.序号=sign.序号 and sign.报名学校='北大' and stu_mark.分数>=41;
```
截图:
![image-20220406200815038](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220406200815038.png)
6创建考上清华的学生视图视图中包含序号、姓名、分数和报名学校
```mysql
create view 清华
(序号,姓名,分数,报名学校) as
select stu_mark.序号,stu_mark.姓名,stu_mark.分数,sign.报名学校
from stu_mark,sign
where stu_mark.序号=sign.序号 and sign.报名学校='清华' and stu_mark.分数>=40;
```
截图:
![image-20220406201123556](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220406201123556.png)
7小田的成绩在录入的时候录入错误多录了50分对其录入成绩进行更新。
```mysql
update 清华 set 分数=分数-50 where 姓名='小田';
```
截图:
![image-20220405163009861](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405163009861.png)
8查询更新过后的视图和表的情况。
```mysql
select * from 清华;
select * from stu_mark;
```
截图:
![image-20220406201156824](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220406201156824.png)
9查看视图的创建信息。
```mysql
show table status like '北大';
show table status like '清华';
```
截图:
![image-20220405163228521](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405163228521.png)
10删除创建的视图。
```mysql
drop view 北大;
drop view if exists 清华;
```
截图:
![image-20220405163346868](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220405163346868.png)

View File

@ -0,0 +1,149 @@
# 综合案例5——索引
本部分介绍了什么是索引以及索引的种类及各种索引的创建方法如建表的同时创建索引、使用alter table或create index语句创建索引。索引是提高数据库性能的一个强有力的工具因此同学们要掌握好索引的创建。
## 1、案例目的
创建数据库index_test按照下面表结构在index_test数据库中创建两个数据表test_table1和test_table2如表1表2所示并按照操作过程完成对数据表的基本操作。
表1 test_table1表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
| ----------- | ----------- | ---- | ---- | ---- | ---- | ---- |
| id | int11 | 否 | 否 | 是 | 是 | 是 |
| name | char100 | 否 | 否 | 是 | 否 | 否 |
| address | char100 | 否 | 否 | 否 | 否 | 否 |
| description | char100 | 否 | 否 | 否 | 否 | 否 |
表2 test_table2表结构
| 字段名 | 数据类型 | 主键 | 外键 | 非空 | 唯一 | 自增 |
| ---------- | ----------- | ---- | ---- | ---- | ---- | ---- |
| id | int11 | 是 | 否 | 是 | 是 | 否 |
| firstname | char50 | 否 | 否 | 是 | 否 | 否 |
| middlename | char50 | 否 | 否 | 是 | 否 | 否 |
| lastname | char50 | 否 | 否 | 是 | 否 | 否 |
| birth | date | 否 | 否 | 是 | 否 | 否 |
| title | char100 | 否 | 否 | 否 | 否 | 否 |
## 2、案例操作过程
1登录MySQL数据库。
```mysql
mysql -u root -p
```
截图:
2创建数据库index_test并选择使用此数据库。
```mysql
create database index_test;
use index_test;
```
截图:
![image-20220407094114402](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407094114402.png)
3按照表1创建test_table1表并在建表的同时创建如下索引在id上创建名称为UniqIdxid的唯一索引在name(长度20),address(长度30)上创建名称为MultiColIdx的组合索引在description(长度30)上创建名称为ComIdx的普通索引。
```mysql
create table test_table1(
id int (11) not null unique auto_increment,
name char(100) not null,
address char(100),
description char(100),
unique index UniqIdx(id),
index MultiColIdx(name(20),address(30)),
index ComIdx(description(30))
);
```
截图:
![image-20220407101245380](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407101245380.png)
4使用show语句查看索引信息。
```mysql
show index from test_table1;
```
截图:
![image-20220407101300158](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407101300158.png)
5按照表2创建表test_table2存储引擎为MyISAM。
```mysql
create table test_table2(
id int(11) not null unique,
firstname char(50) not null,
middlename char(50) not null,
lastname char(50) not null,
birth date not null,
title char(100),
primary key(id)
)engine=MyISAM;
```
截图:
![image-20220407100253683](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407100253683.png)
6使用alter table语句在test_table2的birth字段上建立名称为ComDateIdx的普通索引
```mysql
alter table test_table2 add index ComDateIdx(birth);
```
截图:
![image-20220407100726287](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407100726287.png)
7使用alter table语句在test_table2的id字段上添加名称为UniqIdx2的唯一索引并以降序排列。
```mysql
alter table test_table2 add unique index UniqIdx2(id);
```
截图:
![image-20220407100738304](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407100738304.png)
8使用create index在firstname、middlename和lastname 3个字段上建立名称为MultiColIdx2的组合索引。
```mysql
create index MultiColIdx2 on test_table2(firstname,middlename,lastname);
```
截图:
![image-20220407100905384](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407100905384.png)
9使用create index在title字段上建立名称为FTIdx的全文索引
```mysql
create fulltext index FTIdx on test_table2(title);
```
截图:
![image-20220407101003860](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407101003860.png)
10使用alter table语句删除表test_table1中名称为UniqIdx的唯一索引。
```mysql
alter table test_table1 drop index UniqIdx;
```
截图:
![image-20220407101326523](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407101326523.png)
11使用drop index语句删除表test_table2中名称为MultiColIdx2的组合索引。
```mysql
drop index MultiColIdx2 on test_table2;
```
截图:
![image-20220407101408468](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220407101408468.png)

View File

@ -0,0 +1,103 @@
# 第一章绪论
### 数据
数据是描述事物的符号记录
数据的含义称为语义,数据与语义是不可分的
### 数据库DB
存放数据的仓库
数据库是长期存储在计算机内,有组织的,可共享的大量数据的集合。
数据库具有永久存储,有组织和可共享三个基本特单
### 数据库管理系统DBMS
数据库管理系统是位于用户与操作系统之间的一层数据管理软件,是计算机的基础软件。
数据库管理系统的功能分为以下:
1 数据定义功能
2 数据组织 存储 管理
3数据操纵功能
4数据库的事务管理和运行管理
5 数据库的建立和维护功能
### 数据库管理员
职责1.决定数据库中信息内容和结构
2. 决定数据库的存储结构和存储策略
3. 定义数据的安全性要求和完整性要求
4. 监控数据库的使用和运行
5. 数据库的改进和重组 重构
### 数据库系统DBS
数据库系统是由数据库 数据库管理系统(及其应用开发工具) 应用程序和数据库管理员组成的存储 管理 处理 和维护数据的系统。
数据库系统的特点1. 数据结构化(与文件系统的本质区别)
2.数据共享性高,冗余度低且易于扩充
3.**数据独立性高** 分为数据逻辑独立性和数据物理独立性
数据逻辑独立性是指用户的应用程序与数据库的逻辑结构相互独立
数据物理独立性是指用户的应用程序与数据库中数据的物理存储是独立的。
4. 数据由数据库管理系统统一管理和控制
**数据库系统是三级模式结构**
模式:是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共视图。
外模式:子模式 ,用户模式 是数据库用户能够看见和使用的局部数据的逻辑结构和特征的描述。
内模式:一个数据库只有一个内模式。 是数据物理结构和存储方式的描述,是数据在数据库内部的组织方式。
二级映像:外模式/模式 -保证数据逻辑独立性
模式/内模式-保证数据物理独立性
### 数据管理技术
三个阶段: 人工管理阶段 文件系统阶段 数据库系统阶段
### 数据模型
组成要素:数据结构 数据操作(纵) 完整性约束
真实世界 信息世界 机器世界
第一类:概念模型-主要用于数据库设计的概念结构设计阶段-E-R图
实体(矩形)
属性(椭圆)
联系(菱形)
码:唯一标识实体的属性集称为码
第二类:
逻辑模型-逻辑结构设计阶段-模式 外模式
物理模型-物理结构设计阶段-内模式
**常用的数据模型**(逻辑层次)
层次模型
网状模型
关系模型 -规范化理论

View File

@ -0,0 +1,223 @@
## 关系数据库
关系模型
#### 关系模式-规范化理论
RU,D,DOM,F
1. R 关系名
2. U为一组属性
3. D为属性组U中得属性所来自得域
4. DOM为属性到域得映射
5. F为属性组U上的一组数据依赖
关系模式可能存在的问题 数据冗余 更新异常 插入异常 删除异常 所以要做规范化 根据属性间的依赖关系判定
##### 数据依赖
1.数据依赖是一个关系内部属性与属性之间的一种约束关系,这种约束关系是通过属性间值得相等与否体现出来得数据间得相关联系。
2. 数据依赖的重要两种类型 函数依赖与多值依赖
###### 函数依赖
设RU是属性集U上的关系模式X,Y是U上的子集。若对于R(U)的任意一个可能的关系rr中不可能存在两个元组在X上的属性值相等而在Y上的属性值不等则称X函数决定Y或Y函数依赖于X.
<u>掌握完全函数依赖,部分函数依赖,传递函数依赖,这是规范化的基础。</u>
定义6.2 在R(U)中如果X→Y并且对于X的任何一个真子集X, 都有 X ↛ Y, 则称Y对X完全函数依赖记作X → Y。
若X→Y但Y不完全函数依赖于X则称Y对X部分函数依赖记作X → Y
定义6.3 在R(U)中如果X→Y(Y⊈X)Y↛XY→ZZ⊈Y, 则称Z对X传递函数依赖(transitive functional dependency)。记为X → Z。
<u>分清候选码 主码 主属性 非主属性</u>
候选码:若关系中的某艺术性组的值能唯一的标识一个元组,而其子集不能,则称该属性组为候选码。若一个关系中有多个候选码,则选定其中一个为主码。
候选码的诸属性称为主属性,不包含在任何候选码中的属性称为非主属性或非码属性。
##### 范式
范式:关系模式的规范化形式,衡量关系模式好坏的标准。
规范化:将一个给定的关系模式转化为某种范式的过程称为关系模式的规范化过程,简称规范化。
规范化一般采用分解的办法,将低级别范式向高级别范式转化,使关系的语义单纯化。
<u>1NF</u>
定义 设R是一个关系模式。如果R中每个属性的值域都是不可分的原子值则称R是第一范式记作1NF。
1NF是关系模式具备的最起码的条件。
确保每一列的原子性,如果每列都是不可再分的数据单元,则满足第一范式。
<u>2NF</u>
定义6.6 若关系模式R∈1NF并且每一个非主属性都完全函数依赖于任何一个候选码则R∈2NF
2NF的实质是不存在非主属性“部分函数依赖”于候选键的情况。即每个表只描述一件事情
*转换规则*
非2NF关系或1NF关系向2NF的转换原则
设关系模式R属性集合为U主键是WR上还存在函数依赖X→Z且X是W的子集Z是非主属性那么W→Z就是一个部分函数依赖。此时应把R分解成两个关系模式
R1XZ主键是X
R2Y其中Y=U-Z主键仍是W外键是X。
如果R1和R2还不是2NF则重复上述过程一直到每个关系模式都是2NF为止。
<u>3NF</u>
定义6.7 设关系模式R<U,F>∈1NF,若R中不存在这样的码X、属性组Y及非主属性ZZ ⊇ Y, 使得X→YY→Z成立Y ↛ X成立则称R<U,F> ∈ 3NF。
如果关系模式R是2NF而且R中所有非主属性对任何候选键都不存在传递函数依赖则称R是第三范式记作3NF。
3NF是从1NF消除非主属性对候选键的部分函数依赖和从2NF消除传递函数依赖而得到的关系模式。
3NF需要确保数据表中的每一列数据都和主键直接相关而不能间接相关
*转换规则*
2NF关系向3NF转换的原则
设关系模式R属性集合为U主键是WR上还存在函数依赖X→Z并且Z是非主属性Z不包含于XX不是候选键这样W→Z就是一个传递依赖。此时应把R分解成两个关系模式
R1XZ主键是X
R2Y其中Y=U-Z主键仍是W外键是X。
如果R1和R2还不是3NF则重复上述过程一直到每个关系模式都是3NF为止。
<u>BCNF</u>
在关系模式R<U,F>如果每一个决定属性集都包含候选码则R∈BCNF。
3NF关系向BCNF转换的原则是消除主属性对候选键的部分和传递函数依赖将3NF关系分解成多个BCNF关系模式。
BCNF的关系模式所具有的性质
所有非主属性都完全函数依赖于每个候选码
所有主属性都完全函数依赖于每个不包含它的候选码
没有任何属性完全函数依赖于非码的任何一组属性
如果一个关系数据库中的所有关系模式都属于BCNF那么在函数依赖范畴内它已实现了模式的彻底分解达到了最高的规范化程度消除了插入异常和删除异常。
**对于关系模式中只有一个候选码的情况达到3NF即达到了BCNF**
练习题 PPT 73-74页
ppt 154-156
### 关系操作
关系操作语言分为关系代数 关系演算 和SQL结构化查询语言语言。
##### 关系代数
关系代数分为传统的集合运算和专门的关系运算两类。
传统的集合运算:并 差 交 笛卡儿积
专门的关系运算:选择 投影 连接 除运算等(必须掌握运算方式)
练习题 课本p71页 6题
##### SQL结构化查询语言
SQL是关系数据库语言是高度非过程化语言
SQL功能
数据定义 create drop alter
数据查询 select
数据操纵 insert update delete
数据控制 grant revoke commit rollback
视图
**视图的作用**
1. 视图能够简化用户的操作
2. 视图使用户能以多种角度看待同一问题
3. 视图对重构数据库提供了一定程度的逻辑独立性
4. 视图能够对机密数据提供安全保护
5. 适当利用视图可以更清晰地表达查询
练习题
1.学校数据库中包括四个表,各属性的含义可由属性名体现,不再重复
学生表:S(Sno, Sname,Ssex,Sage, Sdept),
课程表:C(Cno, Cname,CTno, Ccredit)
学生选课表:SC(Sno,Cno,mid-exam, final-exam, Grade)
课程类别表CT(CTno,Type)
其中:CT由课程类别编码(CTno)、课程类别(Type)两个属性组成。
Type取值有:公共课、学科基础课、专业必修课、专业选修课、全校选修课等。
Grade是计算属性,由期中成绩(mid-exam)和期末成绩( final-exam)平均而得到。
用关系代数完成以下操作:
1成绩为95分以上的学生成绩单,包括学号、姓名、课程名、成绩四个属性。
2选修了全部“专业选修课”的学生学号、姓名、所在系。
用SQ语言完成以下操作:
3按系统计不同年龄的学生人数,输岀结果按照系名称的字母升序和学生的年龄降序。
4找出每个学生超过他自己所选修全部课程平均成绩的课程号、课程名称、成绩
5对选修数据库系统概论这门课的学生计算其该门课的总成绩,按照期中占40%,期末
占60%计算。
6査询没有选修过任何“全校选修课”的学生姓名及其所在系。
7统计每一门课程的选修人数及其平均成绩。要求每门课程都必须岀现在査询
结果中,不管有没有学生选修。
8按照总成绩从高到低的顺序输出学生名单(包括学号,姓名,总成绩),成绩相同时,
按照学号从小到大的顺序输出。
2. 有三个表它们的记录行数分别是10行、2行和6行三个表进行多表联合查询结果集中共有( )行数据
A18 B26 C不确定 D120
3. 下列聚集函数中不忽略空值(null)的是( )
A.SUM(列名) B.MAX(列名) C. COUNT(*) D.AVG(列名)
4. 当关系R和S自然联接时,能够把R和S原该舍弃的元组放到结果关系中的操作是( )
A.左外连接 B.右外连 C.外部并 D.外连接
5. SQL语言是 )的语言,易学习。
A.过程化 B.非过程化 C.格式化 D.导航式
6. 关系数据库管理系统应能实现的专门关系运算包括(
A. 排序、索引、统计 B.选择、投影、连接 C. 关联、更新、排序 D. 显示、打印、表
7. 在关系代数运算中,五种基本运算为(
A. 并、差、选择、投影、自然连接
B. 并、差、交、选择、投影
C并、差、选择、投影、乘积
D. 并、差、交、选择、乘积
8. SQL语言具有 的功能。
A关系规范化、数据操纵、数据控制
B. 数据定义、数据操纵、数据控制
C. 数据定义、关系规范化、数据控制
D. 数据定义、关系规范化、数据操纵
9. 1设学生课程数据库中有三个关系:
学生关系SS#SNAMEAGESEX
学习关系SCS#, C#GRADE
课程关系
C (C#, CNAME)
其中S#、C#、SNAME、AGE、SEX、GRADE、CNAME分别表示学号、课程号、姓名、年龄、性别、成绩
和课程名。
用SQL语句表达下列操作
1检索选修课程名称为“MATHS”的学生的学号与姓名
2检索年龄在18到20之间含18和20的女生的学号、姓名和年龄
3检索平均成绩超过80分的学生学号和平均成绩
4检索选修了三门课以上的学生的姓名
10.设学生-课程数据库中包括三个表:
学生表: Student(SnoSnameSex,Sage, Sdept)
课程表:CourseCno, Cname, Ccredit
学生选课表: SCSnoCnoGrade
其中Sno、Sname、Sex、Sage、Sdept、Cno、Cname、Ccredit 、Grade分别表示学号、姓名、性别、年龄、所在系名、课程号、课程名、学分和成绩。
试用SQL语言完成下列项操作:
1创建一个计科系学生信息视图S-CS-VIEW包括Sno学号、Sname 姓名、Sex性别
2通过上面第 2 题创建的视图修改数据,把王平的名字改为王慧平
3创建一选修数据库课程信息的视图视图名称为 datascore-view包含学号、姓名、成绩。

View File

@ -0,0 +1,36 @@
## 数据库安全性
##### 数据控制语言grant revoke
数据库的安全性是指保护数据库以防止不合法的使用所造成的数据泄露 更改和破坏。
数据库安全性控制手段:用户身份鉴别, 多层存取控制,审计,视图和数据加密(分为存储加密和传输加密)。
存取控制分为 自主存取控制和强制存取控制
###### 自主存取控制
用户对于不同的数据库对象有不同的存取权限,不用的用户对同一对象也有不同的权限,而且用户还可将其拥有的存取权限转授给其他用户。自主存取控制非常灵活。
grant 权限 on 对象类型 to 用户/角色 with grant option
revoke 权限 on 对象类型 from 用户/角色
##### 强制存取控制
每一个数据对象被标以一定的密级,每一个用户也被授予某一个级别的许可证。对于任意一个对象,只有具有合法许可证的用户才可以存取。强制存取控制是对数据本身进行密级标记,无论数据如何复制,标记与数据是一个不可分的整体,只有符合密级标记要求的用户才可以操纵数据。
强制存取控制读写规则
仅当主体的许可证级别大于或等于客体的密级时,该主体才能读取相应的客体。
仅当主体的许可证级别小于或等于客体的密级时,该主体才能写相应的客体。
练习题:什么是数据库的自主存取控制方法和强制存取控制方法,强制存取控制的读写规则是什么?自主控制语句是怎样的?

View File

@ -0,0 +1,54 @@
## 数据库完整性
数据库完整性是指数据的正确性和相容性。
完整性约束 实体完整性 参照完整性 用户定义的完整性
##### 实体完整性
若属性指一个或一组属性A是基本关系R的主属性则A不能取空值。所谓空值就是“不知道” “不存在” 或者“无意义”的值。
关系模型的实体完整性在 create table 中用primary key定义。
###### 实体完整性检查和违约处理
1检查主码值是否唯一如果不唯一则拒绝插入和修改
2检查主码的各个属性是否为空只要有一个为空就拒绝插入和修改。
##### 参照完整性
设F是基本关系R的一个或一组属性但不是关系R的码Ks是基本关系S的主码。如果F与Ks相对应则称F是R的外码并称基本关系R为参照系基本关系S为被参照系。
若属性或属性组F是基本关系R的外码它与基本关系S的主码Ks相对应基本关系R和S不一定是不同的关系则对于R中的每个元组在F上的值必须
或者取空值
或者等于S中某个原则的主码值
###### 参照完整性检查和违约处理
1 拒绝执行(一般设置为默认策略)
2 级联cascade操作
3 设置为空值
##### 用户定义完整性
用户定义的完整性是针对某一具体关系数据库的约束条件,它反映某一具体应用所涉及的数据必须满足的语义要求。
在create table 中定义属性的同时,可以根据应用要求定义属性上的约束条件,即属性值限制,包括: 列值非空not null列值唯一unique用check短语指定列值应该满足的条件。
#### 完整性约束命名子句
constraint 完整性约束条件名 完整性约束条件
<u>要求 用check短语写约束条件 和外键约束必须掌握</u>
定义触发器
练习 第四上机内容。文件在群里。

View File

@ -0,0 +1,94 @@
## 数据库设计
数据库设计是指对于一个给定的应用环境,构造(设计)优化数据库逻辑模式和物理结构,并据此建立数据库及其应用系统,使之能够有效的存储和管理数据,满足各种用户的应用需求,包括信息管理需求和数据操作要求。
数据库设计的特点
1. 三分技术,七分管理,十二分基础数据
2. 结构(数据)设计和行为(处理)设计相结合
#### 数据库设计的基本步骤:
<u>需求分析阶段 概念结构设计阶段 逻辑结构设计阶段 物理结构设计阶段 数据库实施阶段 数据库运行和维护阶段</u>
**需求分析阶段**
建立数据字典
数据字典通常包括数据项,数据结构,数据流,数据存储和处理过程几部分。
**概念结构设计阶段**
概念模型-E-R图
1实体与属性的划分原则
作为属性,不能在具有需要描述的性质
属性不能与其他实体具有练习
2E-R图的集成
各子系统的E-R图之间的冲突主要有三类属性冲突命名冲突和结构冲突。
**逻辑结构设计阶段**
逻辑结构设计的任务就是把概念结构设计阶段设计好的基本E-R图转换为与所选用数据库管理系统产品所支持的数据模型相符合的逻辑结构。
E-R模型到关系模型转换原则
1. 实体转换原则
一个实体转换成一个关系模式,实体的码即关系模式的码
2. 实体型间的联系有以下不同情况
1 一个1:1联系可以转换为一个独立的关系模式也可以与任意一端对应的关系模式合并。
① 转换为一个独立的关系模式
关系的属性:与该联系相连的各实体的码以及联系本身的属性
关系的候选码:每个实体的码均是该关系的候选码
②与某一端实体对应的关系模式合并
合并后关系的属性:该关系模式的属性中加入另一个关系模式的码(作为外键)和联系本身的属性。
合并后关系的码:不变
2一个1:n联系可以转换为一个独立的关系模式也可以与n端对应的关系模式合并。
①转换为一个独立的关系模式
关系的属性:与该联系相连的各实体的码以及联系本身的属性
关系的码n端实体的码
②与n端对应的关系模式合并
合并后关系的属性在n端关系中加入1端关系的码作为外键和联系本身的属性
合并后关系的码:不变
可以减少系统中的关系个数,一般情况下更倾向于采用这种方法
3一个m:n联系转换为一个关系模式
关系的属性:与该联系相连的各实体的码以及联系本身的属性
关系的码:各实体码的组合
三个或三个以上实体间的一个多元联系转换为一个关系模式。
关系的属性:与该多元联系相连的各实体的码以及联系本身的属性
关系的码:各实体码的组合
练习题:
1.第七章ppt 17-18
2.某医院病房计算机管理中需要如下信息:
科室:科室名,科地址,科电话,医生姓名
病房:病房号,床位号,所属科室名
医生:姓名,职称,所属科室名,年龄,工作证号
病人:病历号,姓名,性别,诊断,主管医生,病房号
其中,一个科室有多个病房,多个医生,一个病房只能属于一个科室,一个医生只属于
个科室,但可负责多个病人的诊治,
,一个病人的主管医生只有一个。
完成如下设计:
1涉及该计算机管理系统的 E-R 图
2将该E-R图转换为关系模型的结构
3指出转换结果中每个关系模式的候选码
课本241页 7810

Binary file not shown.

After

Width:  |  Height:  |  Size: 969 KiB

View File

@ -0,0 +1,244 @@
**一、上机内容**
\1. 使用SQL语句创建数据库studentsdb。
```sql
create database studentsdb;
```
\2. 使用SQL语句选择studentsdb为当前使用数据库。
```sql
use studentsdb;
```
\3. 使用SQL语句在studentsdb数据库创建数据表student_info、curriculum、grade三个表的数据结构如表1-表3所示。
表1 student_info表结构
| 列名 | 数据类型 | 允许NULL值 | 主键 |
| -------- | ----------- | ---------- | ---- |
| 学号 | char(4) | 否 | 是 |
| 姓名 | char(8) | 否 | 否 |
| 性别 | char(2) | 是 | 否 |
| 出生日期 | date | 是 | 否 |
| 家庭住址 | varchar(50) | 是 | 否 |
```sql
create table student_info(
学号 char(4) not null PRIMARY KEY,
姓名 char(8) not null,
性别 char(2),
出生日期 date,
家庭住址 varchar(50)
);
```
![image-20220923104156917](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/202209231042251.png)
表2 表结构
| 列名 | 数据类型 | 允许NULL值 | 主键 |
| -------- | ----------- | ---------- | ---- |
| 课程编号 | char(4) | 否 | 是 |
| 课程名称 | varchar(50) | 是 | 否 |
| 学分 | int | 是 | 否 |
```sql
create table curriculum(
课程编号 char(4) not null PRIMARY KEY,
课程名称 varchar(50),
学分 int
);
```
![截屏2022-09-23 10.43.40](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/%E6%88%AA%E5%B1%8F2022-09-23%2010.43.40.png)
表3 grade表结构
| 列名 | 数据类型 | 允许NULL值 | 主键 |
| -------- | -------- | ---------- | ---- |
| 学号 | char(4) | 否 | 是 |
| 课程编号 | char(4) | 否 | 是 |
| 分数 | int | 是 | 否 |
```sql
create table grade(
学号 char(4) not null,
课程编号 char(4) not null,
分数 int,
PRIMARY KEY(学号,课程编号)
);
```
![截屏2022-09-23 10.44.15](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/%E6%88%AA%E5%B1%8F2022-09-23%2010.44.15.png)
\4. 使用SQL语句INSERT向studentsdb数据库的student_info、curriculum、grade表插入数据各表数据如表4-表6所示。
表4 student_info表的数据
| 学号 | 姓名 | 性别 | 出生日期 | 家庭住址 |
| ---- | ------ | ---- | ---------- | -------------- |
| 0001 | 张青平 | 男 | 2000-10-01 | 衡阳市东风一路 |
| 0002 | 刘东阳 | 男 | 1998-12-09 | 东阳市八一北路 |
| 0003 | 马晓夏 | 女 | 1995-05-12 | 长岭市五一路 |
| 0004 | 钱忠理 | 男 | 1994-09-23 | 滨海市洞庭大道 |
| 0005 | 孙海洋 | 男 | 1995-04-03 | 长岛市解放路 |
| 0006 | 郭小斌 | 男 | 1997-11-10 | 南山市红旗路 |
| 0007 | 肖月玲 | 女 | 1996-12-07 | 东方市南京路 |
| 0008 | 张玲珑 | 女 | 1997-12-24 | 滨江市新建路 |
```sql
insert into student_info(学号,姓名,性别,出生日期,家庭住址)
values('0001','张青平','男','2000-10-01','衡阳市东风路77号'),
('0002','刘东阳','男','1998-12-09','东阳市八一北路33号'),
('0003','马晓夏','女','1995-05-12','长岭市五一路763号'),
('0004','钱忠理','男','1994-09-23','滨海市洞庭大道279号'),
('0005','孙海洋','男','1995-04-03','长岛市解放路27号'),
('0006','郭小斌','男','1997-11-10','南山市红旗路113号'),
('0007','肖月玲','女','1996-12-07','东方市南京路11号'),
('0008','张玲珑','女','1997-12-24','滨江市新建路97号');
```
![截屏2022-09-23 10.44.41](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/%E6%88%AA%E5%B1%8F2022-09-23%2010.44.41.png)
表5 curriculum表的数据
| 课程编号 | 课程名称 | 学分 |
| -------- | ---------------- | ---- |
| 0001 | 计算机应用基础 | 2 |
| 0002 | C语言程序设计 | 2 |
| 0003 | 数据库原理及应用 | 2 |
| 0004 | 英语 | 4 |
| 0005 | 高等数学 | 4 |
```sql
insert into curriculum(课程编号,课程名称,学分)
values('0001','计算机应用基础',2),
('0002','C语言程序设计',2),
('0003','数据库原理及应用',2),
('0004','英语',4),
('0005','高等数学',4);
```
![截屏2022-09-23 10.45.30](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/%E6%88%AA%E5%B1%8F2022-09-23%2010.45.30.png)
表6 grade表的数据
| 学号 | 课程编号 | 分数 |
| ---- | -------- | ---- |
| 0001 | 0001 | 80 |
| 0001 | 0002 | 91 |
| 0001 | 0003 | 88 |
| 0001 | 0004 | 85 |
| 0001 | 0005 | 77 |
| 0002 | 0001 | 73 |
| 0002 | 0002 | 68 |
| 0002 | 0003 | 80 |
| 0002 | 0004 | 79 |
| 0002 | 0005 | 73 |
| 0003 | 0001 | 84 |
| 0003 | 0002 | 92 |
| 0003 | 0003 | 81 |
| 0003 | 0004 | 82 |
| 0003 | 0005 | 75 |
```sql
insert into grade(学号,课程编号,分数)
values('0001','0001',80),
('0001','0002',91),
('0001','0003',88),
('0001','0004',85),
('0001','0005',77),
('0002','0001',73),
('0002','0002',68),
('0002','0003',80),
('0002','0004',79),
('0002','0005',73),
('0003','0001',84),
('0003','0002',92),
('0003','0003',81),
('0003','0004',82),
('0003','0005',75);
```
![image-20220923100729127](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/202209231007173.png)
\5. 使用SQL语句ALTER TABLE修改curriculum表的“课程名称”列使之为空。
```sql
alter table curriculum modify 课程名称 varchar(50) not null;
```
![image-20220923104648161](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220923104648161.png)
\6. 使用SQL语句ALTER TABLE修改grade表的“分数”列使其数据类型为decimal(5,2)。
```sql
alter table grade modify 分数 decimal(5,2);
```
![image-20220923104705660](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220923104705660.png)
\7. 使用SQL语句ALTER TABLE为student_info表添加一个名为“备注”的数据列其数据类型为varchar(50)。
```sql
alter table student_info add 备注 varchar(50);
```
![image-20220923104721475](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220923104721475.png)
\8. 使用SQL语句创建数据库studb并在此数据库下创建表stu表结构与数据与studentsdb的student_info表相同。
```sql
create database studb;
use studb;
create table stu as select * from studentsdb.student_info;
```
![image-20220923104800750](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220923104800750.png)
\9. 使用SQL语句删除表stu中学号为0004的记录。
```sql
delete from stu where 学号 = '0004';
```
![image-20220923104823284](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220923104823284.png)
10.使用SQL语句更新表stud中学号为0002的家庭住址为“滨江市新建路96号”。
```sql
update stu set 家庭住址 = '滨江市新建路96号' where 学号 = '0002' ;
```
![image-20220923104902292](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220923104902292.png)
11.删除表stud的“备注”列。
```sql
alter table stu drop column 备注;
```
![image-20220923104914868](https://yovinchen-1308133012.cos.ap-beijing.myqcloud.com/image-20220923104914868.png)
**二、实验思考**
\1. 能通过一个CREATE DATABASE语句创建两个及以上的数据库吗
不能
\2. 删除了的数据库还能可能恢复吗?
一般来说是不能恢复的
\3. 对于studentsdb数据库的student_info表而言如果输入相同学号的记录将出现什么现象为什么
不能插入,导致插入冲突。
避免方式就是将学号设为主键,不能重复。
\4. 已经打开的表能删除吗?
可以

View File

@ -0,0 +1,261 @@
## 一、上机内容
1. 使用SQL语句ALTER TABLE分别删除studentsdb数据库的student_info表、grade表、curriculum表的主键索引。
```sql
alter table student_info drop primary key;
alter table grade drop primary key;
alter table curriculum drop primary key;
```
2. 使用SQL语句为curriculum表的课程编号创建唯一性索引命名为cno_idx。
```sql
create unique index cno_idx on curriculum(课程编号);
```
3. 使用SQL语句为grade表的“分数”字段创建一个普通索引命名为grade_idx。
```sql
create index grade_idx on grade(分数);
```
4. 使用SQL语句为grade表的“学号”和“课程编号”字段创建一个复合唯一索引命名为grade_sid_cid_idx。
```sql
create index grade_sid_cid_idx on grade(学号,课程编号);
```
5. 查看grade表上的索引信息。
```sql
show index from grade;
```
6. 使用SQL语句删除索引grade_idx。再次查看grade表上的索引信息。
```sql
drop index grade_idx on grade;
show index from grade;
```
7. 使用SQL语句CREATE VIEW建立一个名为v_stu_c的视图显示学生的学号、姓名、所学课程的课程编号并利用视图查询学号为0003的学生情况。
```sql
create view v_stu_c as select s.学号,姓名,课程编号 from student_info s,grade g where s.学号=g.学号;
select * from v_stu_c where 学号 = '0003';
```
8.基于student_info表、curriculum表和grade表建立一个名为v_stu_g的视图视图包括所有学生的学号、姓名、课程名称、分数。使用视图v_stu_g查询学号为0001的学生的课程平均分。
```sql
create view v_stu_g as select s.学号,姓名,课程名称,分数 from student_info s,grade g,curriculum c where s.学号=g.学号 and g.课程编号=c.课程编号;
select avg(分数) 平均分 from v_stu_g where 学号='0001';
```
9.使用SQL语句修改视图v_stu_g显示学生的学号、姓名、性别。
```sql
alter view v_stu_g as select 学号,姓名,性别 from student_info;
select 学号,姓名,性别 from v_stu_g;
```
10.利用视图v_stu_g为student_info表添加一行数据学号为0010、姓名为陈婷婷、性别为女。
```sql
insert into v_stu_g (学号,姓名,性别) values ('0010','陈婷婷','女');
```
11.利用视图v_stu_g删除学号为0010的学生记录。
```sql
delete from v_stu_g where 学号='0010';
```
12.利用视图v_stu_g修改姓名为张青平的学生的高等数学的分数为87。
```sql
update grade set 分数=87 where 学号=(select 学号 from v_stu_g where 姓名='张青平') and 课程编号=(select 课程编号 from curriculum where 课程名称='高等数学');
```
13.使用SQL语句删除视图v_stu_c和v_stu_g。
```sql
drop view v_stu_c,v_stu_g;
```
14. 在本地主机创建用户账号st_01密码为123456。
```sql
create user st_01@localhost identified by'123456';
```
15. 查看MySQL下所有用户账号列表。
```sql
use mysql;
select * from user;
```
16. 修改用户账号st_01的密码为111111。
```sql
set password for st_01@localhost='111111';
```
17. 使用studentsdb数据库中的student_info表。
1授予用户账号st_01查询表的权限。
```sql
grant select on table studentsdb.student_info to st_01@localhost;
```
2授予用户账号st_01更新家庭住址列的权限。
```sql
grant update(家庭住址) on table studentsdb.student_info to st_01@localhost;
```
3授予用户账号st_01修改表结构的权限。
```sql
grant alter on table studentsdb.student_info to st_01@localhost;
```
18. 使用studentsdb数据库。
1授予用户账号st_01在studentsdb数据库上创建表、删除表、查询数据、插入数据的权限。
```sql
grant create,select,insert,drop on studentsdb.* to st_01@localhost;
```
2以用户账号st_01连接MySQL服务器创建新表st_copy与表student_info完全相同。
```sql
exit
mysql -ust_01 -p
create table studentsdb.st_copy select * from studentsdb.student_info;
```
3以用户账号st_01连接MySQL服务器删除表st_copy。
```sql
drop table studentsdb.st_copy;
```
20. 撤消用户账号st_01在studentsdb数据库上创建表、删除表、查询数据、插入数据的权限。
```sql
revoke create,select,insert,drop on studentsdb.* from st_01@localhost;
```
21. 撤消用户账号st_01所有权限.
```sql
revoke all privileges,grant option from st_01@localhoat;
错误
```
22 使用studentsdb数据库中的student_info表。
1创建本地机角色student。
```sql
create role 'student'@'localhost';
```
2授予角色student查询student_info表的权限。
```sql
grant select on table studentsdb.student_info to 'student'@'localhost';
```
3创建本地机用户账号st_02密码为123。
```sql
create user st_02@localhost identified by '123';
```
4授予用户账号st_02角色student的权限。
```sql
grant 'student'@'localhost' to st_02@localhost;
set global activate_all_roles_on_login = on;
```
5以用户账号st_02连接MySQL服务器查看student_info表信息。
```sql
exit
mysql -ust_02 -p
select * from studentsdb.student_info;
```
6撤消用户账号st_02角色student的权限。
```sql
revoke all privileges ,grant option from 'student'@'localhost';
```
7删除角色student。
```sql
drop role 'student'@'localhost';
```
23.删除用户账号st_01、st_02。
```sql
drop user st_01@localhost,st_02@localhost;
```
## 二、实验思考
#### 1.建立索引的目的。什么情况下不适于在表上建立索引。
目的:
1.加快表之间的连接
2.加快数据的检索速度
3.通过唯一性索引可确保数据的唯一性
4.减少分组和排序时间
5.使用优化隐藏器提高系统性能
以下情况不适合在表上创建索引:
1.数据量小的表
2.大量重复数据的列
3.当修改性能远大于检索性能
4.查询过程中很少使用或参考的列
#### 2.能否在视图上建立索引。
mysql的视图不能创建视图
#### 3.想通过视图修改表中数据,视图应具备哪些条件。
1.select语句在选择列表中没有聚合函数也不包含top,group by,union或distinct子句
2.select语句的选择列表中没有派生列
3.select语句中的from子句至少引用一个表
4.insert,update和delete语句在引用可更新视图之前也必须如上述条件指定的那样满足某些限制条件
#### 4.视图的作用。
1.视图隐藏了底层的表结构,简化了数据访问操作
2.视图提供了一个统一访问数据的接口
3.加强了安全性,使用户只能看到视图所显示的数据
4.视图还可以被嵌套,一个视图中可以嵌套另一个视图
#### 5.用户账号、角色和权限之间的关系是什么?没有角色能给用户授予权限吗?
关系:
1.角色对应一定的权限,角色的权限可以被赋予和收回(有些特定的不能改)
2.用户可以通过被赋予角色来得到权限,也可以直接被赋予权限。
没有角色不能给用户授权权限
#### 6.角色在用户账号连接服务器后自动被激活的设置方法。

Some files were not shown because too many files have changed in this diff Show More