前端

学习网站 w3school

MVVM

MVVM(Model-View-ViewModel):
Model: 数据模型,前端请求从后台获取的数据 —> Ajax
View: 视图,html+css无数据处理 —> Element UI
ViewModel: 将数据用JS的DOM技术展示到视图上 —> Vue

DOM

DOM技术(文档对象模型)接口,动态访问和更新网页。
核心是将HTML或XML文档视为一个树形结构。
通过DOM,可用JS等来操作节点,从而实现对页面内容的修改、添加或删除等功能。

  • 节点(Node): 基本单位,元素、属性、文本。
  • 元素(Element): 节点的一种,比如<div>, <p>等。
  • 属性(Attribute): 如id, class等。

常用DOM操作

  1. 获取元素:
    ○ document.getElementById() 通过ID获取单个元素
    ○ document.getElementsByTagName() 通过标签名获取一组元素
    ○ document.querySelector() 和 document.querySelectorAll() 使用CSS选择器来获取单个或多个元素
  2. 修改元素内容:
    ○ element.innerHTML 修改元素内部的HTML代码
    ○ element.textContent 只修改元素内的文本内容
  3. 修改元素属性:
    ○ element.setAttribute(name, value) 设置属性值
    ○ element.getAttribute(name) 获取属性值
    ○ element.removeAttribute(name) 删除属性
  4. 添加/移除元素:
    ○ parentElement.appendChild(newChild) 向父元素添加子元素
    ○ parentElement.removeChild(oldChild) 从父元素中移除子元素
  5. 事件监听:
    ○ element.addEventListener(event, function, useCapture) 为元素添加事件处理器
    ○ element.removeEventListener(event, function, useCapture) 移除事件处理器

Vue:提高开发的效率

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initialscale=1.0">

<title>Vue-快速入门</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
{{message}}
</div>
</body>
<script>
//定义Vue对象
new Vue({
el: "#app", //vue接管区域
data:{
message: "Hello Vue"
}
})
</script>
</html>

el: 用来指定哪儿些标签受 Vue 管理。该属性取值#app中的app需要是受管理的标签的id属性值
data: 用来定义数据模型
methods: 用来定义函数
{{}}插值表达式:用来将vue对象中定义的model展示到页面上

指令 作用
v-bind 为HTML标签绑定属性值,如设置 href , css样式等,当vue对象中的数据模型发 、生变化时,标签的属性值会随之发生变化
v-model 在表单元素上创建双向数据绑定,一定使用在表单项标签上
v-on
简写@
为HTML标签绑定事件,给标签的事件绑定的函数必须是vue对象种声明的函数,绑定事件时,事件名相比较js中的事件名,没有on
v-if v-else v-else-if
v-show 根据条件展示某元素,区别在于切换的是display属性的值,和v-if的作用效果是一样的,只是原理不一样
v-for 列表渲染,遍历容器的元素或者对象的属性 <标签v-for=”变量名/(变量名,索引变量) in 集合模型数据”> 标签>

Ajax(异步的JS和XML)

客户端的Ajax请求代码如下有如下4步:

  1. 首先创建AJAX的文件夹,并且创建html文件,按钮绑定单击事件希望点击按钮发送ajax请求
  2. 创建Request对象,连接服务器
  3. 调用对象的open()方法设置请求的参数信息(请求地址,请求方式),然后调用 send()方法向服务器发送请求
  4. 通过绑定事件的方式,来获取服务器响应的数据,通过浏览器f12抓包,点击网络中的XHR请求抓包到我们发送的Ajax请求

    XHR代表的就是异步请求

Axios

Axios是对原生的Ajax进行封装,简化书写。
Axios官网

使用
引入Axios文件
使用Axios发送请求,并获取响应结果,官方提供的api很多,此处给出2种,如下

  1. 发送 get 请求
    axios({ method:"get", url:"http://localhost:8080/ajax-demo1/aJAXDemo1? username=zhangsan" }).then(function (resp){ alert(resp.data); })
  2. 发送 post 请求
    axios({ method:"post", url:"http://localhost:8080/ajax-demo1/aJAXDemo1", data:"username=zhangsan" }).then(function (resp){ alert(resp.data); });

axios()是用来发送异步请求的,小括号中使用 js的JSON对象传递请求相关的参数:
method属性:用来设置请求方式的,取值为 get 或 post
url属性:用来书写请求的资源路径
如果是 get 请求,需要将请求参数拼接到路径的后面,格式为:url?参数名=参数值&参数名2=参数值2。
data属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为 data 属性的值。
then() 需要传递一个匿名函数(回调函数)意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。
而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。

