一.使用Mybatis实现数据库编程
<!-- Mybatis整合Spring Boot的依赖项 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- MySQL的依赖项 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
# 连接数据库的配置参数
spring.datasource.url=jdbc:mysql://localhost:3306/mall_pms?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
- 在配置类中使用
@MapperScan
指定接口文件所在的根包- 一次性配置
- 在配置文件中通过
mybatis.mapper-locations
属性来指定XML文件所在的位置- 一次性配置
- 创建实体类
- 创建接口,并声明抽象方法
- 添加XML文件,并在此文件中配置抽象方法映射的SQL语句
- 创建测试类,编写并执行测试方法
- 非必要,但强烈推荐
package cn.tedu.csmall.product.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@MapperScan("cn.tedu.csmall.product.mapper")
@Configuration
public class MybatisConfiguration {
}
在application.properties
中添加配置:
# Mybatis相关配置
mybatis.mapper-locations=classpath:mapper/*.xml
2. Lombok
在任何POJO类上,可以添加@Data
注解,则此框架(Lombok)会自动在编译期生成:
- 各属性对应的Setters & Getters
- 基于各属性的
hashCode()
与equals()
- 基于各属性的
toString()
另外,所有POJO类都应该实现Serializable
接口!
<!-- Lombok的依赖项,主要用于简化POJO类的编写 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
3.关于Lombok框架
Lombok框架的主要作用是通过注解可以在编译期生成某些代码,例如Setters & Getters、hashCode()
与equals()
、toString()
方法等,可以简化开发。
由于源代码(.java
)文件中并没有相关代码,所以,默认情况下,开发工具无法智能提示,直接写出相关代码也会提示错误,则需要在开发工具中安装Lombok插件,安装方式:打开IntelliJ IDEA的设置,在Plugins一栏,在Marketplace
中找到Lombok
并安装即可。
Lombok的常用注解有:
@Data
:添加在类上,可在编译期生成全部属性对应的Setters & Getters、hashCode()
与equals()
、toString()
,使用此注解时,必须保证当前类的父类存在无参数构造方法@Setter
:可以添加在属性上,将仅作用于当前属性,也可以添加在类上,将作用于类中所有属性,用于生成对应的Setter方法@Getter
:同上,用于生成对应的Getter方法@EqualsAndHashCode
:添加在类上,用于生成规范的equals()
和hashCode()
,关于equals()
方法,如果2个对象的所有属性的值完全相同,则返回true
,否则返回false
,关于hashCode()
也是如此,如果2个对象的所有属性的值完全相同,则生成的HashCode值相同,否则,不应该相同@ToString
:添加在类上,用于生成全属性对应的toString()
方法@Slf4j
:添加在类上,???
4.关于Slf4j日志
在Spring Boot项目中,基础依赖项(spring-boot-starter
)中已经包含了日志的相关依赖项。
在添加了Lombok
依赖项后,可以在类上添加@Slf4j
注解,则Lombok框架会在编译期生成名为log
的变量,可调用此变量的方法来输出日志。
日志是有显示级别的,根据日志内容的重要程度,从不重要到重要,依次为:
trace
:跟踪信息,可能包含不一定关注,但是包含了程序执行流程的信息debug
:调试信息,可能包含一些敏感内容,比如关键数据的值info
:一般信息warn
:警告信息error
:错误信息
使用Slf4j时,可以使用log
变量调用以上5个级别对应的方法,来输出不同级别的日志!
在Spring Boot项目中,默认的日志显示级别为【info】,将只会显示此级别及更重要级别的日志!可以在application.properties
中配置logging.level.根包=日志显示级别
来设置当前显示级别,例如:
# 日志的显示级别
logging.level.cn.tedu.csmall=error
在开发实践中,应该使用trace
或debug
级别的日志来输出与流程相关的、涉及敏感数据的日志,使用info
输出一般的、被显示在控制台也无所谓的信息,使用warn
和error
输出更加重要的、需要关注的日志。
5.
关于<resultMap>
与<sql>
标签
Mybatis框架在处理查询时,会自动的将列名与属性名完全一致的数据进行封装(例如查询结果集中列名为name
的值会自动封装到返回值对象的name
属性中),如果名称不一致,则不会自动封装!
通常,建议通过<resultMap>
标签来配置列名与属性名的对应关系,以指导Mybatis如何处理结果集。
另外,还建议使用<sql>
标签来封装查询的字段列表,并通过<include>
标签来引用封装的查询字段列表,
6.Spring MVC框架的统一处理异常的机制
Spring MVC框架提供了统一处理异常的机制,对于每种类型的异常,只需要编写1段相关的处理代码即可!
当使用这种机制时,在控制器类的各处理请求的方法中,将不再使用try...catch
语句来包裹可能抛出异常的方法并处理,则控制器类中各处理请求的方法都是将是抛出异常的(虽然你不必在代码中显示的使用throws
声明抛出),这些异常会被Spring MVC框架捕获并尝试调用统一处理异常的方法!
可以编写统一处理异常的方法,对控制器类中处理请求的方法抛出的异常进行处理,关于统一处理异常的方法:
- 注解:必须添加
@ExceptionHandler
注解 - 访问权限:应该使用
public
- 返回值类型:参考处理请求的方法
- 方法名称:自定义
- 参数列表:必须有1个异常类型的参数,表示Spring MVC框架调用处理请求的方法时捕获到的异常,并且,可以按需添加
HttpServletRequest
、HttpServletResponse
等少量特定类型的参数,不可以随意添加其它参数
如果将统一处理异常的方法定义在某个控制器类中,将只能作用于当前控制器类中各处理请求的方法!
通常,会将统一异常的代码定义在专门的类中,并在此类上添加@RestControllerAdvice
注解,添加了此注解的类中的特定方法将作用于整个项目任何处理请求的方法的过程!
7. 关于Knife4j框架
Knife4j是一款基于Swagger 2的在线API文档框架。
使用Knife4j需要:
-
添加依赖,注意:本次使用的Knife4j的版本必须基于Spring Boot的版本在2.6之前(2.6及更高版本不可用)
<!-- Knife4j Spring Boot:在线API --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.9</version> </dependency>
-
需要在主配置文件(
application.properties
或application.yml
)中添加配置:knife4j.enable=true
-
在使用Knife4j时,应该通过相关注解,将API文档配置得更加易于阅读和使用,可以:
@Api
:添加在控制器类上,通过此注解的tags
属性,可以指定模块名称,并且,可以在模块名称前自行添加数字序号,以实现排序效果,框架会根据各控制器类上@Api
注解的``tags`属性值进行升序排列@ApiOperation
:添加在处理请求的方法上,通过此注解的value
属性,可以指定业务名称@ApiOperationSupport
:添加在处理请求的方法上,通过此注解的order
属性(数值型),可以指定排序序号,框架会根据此属性值升序排列
8. 使用Validation框架检查请求参数的基本格式
添加依赖
在pom.xml
中添加spring-boot-starter-validation
依赖项:
<!-- Spring Boot Validation的依赖项,用于检查请求参数的基本格式 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
检查封装的请求参数
在控制器中,对于封装类型的请求参数,应该先在请求参数之前添加@Valid
或@Validated
注解,表示将需要对此请求参数的格式进行检查,例如:
@ApiOperation("添加相册")
@ApiOperationSupport(order = 100)
@PostMapping("/add-new")
// ↓↓↓↓↓↓ 以下是新添加的注解
public JsonResult addNew(@Valid AlbumAddNewDTO albumAddNewDTO) {
log.debug("开始处理【添加相册】的请求,参数:{}", albumAddNewDTO);
albumService.addNew(albumAddNewDTO);
log.debug("添加相册成功!");
return JsonResult.ok();
}
然后,在此封装类型中,在需要检查的属性上,添加检查注解,例如可以添加@NotNull
注解,此注解表示“不允许为null
值”,例如:
@Data
public class AlbumAddNewDTO implements Serializable {
/**
* 相册名称
*/
@ApiModelProperty(value = "相册名称", required = true)
@NotNull // 新添加的注解
private String name;
// 暂不关心其它代码
}
重启项目,如果客户端提交请求时,未提交name
请求参数,就会响应400
错误,并且,在服务器端的控制台会提示错误:
2022-11-01 11:27:45.398 WARN 15104 --- [nio-9080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.valida
9.基于Spring JDBC的事务管理
在编程式事务管理过程中,需要先开启事务(BEGIN),然后执行数据操作,当全部完成,需要提交事务(COMMIT),如果失败,则回滚事务(ROLLBACK)。
在基于Spring JDBC的项目中,只需要使用声明式事务即可,也就是只需要在方法上添加@Transactional
注解即可。
Spring JDBC实现事务管理大致是:
开启事务:Begin
try {
执行事务方法,即数据访问操作
提交事务:Commit
} catch (RuntimeException e) {
回滚事务:Rollback
}
所以,Spring JDBC在事务管理中,默认将基于RuntimeException
进行回滚,可以通过@Transactional
的rollbackFor
或rollbackForClassName
属性来修改,例如:
@Transactional(rollbackFor = {NullPointerException.class, IndexOutOfBoundsException.class})
@Transactional(rollbackForClassName = {"java.lang.NullPointerException", "java.lang.IndexOutOfBoundsException"})
还可以通过noRollbackFor
或noRollbackForClassName
属性来配置对于哪些异常不回滚。
其实,@Transactional
注解可以添加在:
- 接口上
- 将作用于实现了此接口的类中的所有业务方法
- 接口中的业务方法上
- 将作用于实现了此接口的类中的重写的当前业务方法
- 实现类上
- 将作用于当前类中所有业务方法
- 实现类中的业务方法上
- 将仅作用于添加了注解的业务方法
提示:如果在业务类和业务方法上都添加了@Transactional
,却配置了相同名称但不同值的注解参数,将以业务方法上的配置为准。
在应用此注解时,由于这是一种声明式事务管理,推荐添加在接口上,或接口中的业务方法上。
理论上,如果将@Transactional
添加在接口上,可能有点浪费,毕竟并不是每个业务方法都需要是事务性的。
注意:由于Spring JDBC在处理事务管理时,使用了基于接口的代理模式,所以,业务方法的内部调用时(同一个业务类对象的A方法调用了B方法),被调用方法相当于是“无事务的”,另外,如果某方法不是接口中声明的业务方法,只是实现类自行添加的方法,无论将@Transactional
添加在哪里,都是无效的!
10.关于Spring Security框架
Spring Security框架主要解决了认证与授权相关的问题。
添加Spring Boot Security依赖
在csmall-passport
项目中添加依赖项:
<!-- Spring Boot Security的依赖项,用于处理认证与授权 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
当添加了以上依赖项后,当前项目会:
- 此依赖项中包含
BCryptPasswordEncoder
类,可以用于处理密码加密 - 所有请求都是必须通过认证的,在没有通过认证之前,任何请求都会被重定向到Spring Security内置的登录页面
- 可以使用
user
作为用户名,使用启动项目时随机生成的UUID密码来登录 - 当登录成功后,会自动重定向到此前尝试访问的页面
- 当登录成功后,所有GET的异步请求允许访问,但POST的异步请求不允许访问(403错误)
- 可以使用
当添加依赖后,在浏览器中尝试访问时还可能出现以下错误:
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the header value "Idea-c968a669=03021799-4633-4321-9d0d-11b7ee08f588; username=é»æ±å; JSESSIONID=120F9329E0CE7AF9E052A302EFE494F2" is not allowed.
此错误是浏览器的问题导致的,更换浏览器即可。