文章目录
五、SpringBoot整合MyBatis
5.1 mapper 配置
(1)启动器
- 内含HikariCP 驱动
- 内含jdbc驱动
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
(2)启动器依赖关系
5.2 mapper映射配置:配置文件方式
- 配置文件放置在resources目录下(编译后的类路径下)
5.3 注解配置方式
(1)@Mapper注解
- 在每个
使用mybatis操作注解的接口上
加上@Mapper注解
,SpringBoot 会生成一个此接口的代理对象
并加入Spring容器中进行管理
,从而实现对数据库的持久化操作
(2)@MapperScan注解
- 在
引导类
上加@MapperScan注解
,并指明要扫描的包,SpringBoot会为所指明包下的每一个接口生成一个代理对象
,并将其加入Spring容器中进行管理
,进而实现对数据库的持久化操作
六. 自定义部分SpringMvc配置。
6.1 SpringBoot整合日期转换器
- 通过实现
WebMvcConfigurer
并添加@Configuration
注解来实现自定义部分SpringMvc配置。
- 如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:
拦截器
,格式化器
,视图控制器
、消息转换器
等等)
6.1.1 配置原理
- 拦截器、转换器也是我们经常需要使用的,在SpringBoot中该如何配置呢?
- 拦截器、转换器不是一个普通属性,而是一个类,所以就要用到java配置方式了。在SpringBoot官方文档中有这么一段说明:
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own
@Configuration
class of typeWebMvcConfigurer
but without@EnableWebMvc
. If you wish to provide custom instances ofRequestMappingHandlerMapping
,RequestMappingHandlerAdapter
, orExceptionHandlerExceptionResolver
, you can declare aWebMvcRegistrationsAdapter
instance to provide such components.If you want to take complete control of Spring MVC, you can add your own
@Configuration
annotated with@EnableWebMvc
.
- 翻译:
如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器,格式化器, 视图控制器、消息转换器 等等),你应该让一个类实现
WebMvcConfigurer
,并且添加@Configuration
注解,但是千万不要加@EnableWebMvc
注解。如果你想要自定义HandlerMapping
、HandlerAdapter
、ExceptionResolver
等组件,你可以创建一个WebMvcRegistrationsAdapter
实例 来提供以上组件。如果你想要完全自定义SpringMVC,不保留SpringBoot提供的一切特征,你可以自己定义类并且添加
@Configuration
注解和@EnableWebMvc
注解
- 总结: 通过实现
WebMvcConfigurer
并添加@Configuration
注解来实现自定义部分SpringMvc配置。
6.1.2 日期转换器整合
(1)引入日期格式转化依赖(工具类)
<!-- 日期转换-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
(2)自定义日期转换器(实现了Converter接口)
import org.springframework.core.convert.converter.Converter;
import org.apache.commons.lang3.time.DateUtils;
import java.text.ParseException;
import java.util.Date;
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
// 方式1: 使用工具类(commons.lang3)包下
String[] patterns = new String[]{
"yyyy-MM-dd","yyyy-MM-dd hh:mm:ss","yyyy/MM/dd","yyyy/MM/dd hh:mm:ss",
"MM-dd-yyyy","dd-MM-yyyy"};
Date date=null;
try {
date= DateUtils.parseDate(s, patterns);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
// 方式2: 基本方法
// SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
// Date date=null;
// try {
// date = sdf.parse(s);
// } catch (ParseException e) {
// e.printStackTrace();
// }
// return date;
}
}
(3)配置日期转换器
- 在实现
WebMvcConfigurer
并添加@Configuration
注解类中,实现自定义部分SpringMvc配置 - 通过重写
addXXXXXX
方法,在其中注册
相应的转换器
或拦截器
等等
@Configuration
public class MyConfig implements WebMvcConfigurer {
// 1.拦截器注册
/**
* @param registry :注册自定义的拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* addPathPatterns:要拦截的访问路径
* excludePathPatterns:在拦截访问路径的基础上,排除哪些路径不拦截
*/
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**").excludePathPatterns("/admin/**");
}
// 2.转换器注册
/**
* @param registry : 注册自定义的转换器
*/
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new DateConverter());
}
}
6.2 SpringBoot整合拦截器
(1)自定义拦截器
- 实现HandlerInterceptor接口,重写preHandle方法
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
书写业务逻辑
}
(2)配置拦截器
@Configuration
public class MyConfig implements WebMvcConfigurer {
// 1.拦截器注册
/**
* @param registry :注册自定义的拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* addPathPatterns:要拦截的访问路径
* excludePathPatterns:在拦截访问路径的基础上,排除哪些路径不拦截
*/
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**").excludePathPatterns("/admin/**");
}
// 2.转换器注册
/**
* @param registry : 注册自定义的转换器
*/
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new DateConverter());
}
}
七. Spring Boot 自定义日志配置(基于AOP)
- 基本思路
在service.impl层设置切面(切点+通知),记录每个方法的执行开始和结束,以及出现异常时抛出的异常信息 - 实现代码(LogConfig.java)
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
/**
* @ClassName LogConfig
* @Description TODO
* @Author 非乐
* @Date 2022/9/21 19:50
* @Version 1.0
**/
@Configuration
@Aspect
public class LogConfig {
// 声明日志
private final static Logger LOG=LoggerFactory.getLogger(LogConfig.class);
// 定义切点
@Pointcut("execution(* *.*.service.impl.*.*(..))")
public void put(){}
@Around("put()")
public Object logMessage(ProceedingJoinPoint proceedingJoinPoint) {
// 获取方法信息
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
// 打印日志
LOG.debug("==========开始执行方法:{}"+signature.getMethod().getName()+"====="+new Date() +"=====");
Object proceed = null;
try {
proceed = proceedingJoinPoint.proceed();
LOG.debug("方法执行成功:{}"+signature.getMethod().getName());
} catch (Throwable throwable) {
LOG.error("方法出现异常:{}"+signature.getMethod().getName());
LOG.error("异常信息:"+throwable.getMessage().toString());
throwable.printStackTrace();
}finally {
LOG.debug("==========方法执行结束:{}"+signature.getMethod().getName()+"====="+new Date() +"=====");
}
return proceed;
}
}
- 配置文件
- 虽然定义的切点在service.impl包下,但实质上的日志打印是在所定义的日志文件下(LOG打印),所以配置文件的日志打印要定义在日志文件所在的包下
logging:
level:
com:
edu:
config: debug
八、Spring Boot 整合JPA
8.1 JPA 简介
(1)概念: JPA 是一个全自动化 ORM 持久层框架
,具有以下特点:
- ORM映射元数据
JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中; - API
用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。 - 查询语言
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据
,避免程序的SQL语句紧密耦合。一般只对单表进行操作
(2)JPA 注解
- 由于是
面向对象
的,所以在实体上添加注解
,标记、表示、实现与数据库的映射 - 注解
- @Entity: 表示此实体使用JPA实体映射
- @Table: 表明要映射到数据库中哪一张表(name=“名”)
- @Id: 表明此属性是主键
- @GeneratedValue: 表明主键的策略(是否是自增长)
- @Column: 当实体属性名与数据库字段名称不相同时,使用此注解可以实现二者对应
- @Transient: 表明此字段不加入数据库中(不对数据库表字段进行映射)
8.2 Spring Boot 整合JPA
- JPA 操作数据库是通过自身框架实现的,底层依靠
hibernate
实现 - JPA底层封装有面向对象查询的SQL语句,但也提供了注解支持原生SQL语句的查询
(1)引入JPA启动器
<!-- jpa依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
(2)JPA 配置
(3)JPA 操作接口
- 必须继承JpaRepository<映射实体,映射实体主键类型>接口
public interface PermissionRepository extends JpaRepository<Permission,Integer>{
自定义相关操作
}
当继承了JpaRepository接口后,Spring Boot 会为其继承接口生成一个代理类,并将其加入Spring容器中进行管理
- JPA接口默认提供了基本的增删改查方法API,可以直接调用
- JPA 接口提供了以
findBy...
开始的单体字段查询API
// 支持以 findBy... 单条件查询
Student findStudentByStudentName(String name);
// 支持以 findBy... 的 多条件查询
List<Student> findStudentByAgeAndStudentNameLike(int gge,String name);
List<Student> findStudentByAgeOrStudentNameLike(int gge,String name);
- JPA 提供注解
@Query
,实现原生SQL语句的操作
// 查询权限集合
/**
*@Query:支持原生SQL语句查询
* value:SQL语句,支持传参操作,?1:表示第一个参数(与传入形参相对应)
* nativeQuery = true:表示开启原生SQL语句查询
* @param name:参数
* @return
*/
@Query(value = "select tp.permission_name\n" +
"from tb_user tu,tb_role tr,tb_permission tp,tb_user_role tur,tb_role_permission trp\n" +
"where \n" +
"\ttu.id=tur.userid and\n" +
"\ttur.roleid=tr.id and\n" +
"\ttr.id = trp.roleid and\n" +
"\ttrp.perid=tp.id and\n" +
"\ttu.user_name=?1",nativeQuery = true)
List<String> findPermissionByName(String name);
九、Spring Boot 整合邮件发送
(1)引入邮件发送启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
(2)配置邮件发送
(3)代码整合(以验证码为例)
// 注册密码加密
@Autowired
CreateMD5 createMD5;
// 持久层
@Autowired
UserRepository userRepository;
// 注册邮件发送bean(SpringBoot提供,自动装配时加载)
@Autowired
JavaMailSender javaMailSender;
// 发送源邮箱
@Value("${spring.mail.username}")
String from;
// 获取验证码
@Override
public String sendEmail(TbUser tbUser, HttpSession session) {
// 1.判断邮箱是否已经被注册
TbUser byEmail = userRepository.findByEmail(tbUser.getEmail());
if (byEmail!=null){
return "邮箱已被注册!";
}
// 2.给指定邮箱发送验证码(创建信息携带体)
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
// 设置源邮箱
simpleMailMessage.setFrom(from);
// 设置目的邮箱
simpleMailMessage.setTo(tbUser.getEmail());
// 设置发送主题
simpleMailMessage.setSubject("注册用户验证码");
// 设置发送内容(验证码)
StringBuffer stringBuffer = new StringBuffer();
for (int i=0;i<4;i++){
int i1 = new Random().nextInt(10);
stringBuffer.append(i1);
}
simpleMailMessage.setText(stringBuffer.toString());
// 3.发送验证码
javaMailSender.send(simpleMailMessage);
// 4.将验证码保存在sessin中,供注册验证使用
session.setAttribute("code",stringBuffer.toString());
session.setAttribute("email",tbUser.getEmail());
return "发送成功";
}