Axios还针对不同的请求,提供了别名方式的api,具体如下:

方法 描述
axios.get(url [, config]) 发送get请求
axios.delete(url [, config]) 发送delete请求
axios.post(url [, data[, config]]) 发送post请求
axios.put(url [, data[, config]]) 发送put请求

axios.get("http://yapi.smartxwork.cn/mock/169327/emp/list").then(result => { console.log(result.data); })

axios.post("http://yapi.smartxwork.cn/mock/169327/emp/deleteById","id=1").then(result => { console.log(result.data); })

前端工程化

前端工程化通过脚手架Vue-cli完成,快速的生成一个Vue的项目模板。
需要先安装 NodeJS,然后才能安装Vue-cli
Vue-cli主要提供了如下功能:

  1. 统一的目录结构
  2. 本地调试
  3. 热部署
  4. 单元测试
  5. 集成打包上线
    npm create vue@latest

main.js

1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({ //创建vue对象
router, //路由
render: h => h(App) //主要使用视图的渲染,vue创建的dom对象挂在到id=app的标签区域
}).$mount('#app') //将vue对象创建的dom对象挂在到id=app的这个标签区域中
//作用和之前学习的vue对象的le属性一致

Element
饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页

vue路由

vue官方提供了路由插件Vue Router,其主要组成如下:
VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件
:请求链接组件,浏览器会解析成
:动态视图组件,用来渲染展示与路由路径对应的组件

安装插件 npm install vue-router@3.5.1
在src/router/index.js文件中定义路由表,根据其提供的模板代码进行修改
修改页面按钮为router-link,App.vue中定义route-view,作为组件的切换

前端工程打包

NPM脚本中提供的build按钮
通过nginx服务器发布前端工程
轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器

直接将资源放入到html目录中

dist目录下得内容拷贝到nginx的html目录下
双击nginx.exe文件启动nginx
nginx服务器的端口号是80直接访问 http://localhost:80 即可,其中80端口可省略

Nginx默认占用80端口号,如果80端口号被占用,可以在nginx.conf中修改端口号。(netstat –ano | findStr 80)

接口文档

当前最为主流的开发模式:前后端分离
页面原型+需求

  1. 基本信息
  2. 请求参数
  3. 响应数据

后端

Maven

https://maven.apache.org/

  1. 依赖管理
  2. 统一项目结构
  3. 项目构建

仓库:用于存储资源,管理各种jar包

  • 本地仓库:自己计算机上的一个目录(用来存储jar包)
  • 中央仓库:由Maven团队维护的全球唯一的。仓库地址:<https://repo1.maven.org/maven 2/>
  • 远程仓库(私服):一般由公司团队搭建的私有仓库

使用方法一
下载地址:https://maven.apache.org/download.cgi

bin目录:存放的是可执行命令。(mvn 命令重点关注)
conf目录:存放Maven的配置文件。(settings.xml配置文件后期需要修改)
lib目录:存放Maven依赖的jar包。

本地仓库
新建一个目录
conf下修改settings.xml
定位到53行,复制标签,粘贴到注释的外面(55行)
复制之前新建的用来存储jar包的路径,替换掉标签体内容

配置阿里云私服
conf下修改settings.xml
定位到160行左右,在标签下为其添加子标签

1
2
3
4
5
6
<mirror>  
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

配置环境变量
新建一个变量MAVEN_HOME,环境变量的值,设置为maven的解压安装目录
PATH环境变量的值,设置为:%MAVEN_HOME%\bin
检查安装 mvn -v

使用方法二
选择 IDEA中 File => Settings => Build,Execution,Deployment => Build Tools => Maven
选择 IDEA中 File => close project

POM (Project Object Model)
指的是项目对象模型,用来描述当前的maven项目
groupId:定义当前Maven项目隶属组织名称
artifactId:定义当前Maven项目名称

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 清理项目
mvn clean

# 编译项目
mvn compile

# 运行测试
mvn test

# 打包项目
mvn package

# 安装到本地仓库
mvn install

# 清理并打包
mvn clean package

# 运行 Spring Boot 应用
mvn spring-boot:run

Spring

依赖注入(DI)、事务管理、web开发支持、数据访问、消息服务等等
勾选web开发相关依赖

