项目part1
面向对象程序设计大作业
前端部分准备
NodeJS安装
Vue,是一款用于构建用户界面的渐进式的JavaScript(1)框架,通过使用vue官方提供的脚手架create-vue帮我们完成前端的工程化,而要想使用create-vue来创建vue项目,则必须安装依赖环境:NodeJS
(1)HTML负责网页的结构,CSS负责网页的表现,JavaScript让网页具备一定的交互效果,具有一定的动作行为
1. 双击安装包
2. 选择安装目录
安装到一个,没有中文,没有空格的目录下(新建一个文件夹NodeJS)
3. 验证NodeJS环境变量
NodeJS 安装完毕后,会自动配置好环境变量,我们验证一下是否安装成功,通过: node -v
4. 配置npm的全局安装路径

1 | npm config set prefix "D:\develop\NodeJS" |
注意:E:\develop\NodeJS 这个目录是NodeJS的安装目录
5. 切换npm的淘宝镜像
使用管理员身份运行命令行,在命令行中,执行如下指令:
1 | npm config set registry https://registry.npmmirror.com |
6. 安装Vue-cli
使用管理员身份运行命令行,在命令行中,执行如下指令:
1 | npm install -g @vue/cli |
npm:Node Package Manager,是NodeJS的软件包管理器。
在开发前端项目的过程中,我们需要相关的依赖,就可以直接通过 npm install xxx 命令,直接从远程仓库中将依赖直接下载到本地了。
Vue项目创建
项目创建
命令行形式
创建一个工程化的Vue项目,执行命令:npm create vue@3.3.4
图形化界面方式
首先,在桌面创建vue文件夹,双击进入文件夹,地址目录处输入cmd,然后进入到vue文件夹的cmd窗口界面,直接输入命令vue ui
进入到vue的图形化界面,选择创建按钮,在vue文件夹下创建项目,然后预设模板选择手动,在功能页面开启路由功能,然后再配置页面选择语言版本和语法检查规范,不保存预设,然后创建项目。最后我们只需要等待片刻,即可进入到创建创建成功的界面。
注:Vue的组件有两种不同的风格:组合式API和选项式API。Vue3提供了组合式API(没有this对象的,this对象是undefined )
执行上述指令之一,将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工具
项目结构
启动项目
点击NPM脚本中的dev后的运行按钮
项目流程
其中*.vue是Vue项目中的组件文件,在Vue项目中也称为单文件组件(SFC,Single-File Components)。Vue 的单文件组件会将一个组件的逻辑 (JS),模板 (HTML) 和样式 (CSS) 封装在同一个文件里(*.vue)
利用ElementPlus辅助开发
Element:是饿了么公司前端开发团队提供的一套基于 Vue3 的网站组件库,用于快速构建网页。
Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等。
官方网站
使用
在当前工程的目录下,执行如下命令
1 | npm install element-plus@2.4.4 --save |
main.js中代码修改为
1 | import { createApp } from 'vue' |
常用到的组件有表格组件,分页条组件,对话框组件,表单组件等
VueRouter
- Vue Router:Vue的官方路由。 为Vue提供富有表现力、可配置的、方便的路由。
- Vue中的路由,主要定义的是路径与组件之间的对应关系。
比如,我们打开一个网站,点击左侧菜单,地址栏的地址发生变化。 地址栏地址一旦发生变化,在主区域显示对应的页面组件。
VueRouter主要由以下三个部分组成,如下所示:
1 | VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件 |
安装VueRouter
1 | npm install vue-router@4(Vue 3)或 npm install vue-router@3(Vue 2) |
快速上手
- App.vue中修改部分代码为
1
2
3
4
5<script setup>
</script>
<template>
<router-view></router-view>
</template> - 创建router文件夹,里面创建index.js这一文件。注意要嵌套路由
- 在 views/layout/index.vue 中,调整代码,具体调整位置如下:4.安装axios
1
2
3在左侧菜单栏的 <el-menu> 标签上添加 router 属性,这会让 Element Plus 的 <el-menu> 组件自动根据路由来激活对应的菜单项。
使用 <router-view> 组件来渲染根据路由动态变化的内容。
确保每个 <el-menu-item> 的 index 属性值与你想要导航到的路径相匹配。
Ajax: 全称Asynchronous JavaScript And XML,异步的JavaScript和XML。其作用有如下2点:
- 与服务器进行数据交换:通过Ajax可以给服务器发送请求,并获取服务器响应的数据。
前端资源被浏览器解析,但是前端页面上缺少数据,前端可以通过Ajax技术,向后台服务器发起请求,后台服务器接受到前端的请求,从数据库中获取前端需要的资源,然后响应给前端,前端在通过我们学习的vue技术,可以将数据展示到页面上,这样用户就能看到完整的页面了。 - 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用的校验等等。
使用原生的Ajax请求的代码编写起来比较繁琐,所以使用更加简单的发送Ajax请求的技术Axios 。Axios是对原生的AJAX进行封装,简化书写
安装:5.结构优化1
npm install axios
在前端项目开发时,通常会定义一个请求处理的工具类 - src/utils/request.js。在这个工具类中,对axios进行了封装而与服务端进行异步交互的逻辑,通常会按模块,封装在一个单独的API中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '../router'
//创建axios实例对象
const request = axios.create({
baseURL: '/api',
timeout: 600000
})
//axios的请求 request 拦截器, 每次请求获取localStorage中的loginUser, 从中获取到token, 在请求头token中携带到服务端
request.interceptors.request.use(
(config) => {
let loginUser = JSON.parse(localStorage.getItem('loginUser'))
console.log(localStorage.getItem('loginUser'))
if (loginUser) {
config.headers.token = loginUser.token
}
return config
}
)
//axios的响应 response 拦截器
request.interceptors.response.use(
(response) => { //成功回调
return response.data
},
(error) => { //失败回调
//如果响应的状态码为401, 则路由到登录页面
if (error.response.status === 401) {
ElMessage.error('登录失效, 请重新登录')
router.push('/login')
}else{
ElMessage.success('接口访问异常')
}
return Promise.reject(error)
}
)
后端项目启动
前置基础:Maven、HTTP协议、SpringBootWeb基础、IOC、DI(依赖控制,注入反转)、MySQL、JDBC、Mybatis等
Maven
介绍
Apache Maven是一个项目管理和构建工具,它基于项目对象模型(Project Object Model , 简称: POM)的概念,通过一小段描述信息来管理项目的构建、报告和文档。
Maven的作用:
- 方便的依赖管理
- 统一的项目结构
- 标准的项目构建流程
Maven仓库分为:
- 本地仓库:自己计算机上的一个目录(用来存储jar包)
- 中央仓库:由Maven团队维护的全球唯一的。仓库地址:https://repo1.maven.org/maven2/
- 远程仓库(私服):一般由公司团队搭建的私有仓库
当项目中使用坐标引入对应依赖jar包后, - 首先会查找本地仓库中是否有对应的jar包
- 如果有,则在项目直接引用
- 如果没有,则去中央仓库中下载对应的jar包到本地仓库
- 如果还可以搭建远程仓库(私服),将来jar包的查找顺序则变为: 本地仓库 –> 远程仓库–> 中央仓库
安装
Maven安装配置步骤:
- 解压安装
- bin目录 : 存放的是可执行命令。(mvn 命令重点关注)
- conf目录 :存放Maven的配置文件。(settings.xml配置文件后期需要修改)
- lib目录 :存放Maven依赖的jar包。(Maven也是使用java开发的,所以它也依赖其他的jar包)
- 配置仓库
- 配置阿里云私服
由于中央仓库在国外,所以下载jar包速度可能比较慢,而阿里公司提供了一个远程仓库,里面基本也都有开源项目的jar包。
进入到conf目录下修改settings.xml配置文件:
(1) 使用超级记事本软件,打开settings.xml文件,定位到160行左右
(2)1
2
3
4
5
6
7
8在<mirrors>标签下为其添加子标签<mirror>,内容如下:
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
注意配置的位置,在<mirrors> ... </mirrors>中间添加配置。 - 配置Maven环境变量
Maven环境变量的配置类似于JDK环境变量配置一样
(1)在系统变量处新建一个变量MAVEN_HOME。 MAVEN_HOME环境变量的值,设置为maven的解压安装目录
(2)在Path中进行配置。 PATH环境变量的值,设置为:%MAVEN_HOME%\bin
IDEA集成Maven
创建Maven项目
选择 IDEA中 File => close project => Customize => All settings;打开 All settings , 选择 Build,Execution,Deployment => Build Tools => Maven。配置工程的编译版本为17。这里所设置的maven的环境信息,并未指定任何一个project,此时设置的信息就属于全局配置信息。 以后,我们再创建project,默认就是使用我们全局配置的信息。创建一个空项目,命名为 web-project01, 创建好项目之后,进入项目中,要设置JDK的版本号。选择小齿轮,选择 Project Structure, 创建模块,选择Java语言,选择Maven。 填写模块的基本信息。在maven项目中,创建HelloWorld类,并运行。
以刚创建的共项目为例,Maven项目的目录结构:
maven-project01
|— src (源代码目录和测试代码目录)
|— main (源代码目录)
|— java (源代码java文件目录)
|— resources (源代码配置文件目录)
|— test (测试代码目录)
|— java (测试代码java目录)
|— resources (测试代码配置文件目录)
|— target (编译、打包生成文件存放目录)
pom文件详解
1 | - <project> :pom文件的根标签,表示当前maven项目 |
Maven坐标
什么是坐标?
- Maven中的坐标是资源的唯一标识 , 通过该坐标可以唯一定位资源位置
- 使用坐标来定义项目或引入项目中需要的依赖
Maven坐标主要组成:
- groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)
- artifactId:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)
- version:定义当前项目版本号
- SNAPSHOT: 功能不稳定、尚处于开发中的版本,即快照版本
- RELEASE: 功能趋于稳定、当前更新停止,可以用于发行的版本
导入Maven项目
在IDEA中导入Maven项目,有两种方式。
- 方式一:File -> Project Structure -> Modules -> Import Module -> 选择maven项目的pom.xml。
- 方式二:Maven面板 -> +(Add Maven Projects) -> 选择maven项目的pom.xml。
生命周期
Maven的生命周期就是为了对所有的构建过程进行抽象和统一。 描述了一次项目构建,经历哪些阶段。在Maven出现之前,项目构建的生命周期就已经存在,软件开发人员每天都在对项目进行清理,编译,测试及部署。虽然大家都在不停地做构建工作,但公司和公司间、项目和项目间,往往使用不同的方式做类似的工作。Maven从大量项目和构建工具中学习和反思,然后总结了一套高度完美的,易扩展的项目构建生命周期。这个生命周期包含了项目的清理,初始化,编译,测试,打包,集成测试,验证,部署和站点生成等几乎所有构建步骤。Maven对项目构建的生命周期划分为3套(相互独立):
- clean:清理工作。
- default:核心工作。如:编译、测试、打包、安装、部署等。
- site:生成报告、发布站点等。
每套生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。我们看到这三套生命周期,里面有很多很多的阶段,这么多生命周期阶段,其实我们常用的并不多,主要关注以下几个: - clean:移除上一次构建生成的文件
- compile:编译项目源代码
- test:使用合适的单元测试框架运行测试(junit)
- package:将编译后的文件打包,如:jar、war等
- install:安装项目到本地仓库
Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际工作。在Maven的设计中,实际任务(如源代码编译)都交由插件来完成。IDEA工具为了方便程序员使用maven生命周期,在右侧的maven工具栏中,已给出快速访问通道。 - 生命周期的顺序是:clean –> validate –> compile –> test –> package –> verify –> install –> site –> deploy,而我们需要关注的就是:clean –> compile –> test –> package –> install。
说明:在同一套生命周期中,我们在执行后面的生命周期时,前面的生命周期都会执行。
思考:当运行package生命周期时,clean、compile生命周期会不会运行?
clean不会运行,compile会运行。 因为compile与package属于同一套生命周期,而clean与package不属于同一套生命周期。
补充:三套生命周期又包含哪些具体的阶段呢, 我们来看下面这幅图:
Maven常见问题
- 问题现象:Maven项目中添加的依赖,未正确下载,造成右侧Maven面板中的依赖报红,再次reload重新加载也不会再下载。
- 产生原因:由于网络原因,依赖没有下载完整导致的,在maven仓库中生成了xxx.lastUpdated文件,该文件不删除,不会再重新下载。双击 del.bat这个批处理脚本,就可以递归删除该目录下所有的 xxx.lastUpdated 文件。
一些基础
学习前端网页开发的三剑客HTML、CSS、JS之后,我们就可以制作前端页面了。最终,这些页面资料,我们就可以部署在服务器上,然后打开浏览器就可以直接访问服务器上部署的前端页面了。而像HTML、CSS、JS 以及图片、音频、视频等这些资源,我们都称为静态资源。 所谓静态资源,就是指在服务器上存储的不会改变的数据,通常不会根据用户的请求而变化。那与静态资源对应的还有一类资源,就是动态资源。那所谓动态资源,就是指在服务器端上存储的,会根据用户请求和其他数据动态生成的,内容可能会在每次请求时都发生变化。比如:Servlet、JSP等(负责逻辑处理)。而Servlet、JSP这些技术现在早都被企业淘汰了,现在在企业项目开发中,都是直接基于Spring框架来构建动态资源。而对于我们java程序开发的动态资源来说,我们通常会将这些动态资源部署在Tomcat,这样的Web服务器中运行。 而浏览器与服务器在通信的时候,基本都是基于HTTP协议的。那上述所描述的这种浏览器/服务器的架构模式呢,我们称之为:BS架构。
Spring发展到今天已经形成了一种开发生态圈,Spring提供了若干个子项目,每个项目用于完成特定的功能。spring家族的技术被称为spring全家桶。本项目在项目开发时,选择的是springboot。
springboot一点点解析
我们在创建springboot项目的时候,选择了web开发的起步依赖 spring-boot-starter-web。而spring-boot-starter-web依赖,又依赖了spring-boot-starter-tomcat,由于maven的依赖传递特性,那么在我们创建的springboot项目中也就已经有了tomcat的依赖,这个其实就是springboot中内嵌的tomcat。 而我们运行引导类中的main方法,其实启动的就是springboot中内嵌的Tomcat服务器。 而我们所开发的项目,也会自动的部署在该tomcat服务器中,并占用8080端口号 。
起步依赖:
- 一种为开发者提供简化配置和集成的机制,使得构建Spring应用程序更加轻松。起步依赖本质上是一组预定义的依赖项集合,它们一起提供了在特定场景下开发Spring应用所需的所有库和配置。
- spring-boot-starter-web:包含了web应用开发所需要的常见依赖。
- spring-boot-starter-test:包含了单元测试所需要的常见依赖。
- 官方提供的starter:https://docs.spring.io/spring-boot/docs/3.1.3/reference/htmlsingle/#using.build-systems.starters
每一个起步依赖,都用于开发一个特定的功能。
举例:当我们开发中需要使用redis数据库时,只需要在SpringBoot项目中,引入:springboot-starter-redis ,即可导入redis开发所需要的依赖。
不论使用IDEA创建SpringBoot项目,还是直接在官方网站利用骨架生成SpringBoot项
目,项目的结构和pom.xml文件中内容是相似的。此外,我们通过maven引入的依赖,是没有指定具体的依赖版本号的。因为每一个SpringBoot工程,都有一个父工程。依赖的版本号,在父工程中统一管理。
计网一些小知识复习–HTTP协议
HTTP协议:
- 基于TCP协议: 面向连接,安全
- 基于请求-响应模型
- HTTP协议是无状态协议
HTTP请求协议:浏览器将数据以请求格式发送到服务器。包括:请求行、请求头 、请求体( - GET请求的请求参数在请求行中,故不需要设置请求体)
HTTP响应协议:服务器将数据以响应格式返回给浏览器。包括:响应行 、响应头 、响应体
注:
1.响应状态码
2.Web服务器(Tomcat)对HTTP协议的请求数据进行解析,并进行了封装(HttpServletRequest),并在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷;Web服务器对HTTP协议的响应数据进行了封装(HttpServletResponse),并在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。
请求与响应
那么在后端程序中,如何接收传递过来的普通参数数据呢?
常见的有两种方式
1 | 1. 原始方式 |
IDEA控制台上输出的是sout输出的前端参数。刚才模拟了浏览器向后端服务器发起任何形式的HTTP请求,那么controller方法中的return的结果,怎么就可以响应给浏览器呢?答案:使用@ResponseBody注解
1 | @ResponseBody注解: |
但是在我们所书写的Controller中,只在类上添加了@RestController注解、方法添加了@RequestMapping注解。原因:在类上添加的@RestController注解,是一个组合注解。@RestController = @Controller + @ResponseBody
所以在前后端分离的项目中,一般直接在请求处理类上加@RestController注解,就无需在方法上加@ResponseBody注解了。
定义一个统一的返回结果,包含:响应状态码,状态码信息,返回的数据:给前端响应的数据(字符串、对象、集合)。我们定义在一个实体类Result来包含以上信息。这样我们返回比如说return Result.success(hobby)。在postman中可以看到{
“code”: 1,
“msg”: “success”,
“data”: [
“java”,
“game”
]
}
IOC与DI
先分层
先前的小案例代码太过于臃肿,全都放在Controller层中了。在我们进行程序设计以及程序开发时,尽可能让每一个接口、类、方法的职责更单一些。按照上述的三个组成部分,在我们项目开发中呢,可以将代码分为三层:
Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。
Service:业务逻辑层。处理具体的业务逻辑。
Dao:数据访问层(Data Access Object),也称为持久层。负责数据访问操作,包括数据的
增、删、改、查。
基于三层架构的程序执行流程:
前端发起的请求,由Controller层接收(Controller响应数据给前端)
Controller层调用Service层来进行逻辑处理(Service层处理完后,把处理结果返回给Controller层)
Serivce层调用Dao层(逻辑处理过程中需要用到的一些数据要从Dao层获取)
Dao层操作文件中的数据(Dao拿到的数据会返回给Service层)
三层架构的好处:
- 复用性强
- 便于维护
- 利用扩展
再分离解耦
软件设计原则:高内聚低耦合。
高内聚指的是:一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间
的联系程度越高,则内聚性越高,即 “高内聚”。
低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。
之前我们在编写代码时,需要什么对象,就直接new一个就可以了。 这种做法呢,层与层之间代码就耦
合了,当service层的实现变了之后, 我们还需要修改controller层的代码。那只能不new了,就意味着没有业务层对象(程序运行就报错)。我们的解决思路是:提供一个容器,容器中存储一些对象(例:EmpService对象),然后
controller程序从容器中获取EmpService类型的对象。我们想要实现上述解耦操作,就涉及到Spring中的两个核心概念:
控制反转IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器
依赖注入DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。程序运行时需要某个资源,此时容器就为其提供这个资源。例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入EmpServic对象。
IOC容器中创建、管理的对象,称之为:bean对象。
IOC细节
在之前的入门案例中,要把某个对象交给IOC容器管理,需要在类上添加一个注解:@Component(粗暴)
而Spring框架为了更好的标识web应用程序开发当中,bean对象到底归属于哪一层,又提供了@Component的衍生注解:
@Controller (标注在控制层类上Controller) 再说一遍:在类上添加的@RestController注解,是一个组合注解。@RestController = @Controller + @ResponseBody.所以在前后端分离的项目中,一般直接在请求处理类上加@RestController注解,就无需在方法上加@ResponseBody注解了。
@Service (标注在业务层类上Service)
@Repository (标注在数据访问层类上Dao)
不属于以上三类时用@Component
在IOC容器中,每一个Bean都有一个属于自己的名字,可以通过注解的value属性指定bean的名字。比如
如@Repository(“daoA”)
果没有指定,默认为类名首字母小写。
使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean
只能用@Controller。
DI细节
在入门程序案例中,我们使用了@Autowired(自动装配)这个注解,完成了依赖注入的操作。
@Autowired注解,默认是按照类型进行自动装配的(去IOC容器中找某个类型的对象,然后完成注入
操作)。那如果在IOC容器中,存在多个相同类型的bean对象,程序运行会报错。
Spring提供了以下几种解决方案:
@Primary
@Qualifier
@Resource
1 | 使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。 |
小问题
使用四大注解声明的bean,要想生效,还需要被组件扫描注解@ComponentScan扫描。
@ComponentScan注解虽然没有显式配置,但是实际上已经包含在了引导类声明注解@SpringBootApplication 中, 默认扫描的范围是SpringBoot启动类所在包及其子包。
推荐做法:将我们定义的controller,service,dao这些包呢,都放在引导类所在包com.itheima的子包下,这样我们定义的bean就会被自动的扫描到
数据库
MySQL已经安装
MySQL、Oracle、DB2、SQLServer这些都是属于关系型数据库,里面都是基于二维表存储数据的。
注:不是基于二维表存储数据的数据库,就是非关系型数据库(比如Redis)。
SQL语句根据其功能被分为四大类:DDL、DML、DQL、DCL
DDL 数据定义语言,用来定义数据库对象(数据库,表,字段)
DML 数据操作语言,用来对数据库表中的数据进行增删改
DQL 数据查询语言,用来查询数据库中表的记录
DCL 数据控制语言,用来创建数据库用户、控制数据库的访问权限
图形化工具
连接数据库步骤:
1.打开IDEA自带的Database
2、配置MySQL
3、输入相关信息
4、下载MySQL连接驱动
5、测试数据库连接
6、保存配置
其实工具底层也是通过DDL语句操作的数据库,只不过这些SQL语句是图形化界面工具帮我们自动
完成的。
DDL
常见操作:查询、创建、使用、删除
操作数据库
1.查询
查询所有数据库:show databases;
查询当前数据库:select database();
2.创建
语法:– 数据库不存在,则创建该数据库;如果存在则不创建
create database if not extists itcast;
3 使用数据库
语法:use 数据库名 ;
我们要操作某一个数据库下的表时,就需要通过该指令,切换到对应的数据库下,否则不能操作。
4 删除数据库
语法:drop database [ if exists ] 数据库名 ;
如果删除一个不存在的数据库,将会报错。可以加上参数 if exists ,如果数据库存在,再执行删除,否则不执行删除。
说明:上述语法中的database,也可以替换成 schema
如:create schema db01;
如:show schemas;
表结构的操作
创建表、查询表、修改表、删除表。
1.创建表
1 | create table 表名( |
注意: [ ] 中的内容为可选参数; 最后一个字段后面没有逗号;约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段值不能为null | not null |
唯一约束 | 保证字段的所有数据都是唯一、不重复的 | unique |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | primary key |
默认约束 | 保存数据时,如果未指定该字段值,则采用默认值 | default |
外键约束 | 让两张表的数据建立连接,保证数据的一致性和完整性 | foreign key |
偷个懒:
主键自增:auto_increment
每次插入新的行记录时,数据库自动生成id字段(主键)下的值。具有auto_increment的数据列是一个正数序列开始增长(从1开始自增)
2.查询表
1 | 查询当前数据库所有表 show tables; |
3.修改表
关于表结构的修改操作,工作中一般都是直接基于图形化界面操作。
添加字段alter table 表名 add 字段名 类型(长度) [comment 注释] [约束];
案例: 为tb_emp表添加字段qq,字段类型为 varchar(11)
图形化操作:添加字段
alter table tb_emp add qq varchar(11) comment ‘QQ号码’;
4.删除表
删除字段
案例:删除tb_emp表中的qq_num字段alter table 表名 drop 字段名;
图形化操作:删除字段
alter table tb_emp drop qq_num;
修改表名
案例:将当前的tb_emp表的表名修改为emp rename table 表名 to 新表名;
图形化操作:修改表名
rename table tb_emp to emp
删除
关于表结构的删除操作,工作中一般都是直接基于图形化界面操作。
删除表语法:drop table [ if exists ] 表名;
if exists :只有表名存在时才会删除该表,表名不存在,则不执行删除操作(如果不加该参数
项,删除一张不存在的表,执行将会报错)。
案例:如果tb_emp表存在,则删除tb_emp表
drop table if exists tb_emp; – 在删除表时,表中的全部数据也会被删除。
图形化操作:删除表
MySQL的数据类型
MySQL中的数据类型有很多,主要分为三类:数值类型、字符串类型、日期时间类型
char是定长字符串,指定长度多长,就占用多少个字符,和字段值的长度无关 。而varchar是变长字符串,指定的长度为最大占用长度 。相对来说,char的性能会更高些。
DATE 3 1000-01-01 至 9999-12-31 YYYY-MM-DD 日期值
TIME 3 -838:59:59 至 838:59:59 HH:MM:SS时间值或持续时间
YEAR 1 1901 至 2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00 至9999-12-31 23:59:59YYYY-MM-DD HH:MM:SS 混合日期和时间值
TIMESTAMP 4 1970-01-01 00:00:01 至2038-01-19 03:14:07 YYYY-MM-DD HH:MM:SS 混合日期和时间值,时间戳
数据库操作-DML
DML英文全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进
行增、删、改操作。
添加数据(INSERT)
1 | 向指定字段添加数据insert into 表名 (字段名1, 字段名2) values (值1, 值2); |
修改数据(UPDATE)
1 | update 表名 set 字段名1 = 值1 , 字段名2 = 值2 , .... [where 条件] ; |
注:1. 修改语句的条件可以有,也可以没有,如果没有条件,则会修改整张表的所有数据。
2. 在修改数据时,一般需要同时修改公共字段update_time,将其修改为当前操作时间。
删除数据(DELETE)
1 | delete from 表名 [where 条件] ; |
DQL
1 | DQL查询语句,语法结构如下: |
查询多个字段select 字段1, 字段2, 字段3 from 表名;
查询所有字段(通配符) select * from 表名;
注:* 号代表查询所有字段,在实际开发中尽量少用(不直观、影响效率)
设置别名select 字段1 [ as 别名1 ] , 字段2 [ as 别名2 ] from 表名;
去除重复记录select distinct 字段列表 from 表名;
在SQL语句当中构造条件的运算符分为两类:比较运算符,逻辑运算符
列举一些易混淆的
between … and … 在某个范围之内(含最小、最大值)
in(…) 在in之后的列表中的值,多选一
like 占位符 模糊匹配(_匹配单个字符, %匹配任意个字符)
is null 是null(查询为NULL的数据时,不能使用 = null)
where与having区别
执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组
之后对结果进行过滤。
判断条件不同:where不能对聚合函数进行判断,而having可以。
注意事项:如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序
if(表达式, tvalue, fvalue) :当表达式为true时,取值tvalue;当表达式为false时,
取值fvalue
case 表达式 when 值1 then 结果1 [when 值2 then 结果2 …]
[else result] end
多表设计:
一对多关系实现:在数据库表中多的一方,添加字段,来关联属于一这方的主键。
一对一 :在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)
多对多实现关系:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
java语言操作数据库,只能通过一种方式:使用sun公司提供的 JDBC 规范。
Java程序操作数据库,现在主流的方式是:Mybatis。MyBatis是一款优秀的 持久层 框架,是对原始的JDBC程序的封装,用于简化JDBC的开发。
原始的JDBC程序,存在以下几点问题:
- 数据库链接的四要素(驱动、链接、用户名、密码)全部硬编码在java代码中
- 查询结果的解析及封装非常繁琐
- 每一次查询数据库都需要获取连接,操作完毕后释放连接, 资源浪费, 性能降低
分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的: - 数据库连接四要素(驱动、链接、用户名、密码),都配置在springboot默认的配置文件
application.properties中 - 查询结果的解析及封装,由mybatis自动完成映射封装,我们无需关注
- 在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪
费。
在springboot项目中,可以编写application.properties文件,配置数据库连接信息。我们要连
接数据库,就需要配置数据库连接的基本信息
1 | #驱动类名称 |
数据库连接池的好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
常见的数据库连接池:
C3P0
DBCP
Druid
Hikari (springboot默认)
现在使用更多的是:Hikari、Druid (性能更优越)
Hikari(追光者) [默认的连接池]
Druid(德鲁伊)
Druid连接池是阿里巴巴开源的数据库连接池项目
功能强大,性能优秀,是Java语言最好的数据库连接池之一
如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要完成以下两步操作即可:
- 在pom.xml文件中引入依赖
1
2
3
4
5
6<dependency>
<!-- Druid连接池依赖 -->
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency> - 在application.properties中引入数据库连接配置
方式1:spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.druid.username=root
spring.datasource.druid.password=1234
方式2:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.username=root
spring.datasource.password=1234
而对于Mybatis来说,我们在开发持久层程序操作数据库时,需要重点关注以下两个方面:
- application.properties
- Mapper接口(编写SQL语句)
在创建出来的SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类 ,并且
在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与SpringBoot整合。
该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。我们要测试那个bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。
@Mapper注解:表示是mybatis中的Mapper接口
程序运行时:框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理
@Select注解:代表的就是select查询,用于书写select查询语句
@Delete注解:用于编写delete操作的SQL语句
如果mapper接口方法形参只有一个普通类型的参数,#{…} 里面的属性名可以随便写,如:#
{id}、#{value}。但是建议保持名字一致。
Lombok是一个实用的Java类库,可以通过简单的注解来简化和消除一些必须有但显得很臃肿的Java代码。通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发、提高效率。第1步:在pom.xml文件中引入依赖
第2步:在实体类上添加注解@Data,那么这个类在编译时期,就会生成getter/setter、equals、
hashcode、toString等方法。
注意:@Data注解中不包含全参构造方法,通常在实体类上,还会添加上:全参构造、无参构造;
Lombok会在编译时,会自动生成对应的java代码;
在使用lombok时,还需要安装一个lombok的插件(新版本的IDEA中自带)。
在Mybatis当中我们可以借助日志,查看到sql语句的执行、执行传递的参数以及执行结果。具体操作如下:
- 打开application.properties文件
- 开启mybatis的日志,并指定输出到控制台
1
2#指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.logimpl=org.apache.ibatis.logging.stdout.StdOutImpl
预编译SQL有两个优势:
- 性能更高
- 更安全(防止SQL注入)
性能更高:预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句
时,不会再次编译。(只是输入的参数不同)
更安全(防止SQL注入):将敏感字进行转义,保障SQL的安全性
SQL注入:由于没有对用户输入进行充分检查,而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。默认情况下,执行插入操作时,是不会主键值返回的。如果我们想要拿到主键值,需要在Mapper1
2
3
4
5
6
7
8
9
10
11
12在Mybatis中提供的参数占位符有两种:${...} 、#{...}
#{...}
执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
使用时机:参数传递,都使用#{…}
${...}
拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
使用时机:如果对表名、列表进行动态设置时使用 比如姓名张开头
where name like '%${name}%'
where name like concat('%',#{name},'%')
解决:使用MySQL提供的字符串拼接函数:concat('%' , '关键字' , '%')
注意事项:在项目开发中,建议使用#{...},生成预编译SQL,防止SQL注入安全。
说明:#{...} 里面写的名称是对象的属性名
接口中的方法上添加一个Options注解,并在注解中指定属性useGeneratedKeys=true和
keyProperty=”实体类属性名”
实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装。
如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。
解决方案:
- 起别名 在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样
- 结果映射 通过 @Results及@Result 进行手动结果映射
@Results({@Result(column = “dept_id”, property = “deptId”),
@Result(column = “create_time”, property = “createTime”),
@Result(column = “update_time”, property = “updateTime”)})
@Select(“select id, username, password, name, gender, image, job,
entrydate, dept_id, create_time, update_time from emp where id=#{id}”)
public Emp getById(Integer id); - 开启驼峰命名Mybatis的开发有两种方式:
1
2# 在application.properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true - 注解
- XML
在Mybatis中使用XML映射文件方式开发,需要符合一定的规范: - XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下
(同包同名) - XML映射文件的namespace属性为Mapper接口全限定名一致
- XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
配置:XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致
使用XML映射文件后动态SQL规避bug
1 | <if> :用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。 |
需要引入的依赖
1 | 1.引入dom4j的依赖,用于解析XML文件 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<!-- mybatis起步依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<!-- mysql驱动包依赖 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- spring单元测试 (集成了junit) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>- IDEA中需要安装的插件
1
2
3
4
5
6<!-- 在springboot的父工程中,已经集成了lombok并指定了版本号,故当前引入依赖
时不需要指定version -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>正式开始项目!1
2
31.lombok(老版本需要)
2.grep console
3.mybatis x
后端开发人员:必须严格遵守提供的接口文档进行后端功能开发(保障开发的功能可以和前端对接)
而在前后端进行交互的时候,我们需要基于当前主流的REST风格的API接口进行交互。
在REST风格的URL中,通过四种请求方式,来操作数据的增删改查。
- GET : 查询
- POST :新增
- PUT : 修改
- DELETE :删除
浏览器中所发起的所有的请求,都是GET方式的请求。
前后端都在并行开发时,可以借助一些接口测试工具,比如:Postman,后端开发完对应的接口之后,对接口进行请求测试;前端开发过程中,获取到数据,测试页面的渲染展示。
步骤:
- 准备数据库表
- 创建springboot工程,引入对应的起步依赖(web、mybatis、mysql驱动、lombok)
- 配置文件application.properties中引入mybatis的配置信息,准备对应的实体类
- 准备对应的Mapper、Service(接口、实现类)、Controller基础结构
1