1、SpringBoot单元测试【掌握】
2、SpringBoot 整合 MybatisPlus【重点】
3、SpringBoot添加分页插件【掌握】
4、SpringBoot定义拦截器【掌握】
5、SpringBoot使用类型转换器【掌握】
6、文件上传【掌握】
7、SpringBoot异常处理【掌握】
8、SpringBoot定时任务【掌握】
9、SpringBoot热部署【掌握】
10、服务端表单数据校验【掌握】
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
提示:测试类必须和启动类在同一个包或子包下
package demo.test;
import com.baomidou.mybatisplus.core.metadata.IPage;
import demo.Demo;
import demo.entity.PageInfo;
import demo.entity.User;
import demo.mappers.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Demo.class}) //启动类
public class JTest {
@Autowired
private UserMapper userMapper;
@Test
public void test1(){
System.out.println("我是一个测试方法");
}
}
使用单元测试向控制台输出1-100之间整数相加的和
- 在启动类的子包下创建单元测试类JTest
- 在类上添加单元测试的注解
- 创建单元测试方法输出0-100整数相加的和
在项目中使用单元测试的关键要点是什么?
1、在pom.xml中添加单元测试的依赖
2、在启动类的子包中添加单元测试类,并使用@RunWith注解标注单元测试类,@SpringBootTest注解标注启动类
3、创建测试方法,并使用@Test注解标注
4、注意:单元测试类的类名不可以叫Test
mybatis-spring-boot-starter是 MyBatis 帮助我们快速集成 SpringBoot 提供的一个组件包,使用这个组件可以做到以下几点:
使用了该Starter之后,只需要定义一个DataSource即可(application.properties或application.yml中可配置),它会自动创建使用该DataSource的SqlSessionFactoryBean以及SqlSessionTemplate。会自动扫描你的Mappers,连接到SqlSessionTemplate,并注册到Spring上下文中。
从 Spring Boot 2.0 开始,spring-boot-starter-jdbc内部提供了默认的 HikariCP 数据库连接池,(也是传说中最快的数据库连接池)。spring-boot-starter-jdbc主要提供了三个功能,第一个就是对数据源的装配,第二个就是提供一个JdbcTemplate简化使用,第三个就是事务。
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.7.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.22version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.2version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.4.0version>
<scope>compilescope>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.2version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
dependencies>
创建springboot的配置文件application.properties
#连接数据库的四大参数
spring:
datasource:
url: jdbc:mysql://10.211.55.2:3306/t_mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: Aa123123.
#以下四个参数可省略,Springboot自动推断
driverClassName: com.mysql.cj.jdbc.Driver
hikari.idle-timeout: 60000
hikari.maximum-pool-size: 30
hikari.minimum-idle: 10
如果你更喜欢Druid连接池,也可以使⽤Druid官⽅提供的启动器,那麼就不需要spring-boot-starter-jdbc启动器了。
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/woniu_db?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.max-wait=60000
#初始化连接数
spring.datasource.initial-size=1 #最⼩空闲连接
spring.datasource.min-idle=1 #最⼤活动连接
spring.datasource.max-active=20
#获取连接时测试是否可⽤
spring.datasource.test-on-borrow=true
#监控⻚⾯启动
spring.datasource.stat-view-servlet.allow=true
package demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("demo.mappers") //扫描DAO
public class Demo {
public static void main(String[] args) {
SpringApplication.run(Demo.class, args);
}
}
package demo.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("t_user")
public class User {
@TableId
private int id;
private String userName;
private String passwd;
}
package demo.mappers;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import demo.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
}
package demo.test;
import demo.Demo;
import demo.entity.User;
import demo.mappers.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Demo.class}) //启动类
public class TestMyBatis {
@Autowired
private UserMapper userMapper;
@Test
public void test1(){
List<User> users = userMapper.selectList(null);
for(User user : users){
System.out.println(user);
}
}
}
使用MyBatisPlus完成用户管理的增删改查功能
- 创建SpringBoot项目
- 在pom中添加MyBatisPlus相关依赖
- 在application.yml中配置数据源
- 在启动类中扫描dao
- 创建User实体映射数据库t_user表
- 创建UserMapper访问数据库
- 创建测试类TestUser,提供4个测试方法,分别是:addUser、deleteUser、updateUser、loginUser
在SpringBoot中使用MyBatisPlus的关键步骤是什么?
1、创建SpringBoot项目
2、在pom中添加MyBatisPlus相关依赖
3、在application.yml中配置数据源
4、在启动类通过@MapperScan注解扫描DAO
5、添加业务代码:实体层、数据库访问层、单元测试
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelper-spring-boot-starterartifactId>
<version>1.3.1version>
dependency>
package demo.mappers;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import demo.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
/**
* 查询所有并分页
* @param pageNo
* @param pageSize
* @return
*/
default IPage<User> listUserPage(Integer pageNo, Integer pageSize){
//实例化mybatis plus的分页对象
Page<User> page = new Page<>(pageNo, pageSize);//参数一是当前页,参数二是每页个数
//获得数据 参数一:分页参数 参数二:查询条件,没有查询条件则为null
IPage<User> mapIPage=this.selectPage(page,null);
return mapIPage;
}
}
package demo.test;
import com.baomidou.mybatisplus.core.metadata.IPage;
import demo.Demo;
import demo.entity.PageInfo;
import demo.entity.User;
import demo.mappers.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Demo.class}) //启动类
public class TestPage {
@Autowired
private UserMapper userMapper;
@Test
public void test1(){
//获得分页数据
IPage<User> userPage = userMapper.listUserPage(1,3);
//将数据保存到分页数据对象中
PageInfo<User> pageInfo = new PageInfo<User>(userPage);
System.out.println(pageInfo);
}
}
结合BootStrap+VUE实现用户列表的展示,要求带分页器
后台开发
- 创建SpringBoot项目,并添加web依赖
- 添加并配置数据源
- 在pom中添加MyBatisPlus依赖
- 在启动类通过@MapperScan注解扫描DAO
- 在pom中添加PageHelper依赖
- 编写业务代码:Controller层、Service层、DAO层、domain层
前台开发
- 创建一个html页面,并导入VUE和BootStrap的相关css、js库
- 使用BootStrap的表格样式和分页导航样式实现页面的绘制
- 使用axios请求后台Controller响应带有分页的用户列表
- 通过vue的双向绑定,将用户列表数据通过v-for指令渲染到html表格
在MyBatisPlus中使用分页插件的关键步骤是什么?
1、创建SpringBoot项目,并添加web依赖
2、添加并配置数据源
3、在pom中添加MyBatisPlus依赖
4、在启动类通过@MapperScan注解扫描DAO
5、在pom中添加PageHelper依赖
6、在Mapper的分页查询方法中创建Page对象设置起始页和每页显示的条数
7、在Mapper的分页查询方法中调用selectPage方法实现分页查询
前端调用后端接口,后端需要将输入参数解析为Java中的数据类型,但是Spring仅支持对于基本类型的转换,对于Spring转Date,或者Long转Date这些,是需要提供自定义类型转换器来进行转换的。
package demo.convert;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class MyDateConverter implements Converter<String, Date> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date convert(String source) {
try {
return sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
@RequestMapping("/tt2")
public Date test2(Date birth){
System.out.println(birth);
return birth;
}
将以上案例练习一遍
在SpringBoot中使用类型转换器的关键步骤是什么?
1、创建类型转换器类MyDateConverter
2、实现Convert接口
3、实现convert方法,添加转换的功能
在项目中,我们不可能能够预知并catch所有的异常,为了避免非期望异常抛给客户端,Spring为我们提供了统一异常处理的机制@RestControllerAdvice,能够让我们在逻辑抛出异常时,能够将异常友好化或者指定返回的数据结构给前台。
添加全局异常处理类ExceptionHandleAdvice
package demo.exception;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class ExceptionHandleAdvice {
@ExceptionHandler(Exception.class)
public String exceptionHandle(Exception e){
System.out.println(e); //处理异常,比如保存日志
return "系统异常!";
}
}
在controller中模拟500错误
package demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Test1 {
@RequestMapping("/t1")
public String t1(){
System.out.println(1/0); //模拟错误
return "hello";
}
}
按照以上案例再次操练
实现全局异常处理的关键步骤是什么?
1、添加全局异常处理类,并使用@RestControllerAdvice注解标注
2、添加处理异常的方法,并使用@ExceptionHandler(Exception.class)注解标注
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
package demo.schedule;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class SaticScheduleTask {
/**
*定时任务方法
* @Scheduled:设置定时任务 cron 属性:cron 表达式。定时任务触发是时间的一个字符串表达形式
*/
//@Scheduled(cron = "0/2 * * * * ?")
@Scheduled(fixedRate=2000) //每2秒钟执行一次
public void scheduledMethod() {
System.out.println("定时器被触发" + new Date());
}
}
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling //开启定时任务
public class Demo {
public static void main(String[] args) {
SpringApplication.run(Demo.class, args);
}
}
Cron 表达式是一个字符串,分为 6 或 7 个域,每一个域代表一个含义;
Cron 从左到右(用空格隔开): 秒 分 小时 月份中的日期 月份 星期中的日期 年份
Cron 有如下两种语法格式:
序号 | 说明 | 取值 | 表达式 |
---|---|---|---|
1 | 秒 | 0-59 | -*/ |
2 | 分钟 | 0-59 | -*/ |
3 | 小时 | 0-23 | -*/ |
4 | 日 | 1-31 | -*/LWC |
5 | 月 | 1-12 | -*/ |
6 | 星期 | 1-7 | -*?/LC# |
7 | 年(可选) | 1970-2099 | -*/ |
Cron 表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功,如下:
案例说明:
@Scheduled(cron = "0 0 1 1 1 ?")//每年一月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 1,6 ?") //一月和六月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 1,4,7,10 ?") //每个季度的第一个月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 * ?")//每月一号 1:00:00 执行一次
@Scheduled(cron="0 0 1 * * *") //每天凌晨 1 点执行一次
将以上案例再次操练
使用定时任务的关键步骤有哪些?
1、在pom.xml中添加依赖
2、在启动类中使用@EnableScheduling注解开启定时任务
3、创建定时任务类,通过@Scheduled注解规定任务执行的周期
作为一个Java程序员,在日常的工作中,经常需要修改代码,然后重启服务,在验证代码是否生效。如果是小项目还好,重启速度比较快,等待时间比较短。但是随着项目逐渐变大,并且被拆分成多个服务时,改动一些代码,可能需要重启多个服务才能生效。这样下来就耗费了大量的时间在等待服务重启。
这样肯定是不行的,极大的影响了我的开发效率,那么是否有方式能够实现,修改完代码之后,能够不重启项目呢?
那肯定是有的,要不然这篇文章咋来的 。
热部署(Hot Swap)
从Java1.4起,JVM引入了HotSwap,能够在Debug的时候更新类的字节码。所以使用热部署,可以实现修改代码后,无须重启服务就可以加载修改的代码,但是它只能用来更新方法体。作为神器的IDEA自然是支持这一技术的。
DevTools是Spring为开发者提供了一个名为spring-boot-devtools的模块,来使Spring Boot应用支持热部署,提高开发者的开发效率,无需手动重启Spring Boot应用。使用起来非常简单,只需要将下面的依赖引入项目里面就可以了。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
dependency>
触发重启
DevTools严格意义上其实不算热部署,而是快速重启。为什么这样说呢?DevTools的实现原理是:使用两个类加载器,一个是base classloader来加载不会被更改的类(例如,来自第三方的Jar),还有一个是restart classloader用来加载当前正在开发的类。所以当应用程序重新启动时,restart classloader将被丢弃,并创建一个新的类加载器。也就意味着应用程序重新启动通常比“冷启动”快得多,因为base classloader已经填充好了并且是可用的。
简而言之就是:通过监控类路径资源,当类路径上的文件发生更改时,自动重新启动应用程序,由于只需要重新读取被修改的类所,所以要比冷启动快。
配置自动重启
只需要进行下面两步的配置就可以实现了。
使用快捷键:Ctrl + Alt + Shift + / 调出 Registry 窗口,勾选 compiler.automake.allow.when.app.running 选项。
注意1:有的idea版本在项目中点击CTRL + ALT + SHIFT + / 无反应,那么就可以点击CTRL+SHIFT+A搜索Registry点击进去找到上面的那个key在后面勾上对勾即可
如果点击进去后,发现没有compiler.automake.allow.when.app.running,那么就需要我们去这个地方进行勾选:
spring:
devtools:
livereload:
#ture=开启热部署;false=关闭热部署
enabled: true
按照如上案例再次操练
实现热部署的关键步骤有哪些?
1、在pom.xml中添加依赖
2、在idea中开启热部署(2步)
早期的网站,用户输入一个邮箱地址,需要将邮箱地址发送到服务端,服务端进行校验,校验成功后再给前端一个响应。自从有了 JavaScript 后,校验工作可以放在前端去执行。那么为什么还需要服务端校验呢?因为前端传来的数据不可信,前端很容易获取到后端的接口,如果有人直接调用接口,就可能会出现非法数据,因此服务端也要数据校验。
总的来说:
前端校验,提高用户体验
后端校验,保证数据安全可靠
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.0.18.Finalversion>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
package demo;
import lombok.Data;
import javax.validation.constraints.*;
@Data
public class User {
@NotNull(message = "用户ID不可为null")
private int id;
@NotEmpty(message = "用户名不可以是空字符串")
private String userName;
@Min(value = 18, message = "年龄最小18岁")
@Max(value = 80, message = "年龄最大80岁")
private int age;
@Pattern(regexp = "[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "邮箱格式不正确")
private String email;
}
//import org.springframework.validation.annotation.Validated;
@RequestMapping("/t2")
public User t2(@Validated User user){
return user;
}
@AssertTrue:用于boolean字段,该字段只能为true
@AssertFalse:用于boolean字段,该字段只能为false
@CreditCardNumber:对信用卡号进行一个大致的验证
@DecimalMax:只能小于或等于该值
@DecimalMin:只能大于或等于该值
@Email:检查是否是一个有效的email地址
@Future:检查该字段的日期是否是属于将来的日期
@Length(min=,max=):检查所属的字段的长度是否在min和max之间,只能用于字符串
@Max:该字段的值只能小于或等于该值
@Min:该字段的值只能大于或等于该值
@NotNull:该字段的值不能为null
@NotBlank:不能为空,检查时会将空格忽略
@NotEmpty:不能为空,这里的空是指空字符串
@Pattern(regex=):被注释的元素必须符合指定的正则表达式
@URL(protocol=,host,port):检查是否是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件
将以上案例再次操练
通过springboot使用后台表单校验的关键步骤有哪些?
1、在pom.xml中添加依赖
2、在实体中通过注解标注校验规则
3、在controller中通过@Validated注解标注参数