创建一个子包controller,包下新建一个类:HelloController

1
2
3
4
5
6
7
8
9
10
package com.itheima.controller;
import org.springframework.web.bind.annotation.*;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
System.out.println("Hello World ~");
return "Hello World ~";
}
}

WEB服务器-Tomcat

免费的开源的web应用服务器,Web容器、Servlet容器
Tomcat的官网: https://tomcat.apache.org/

使用步骤

  1. 准备静态资源
  2. 下载安装Web服务器软件
  3. 将静态资源部署到Web服务器上
  4. 启动Web服务器使用浏览器访问对应的资源

bin:目录下有两类文件,一种是以 .bat 结尾的,是Windows系统的可执行文件,一种是以 .sh 结尾 的,是Linux系统的可执行文件。
webapps:就是以后项目部署的目录

Tomcat的默认端口为8080,所以在浏览器的地址栏输入http://127.0.0.1:8080即可访问tomcat服务器
正常关闭:bin\shutdown.bat或者Ctrl+C

问题1:Tomcat启动时,窗口一闪而过(检查JAVA_HOME环境变量是否正确配置)
问题2:端口号冲突

spring-boot-starter-web和spring-boot-starter-test,在SpringBoot中又称为:起步依赖
而在SpringBoot的项目中,有很多的起步依赖,共同的特征:就是以 spring-boot-starter- 作开头
spring-boot-starter-web:包含了web应用开发所需要的常见依赖(集成了内置的Tomcat服务器)
spring-boot-starter-test:包含了单元测试所需要的常见依赖
举例:当我们开发中需要使用redis数据库时,只需要在SpringBoot项目中,引入:springboot-starter-redis ,即可导入redis开发所需要的依赖。

BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。

Postman

作用:进行接口测试

简单参数:在向服务器发起请求时,向服务器传递的是一些普通的请求数据

后端接收传递过来的普通参数数据

  1. 原始方式
    通过Servlet中提供的API:HttpServletRequest(请求对象),获取请求的相关信息
    在Controller中,我们要想获取Request对象,可以直接在方法的形参中声明 HttpServletRequest 对象
  2. SpringBoot方式
    Springboot的环境中,对原始的API进行了封装,接收参数的形式更加简单
    如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数
    使用Spring提供的@RequestParam注解完成映射,方法形参前面加上 @RequestParam 然后通过value属性执行请求参数名,从而完成映射

实体参数:将请求参数封装到一个实体类对象中(请求参数名与实体类的属性名相同)

数组集合参数:
数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数
前端请求时,有两种传递形式
方式一: xxxxxxxxxx?hobby=game&hobby=java
方式二:xxxxxxxxxxxxx?hobby=game,java
集合参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam 绑定参数关系
前端请求时,有两种传递形式
方式一: xxxxxxxxxx?hobby=game&hobby=java
方式二:xxxxxxxxxxxxx?hobby=game,java
日期参数:
日期类型的参数在进行封装时,需要通过@DateTimeFormat注解以及其pattern属性来设置日期的格式
@DateTimeFormat注解的pattern属性中指定了哪种日期格式,前端的日期参数就必须按照指定的格式传递。 后端controller方法中,需要使用Date类型或LocalDateTime类型,来封装传递的参数。
JSON参数:

  1. Postman在发送请求时,如何传递json格式的请求参数
  2. 在服务端的controller方法中,如何接收json格式的请求参数
    (1. 传递json格式的参数,在Controller中会使用实体类进行封装
    (2. 封装规则:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数。需要使用 @RequestBody标识。
    (3. @RequestBody注解:将JSON数据映射到形参的实体类对象中(JSON中的key和实体类中的属性 名保持一致)

路径参数:
直接在请求的URL中传递参数,掌握在后端的controller方法中,如何接收路径参数
前端:通过请求URL直接传递参数
后端:使用{…}来标识该路径参数,需要使用@PathVariable获取路径参数

响应

Controller程序,除了接收请求外,还可以进行响应
@ResponseBody
类型:方法注解、类注解
位置:Controller方法上或类上
作用:将方法返回值(controller方法中的return的结果)直接响应给浏览器
如果返回值类型是实体对象/集合,将会转换为JSON格式后在响应给浏览器
@RestController = @Controller + @ResponseBody(组合注解)

统一响应结果

统一的返回结果使用类来描述,在这个结果中包含:

  • 响应状态码:当前请求是成功,还是失败
  • 状态码信息:给页面的提示信息
  • 返回的数据:给前端响应的数据(字符串、对象、集合)

当我们要修改操作数据部分的代码,需要改动Controller
当我们要完善逻辑处理部分的代码,需要改动Controller
当我们需要修改数据响应的代码,还是需要改动Controller

会造成整个工程代码的复用性比较差,而且代码难以维护。
有非常成熟的解决思路,分层开发

分层解耦

  • Controller:控制层。接收前端发送的请求,请求处理,响应数据
  • Service:业务逻辑层。处理具体业务逻辑
  • Dao:数据访问层,也称为持久层。数据访问操作,增、删、改、查
    高内聚低耦合

控制反转: Inversion Of Control,简称IOC
对象的创建控制权由程序自身转移到外部 (容器)

对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC 容器Spring 容器
Spring 提供两种类型的IoC容器:

  1. BeanFactory:最简单的容器,提供基本的Dl支持。
  2. ApplicationContext:扩展了BeanFactory,.增加了更多企业级功能,如事件发布、国际化支持、资源加载
    等。在大多数场景下,我们使用ApplicationContext,因为它提供了更丰富的功能。

依赖注入: Dependency Injection,简称DI
容器为应用程序提供运行时,所依赖的资源

程序运行时需要某个资源,此时容器就为其提供这个资源。
例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入 EmpService对象
IOC容器中创建、管理的对象,称之为:bean对象
依赖注入有三种注入方式:

  1. 构造器注入
  2. 字段注入(使用注解)
  3. setter方法注入

注意
注意:虽然字段注入使用起来最为简便,但Spring团队推荐使用构造函数注入,因为它可以: ·确保依赖不可变 ·确保必要的依赖在对象创建时就已存在 ·便于单元测试

完成Controller层、Service层、Dao层的代码解耦
思路:

  1. 删除Controller层、Service层中new对象的代码
  2. Service层及Dao层的实现类,交给IOC容器管理
    Spring提供的注解:@Component ,就可以实现类交给IOC容器管理
  3. 为Controller及Service注入运行时依赖的对象

Controller程序中注入依赖的Service层对象
Service程序中注入依赖的Dao层对象
Spring提供的注解:@Autowired ,就可以实现程序运行时IOC容器自动注入需要的依赖对象

@Component的衍生注解:
@Controller (标注在控制层类上)
@Service (标注在业务层类上)
@Repository (标注在数据访问层类上)dao
在IOC容器中,每一个Bean都有一个属于自己的名字,可以通过注解的value属性指定bean的名字。如果没有指定,默认为类名首字母小写。
在springboot集成web开发中,声明控制器bean 只能用@Controller
使用四大注解声明的bean,要想生效,还需要被组件扫描注解@ComponentScan扫描
@SpringBootApplication 中, 默认扫描的范围是SpringBoot启动类所在包及其子包

在IOC容器中,存在多个相同类型的bean对象,程序运行会报错
使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现
使用@Qualifier注解:指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的 bean的名称。
使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称
@Autowird 与 @Resource的区别
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
@Autowired 默认是按照类型注入,而@Resource是按照名称注入

Bean的生命周期

在Spring容器中,Bean有一个明确的生命周期:

  1. 实例化:创建Bean的实例
  2. 填充属性:设置Bean的属性值和依赖关系
  3. 初始化前:调用 BeanPostProcessor 的postProcessBeforelnitialization方法
  4. 初始化:调用Bean的初始化方法(@PostConstruct注解的方法或实现Initializing Bean接口的afterPropertiesSet方法)
  5. 初始化后:调用BeanPostProcessor的postProcessAfterlnitialization方法
  6. 使用:Bean可以被应用程序使用
  7. 销毁:当容器关闭时,调用Bean的销毁方法(@PreDestroy注解的方法或实现DisposableBean接口的destroy方法)

Mybatis

Java操作数据库,现在主流的方式是:Mybatis
MyBatis是一款优秀的持久层框架,用于简化JDBC的开发
官网:https://mybatis.org/mybatis-3/zh/index.html
持久层:dao,操作数据库

创建用户表user,并创建对应的实体类User

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- 用户表
create table user(
id int unsigned primary key auto_increment comment 'ID',
name varchar(100) comment '姓名',
age tinyint unsigned comment '年龄',
gender tinyint unsigned comment '性别, 1:男, 2:女',
phone varchar(11) comment '手机号'
) comment '用户表';
-- 测试数据
insert into user(id, name, age, gender, phone) VALUES (null,'白眉鹰
王',55,'1','18800000000');
insert into user(id, name, age, gender, phone) VALUES (null,'金毛狮
王',45,'1','18800000001');
insert into user(id, name, age, gender, phone) VALUES (null,'青翼蝠
王',38,'1','18800000002');
insert into user(id, name, age, gender, phone) VALUES (null,'紫衫龙
王',42,'2','18800000003');
insert into user(id, name, age, gender, phone) VALUES (null,'光明左
使',37,'1','18800000004');
insert into user(id, name, age, gender, phone) VALUES (null,'光明右
使',48,'1','18800000005');
1
2
3
4
5
6
7
8
9
public class User {
private Integer id; //id(主键)
private String name; //姓名
private Short age; //年龄
private Short gender; //性别
private String phone; //手机号

//省略GET, SET方法
}

在springboot项目中编写application.properties文件,配置数据库连接信息。
连接数据库,就需要配置数据库连接的基本信息,包括:driver-class-name、url 、username, password

1
2
3
4
5
6
7
8
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

在创建出来的springboot工程中,在引导类所在包下,在创建一个包 mapper。
在mapper包下创建 一个接口 UserMapper ,这是一个持久层接口(Mybatis的持久层接口规范一般都叫 XxxMapper)

1
2
3
4
5
6
@Mapper //表示是mybatis中的Mapper接口
public interface UserMapper {
//查询所有用户数据,select查询,用于书写select查询语句
@Select("select id, name, age, gender, phone from user")
public List<User> list();
}

在SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类,并且在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与SpringBoot整合。
该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。
我们要测试那个bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。

JDBC

Java语言操作关系型数据库的一套API

  1. 注册驱动
  2. 获取连接对象
  3. 执行SQL语句,返回执行结果
  4. 处理执行结果
  5. 释放资源

数据库连接池是个容器,负责分配、管理数据库连接(Connection)
程序启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用) 释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据 库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象

数据库连接池的好处:

  1. 资源重用
  2. 提升系统响应速度
  3. 避免数据库连接遗漏

实现数据库连接池
官方(sun)提供了数据库连接池标准(javax.sql.DataSource接口)
功能:获取连接
public ConnectiongetConnection() throws SQLException;
第三方组织必须按照DataSource接口实现
常见的数据库连接池:C3P0 DBCP Druid Hikari(springboot默认)
现在使用更多的是:Hikari、Druid (性能更优越)
Hikari(追光者) [默认的连接池]
Druid(德鲁伊) 阿里巴巴开源的数据库连接池项目,Java语言最好的数据库连接池之一

默认的数据库连接池切换为Druid数据库连接池
参考官方地址:<https://github.com/alibaba/druid/tree/master/druid-spring-b oot-starter>
在pom.xml文件中引入依赖
在application.properties中引入数据库连接配置

MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生
Mybatis的开发有两种方式:

  1. 注解
  2. XML
    使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建 议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。
    在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:
  3. XML映射文件的名称与Mapper接口名称一致,并且放置在相同包下(同包同名)
  4. XML映射文件的namespace属性为Mapper接口全限定名一致
  5. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。

    标签:就是用于编写select查询语句的。resultType属性,指的是查询返回的单条记录所封装的类型。

编写XML映射文件
xml映射文件中的dtd约束,直接从mybatis官网复制即可

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">

</mapper>

动态SQL
SQL语句会随着用户的输入或外部条件的变化而变化
:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL
:标签代替SQL语句中的where关键字
只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或 OR
:标签代替SQL语句中的set关键字
动态的在SQL语句中插入set关键字,并会删掉额外的逗号(用于update语句中)
:遍历deleteByIds方法中传递的参数ids集合
:定义可重用的SQL片段
:通过属性refid,指定包含的SQL片段

事务管理

事务是一组操作的集合,它是一个不可分割的工作单位。
事务会把所有的操作作为一个整体,一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功,要么同时失败。
事务的操作主要有三步:

  1. 开启事务(一组操作开始前,开启事务):start transaction / begin ;
  2. 提交事务(这组操作全部成功后,提交事务):commit ;
  3. 回滚事务(中间任何一个操作出现异常,回滚事务):rollback ;

在spring框架当中就已经把事务控制的代码都已经封装好了,并不需要我们手动实现。只需要@Transactional就搞定了
@Transactional作用:就是在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交 事务。如果在这个方法执行的过程当中出现了异常,就会进行事务的回滚操作。
@Transactional注解:我们一般会在业务层当中来控制事务,因为在业务层当中,一个业务功 能可能会包含多个数据访问的操作。在业务层来控制事务,我们就可以将多个数据访问操作控制在 一个事务范围内。
@Transactional注解书写位置:
方法 当前方法交给spring进行事务管理
类 当前类中所有的方法都交由spring进行事务管理
接口 接口下所有的实现类当中所有的方法都交给spring 进行事务管理

@Transactional注解当中的两个常见的属性:

  1. 异常回滚的属性:rollbackFor
    默认情况下,只有出现RuntimeException(运行时异常)才会回滚事务。
    让所有的异常都回滚,需要来配置@Transactional注解当中的rollbackFor属性,通过rollbackFor这个属性可以指定出现何种异常类型回滚事务。

  2. 事务传播行为:propagation
    我们要想控制事务的传播行为,在@Transactional注解的后面指定一个属性propagation,通过 propagation 属性来指定传播行为。
    接下来我们就来介绍一下常见的事务传播行为:

  • REQUIRED 【默认值】需要事务,有则加入,无则创建新事务
  • REQUIRES_NEW 需要新事务,无论有无,总是创建新事务
  • SUPPORTS 支持事务,有则加入,无则在无事务状态中运行
  • NOT_SUPPORTED 不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
  • MANDATORY 必须有事务,否则抛异常
  • NEVER 必须没事务,否则抛异常

场景
lREQUIRED :大部分情况下都是用该传播行为即可。
lREQUIRES_NEW :当我们不希望事务之间相互影响时,可以使用该传播行为。
比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。

AOP

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

  • 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)例如:部分业务方法都是可以被aop控制的方法
  • 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法) 在AOP面向切面编程当中,只需要将这部分重复代码逻辑抽取出来单独定义。
  • 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用在通知当中,定义的共性功能到底要应用在哪些方法上?此时就涉及到了切入点。切入点指的是匹配连接点的条件。通知仅会在切入点方法运行时才会被应用。 在aop的开发当中,我们通常会通过一个切入点表达式来描述切入点
  • 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)当通知和切入点结合在一起,就形成了一个切面。通过切面就能够描述当前aop程序需要针对于哪个原始方法,在什么时候执行什么样的操作
  • 目标对象:Target,通知所应用的对象
  1. 通知类型
    @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
    @Before:前置通知,此注解标注的通知方法在目标方法前被执行
    @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
    @AfterReturning :返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
    @AfterThrowing :异常后通知,此注解标注的通知方法发生异常后执行

    程序没有发生异常的情况下,@AfterThrowing标识的通知方法不会执行。
    程序发生异常的情况下: @AfterReturning标识的通知方法不会执行,@AfterThrowing标识的通知方法执行了 @Around环绕通知中原始方法调用时有异常,通知中的环绕后的代码逻辑也不会在执行了(因为原始方法调用已经出异常了)
    @Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行 @Around环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回值,否则原始方法 执行完毕,是获取不到返回值的。
    切入点表达式重复的问题?答案就是:抽取
    Spring提供了@PointCut注解,该注解的作用是将公共的切入点表达式抽取出来,需要用到时引用该切入点表达式即可。
    需要注意的是:当切入点方法使用private修饰时,仅能在当前切面类中引用该表达式,当外部其他切面类中也要引用当前类中的切入点表达式,就需要把private改为public,而在引用的时候,具体的语法为: 全类名.方法名()

  2. 通知顺序
    通过以上程序运行可以看出在不同切面类中,默认按照切面类的类名字母排序:
    目标方法前的通知方法:字母排名靠前的先执行
    目标方法后的通知方法:字母排名靠前的后执行
    如果我们想控制通知的执行顺序有两种方式:

  3. 修改切面类的类名(这种方式非常繁琐、而且不便管理)

  4. 使用Spring提供的@Order注解

    1. 不同的切面类当中,默认情况下通知的执行顺序是与切面类的类名字母排序是有关系的
    2. 可以在切面类上面加上@Order注解,来控制不同的切面类通知的执行顺序
  5. 切入点表达式
    描述切入点方法的一种表达式(2种)
    作用:主要用来决定项目中的哪些方法需要加入通知
    常见形式:
    execution(……):根据方法的签名来匹配
    //带 ? 的表示可以省略的部分
    execution(访问修饰符? 返回值包名.类名.?方法名(方法参数) throws异常?)
    *:单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数, 也可以通配包、类、方法名的一部分
    ..:多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
    切入点表达式的语法规则:

  6. 方法的访问修饰符可以省略

  7. 返回值可以使用 * 号代替(任意返回值类型)

  8. 包名可以使用 * 号代替,代表任意包(一层包使用一个 * )

  9. 使用 .. 配置包名,标识此包以及此包下的所有子包

  10. 类名可以使用 * 号代替,标识任意类

  11. 方法名可以使用 * 号代替,表示任意方法

  12. 可以使用 * 配置参数,一个任意类型的参数

  13. 可以使用 .. 配置参数,任意个任意类型的参数

  14. 根据业务需要,可以使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式

  15. 查询类方法都是 find 开 头,更新类方法都是update开头

@annotation(……) :根据注解匹配

  1. 编写自定义注解

  2. 在业务类要做为连接点的方法上添加自定义注解
    execution切入点表达式:
    根据我们所指定的方法的描述信息来匹配切入点方法,这种方式也是最为常用的一种方式
    如果我们要匹配的切入点方法的方法名不规则,或者有一些比较特殊的需求,通过execution切入点表达式描述比较繁琐
    annotation 切入点表达式:
    基于注解的方式来匹配切入点方法。这种方式虽然多一步操作,我们需要自定义一个注解,但是相对来比较灵活。我们需要匹配哪个方法,就在方法上加上对应的注解就可以了

  3. 连接点
    我们目标对象当中所有的方法是不是都是可以被AOP控制的方法。
    而在SpringAOP当中,连接点又特指方法的执行。 }
    //后置通知
    @After(“@annotation(com.itheima.anno.MyLog)”) publicvoidafter(){ log.info(“MyAspect6 -> after …”); } }
    在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。
    对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint类型对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint的父类型

SpingBoot原理

配置优先级:Springboot项目当中属性配置的常见方式以及配置的优先级
properties、yaml、yml三种配置文件,优先级最高的是properties,最低是yaml
还支持另外两种常见的配置方式:

  1. Java系统属性配置(格式: -Dkey=value)
  2. 命令行参数(格式:–key=value)
    优先级:命令行参数 > 系统属性参数 > properties参数 > yml参数 > yaml参数

Bean的管理

  1. 如何从IOC容器中手动的获取到bean对象
  2. bean的作用域配置
  3. 管理第三方的bean对象

标准项目结构:
my-spring-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── myapp/
│ │ │ ├── MySpringAppApplication.java # 主应用类
│ │ │ ├── config/ # 配置类
│ │ │ ├── controller/ # 控制器
│ │ │ ├── model/ # 实体类
│ │ │ ├── repository/ # 数据访问层
│ │ │ ├── service/ # 业务逻辑层
│ │ │ └── util/ # 工具类
│ │ └── resources/
│ │ ├── application.yml # 应用配置
│ │ ├── static/ # 静态资源
│ │ └── templates/ # 模板文件
│ └── test/ # 测试代码
├── pom.xml # Maven 配置
└── README.md # 项目文档

  • Application类:通常使用@SpringBootApplication注解。
  • controller(控制器):处理HTTP请求,通常使用@Controller@RestContro1ler注解。
  • Service(服务):包含业务逻辑,通常使用@Service注解。
  • Repository(仓库):负责数据访问,通常使用@Repository注解。
  • Model(模型):表示领域对象,通常是实体类。
  • Configuration(配置):提供Bean定义和应用配置,使用@Configuration注解。

剖析Springboot的底层原理

SpringBoot框架之所以使用起来更简单更快捷,是因为SpringBoot框架底层提供了两个非常重要的功能:

  1. 自动配置
1
2
3
4
5
6
7
8
// 添加依赖后,数据源会被自动配置
// 无需手动创建 DataSource、EntityManagerFactory 等
@SpringBootApplication
public class LaoyujianliFamilyMemberApplication {
public static void main(String[] args) {
SpringApplication.run(LaoyujianliFamilyMemberApplication.class, args);
}
}
  1. 起步依赖
1
2
3
4
5
<!-- 示例:Spring Boot Web 起步依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

起步依赖的原理就是Maven的依赖传递