一、数据校验
1、引入jar包支持
<!--数据校验 针对控制层参数进行校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
常用注解
-
@NotNull:用于检查被注解的元素值是否为null。适用于字符串、集合、Map等任何对象类型,但不适用于基本数据类型(如int、long等)。
-
@NotBlank:用于检查被注解的字符串元素是否不为null且去除两端空白字符后长度大于0。只适用于字符串类型。
-
@NotEmpty:用于检查被注解的元素不为null且不为空。适用于字符串、集合、Map等。如果是字符串,相当于同时检查null和长度大于0。
-
@Size:用于指定字段的长度范围。可以指定最小长度(min)和最大长度(max)。
-
@Email:用于检查被注解的字符串是否为有效的电子邮件地址。
-
@Pattern:用于检查被注解的字符串是否符合指定的正则表达式。
-
@Min 和 @Max:分别用于检查被注解的数值是否大于等于最小值和小于等于最大值。
-
@DecimalMin 和 @DecimalMax:分别用于检查被注解的小数是否大于等于最小值和小于等于最大值。
-
@Range 是 Hibernate Validator 提供的一个用于数据校验的注解,它主要用于对数值类型(如
int
、long
、BigDecimal
等)的属性进行范围校验,确保属性值在指定的最小值和最大值之间。
使用方式
-
引入依赖:在Spring Boot项目中,首先需要引入
spring-boot-starter-validation
依赖。 -
在实体类中使用注解:在需要校验的实体类属性上添加相应的校验注解。
-
在Controller中使用注解:在Controller的方法参数上使用
@Valid
或@Validated
注解来触发校验。@Valid
通常用于方法参数,而@Validated
可以用于方法参数或类上。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@NotNull
@Min(value = 1)
private int id;
@NotEmpty
@Size(min = 3, max = 6)
private String name;
@Min(value = 1)
@Max(value = 100)
private int age;
@Email
private String email;
}
@RestController
@RequestMapping("/user")
@Validated //触发校验
public class UserController {
@RequestMapping("/m1")
public R m1(@NotNull Integer id,
@NotBlank @Size(min = 3) String name,
@Range(min = 1,max = 100) Integer age,
@Min(value = 0) Integer money,
@Email String email){
System.out.println(id+"---"+name+"--"+age+"---"+money);
return R.ok();
}
@RequestMapping("/m2")
public R m2(@Valid User user){
return R.ok(user);
}
}
二、统一异常处理
控制层异常处理
1、局部异常处理(使用少)
只针对当前controller方法中的异常进行处理
@ExectionHanlder
public class UserController{
@RequestMapping("/m3")
public R m3(Integer id){
System.out.println(1/0);
return R.ok(id);
}
//异常处理器
@ExceptionHandler(Exception.class)
public R exception(Exception e){
e.printStackTrace();
return R.fail("服务器繁忙,稍后访问!");
}
}
2、全局异常处理(使用多)
可以对所有controller方法中的异常进行处理(也可以限制处理部分包,部分类或者特定的异常)
@ExecptionHanlder
@ControllerAdvice @RestControllerAdvice
package com.hl.springboot3.web;
import com.hl.springboot3.pojo.R;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/*
@ControllerAdvice
@ResponseBody
*/
/*
全局异常处理:可以限制特定的包、特定的类、使用了特定注解的类,
还可以限制只处理特定的异常
*/
@RestControllerAdvice(annotations = RestController.class,
basePackages = "com.hl.springboot3.web",
basePackageClasses = {UserController.class})
//@RestControllerAdvice
public class GlobalExceptionHandler {
//异常处理器
@ExceptionHandler(Exception.class)
public R exception(Exception e){
e.printStackTrace();
return R.fail("服务器繁忙,稍后访问!");
}
}
三、定时器
在Spring Boot中,定时器是一种用于在特定时间点或按照预定时间间隔自动执行任务的机制。
周报表、月报表、年报表
1、在启动类开启定时
@SpringBootApplication
//开启定时
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2、创建定时任务实现类
/**
* 定时任务类1
*/
//要声明为bean,没有声明启动类启动无法实现定时效果
@Component
public class SchedulerTask {
//表示每隔6秒打印一次
@Scheduled(cron = "*/6 * * * * ?")
public void proces(){
System.out.println("this is a scheduler task running");
}
}
/**
* 定时任务类2
*/
@Component
public class Scheduler2Task {
//表示每隔6秒打印一次
@Scheduled(fixedRate = 6000)
public void reportCurrentTime(){
System.out.println("现在时间:"+new Date());
}
}
@Component
public class MyScheduler {
//@Scheduled(cron = "*/6 * * * * *")
@Scheduled(initialDelay = 5000, fixedDelay = 10000)
public void print(){
System.out.println("MyScheduler...."+new Date());
}
}
3、启动类启动即可
参数说明
@Scheduled
参数可以接受两种定时的设置,一种是我们常用的cron="*/6 * * * * ?"
,一种是 fixedRate = 6000
,两种都表示每隔六秒打印一下内容。
fixedRate 说明
-
@Scheduled(fixedRate = 6000) :上一次开始执行时间点之后6秒再执行
-
@Scheduled(fixedDelay = 6000) :上一次执行完毕时间点之后6秒再执行
-
@Scheduled(initialDelay=1000, fixedRate=6000) :第一次延迟1秒后执行,之后按fixedRate的规则每6秒执行一次
四、springboot日志
日志级别
info 重要信息
warn 警告信息
error 错误信息
trace < debug< info < warn < error
默认级别为info,只有 >=info 级别的日志,才能输出。
输出日志
@Slf4j // --- lombok
@RestController
public class LoggingController {
@RequestMapping("/test2")
public R test1() {
log.error("我是error");
log.warn("我是warning");
log.info("我是info");
log.debug("我是degu");
log.trace("我是trace");
return R.ok("日志测试");
}
}
调整日志级别
logging:
level:
# root: trace #最低跟踪级别
root: info # 统一定义日志级别 全局
com.hl.springboot3.web: trace #局部日志级别
日志框架关系
使用logback日志
logback.xml文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
<!-- 定义日志的根目录 -->
<property name="LOG_HOME" value="F:/upload/log" />
<!-- 定义日志文件名称 -->
<property name="appName" value="springboot"></property>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!--
日志输出格式:
%d表示日期时间,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息,
%n是换行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</layout>
</appender>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定日志文件的名称 -->
<file>${LOG_HOME}/${appName}.log</file>
<!--
当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
%i:当文件大小超过maxFileSize时,按照i进行文件滚动
-->
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
那些为了归档而创建的目录也会被删除。
-->
<MaxHistory>365</MaxHistory>
<!--
当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 日志输出格式: -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
</layout>
</appender>
<!--
logger主要用于存放日志对象,也可以定义日志类型、级别
name:表示匹配的logger类型前缀,也就是包的前半部分
level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
false:表示只用当前logger的appender-ref,true:
表示当前logger的appender-ref和rootLogger的appender-ref都有效
-->
<!--******************* name需要修改为当前项目的包名 *********************-->
<logger name="com.hl.springboot3.web" level="debug" />
<!-- Spring framework logger -->
<logger name="org.springframework" level="debug" additivity="false"></logger>
<!--
root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。
-->
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="appLogAppender" />
</root>
</configuration>
五、swagger
swagger 文档简略
apifox 文档详细
1、引入jar包
<!-- swagger包 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
2、配置 2.6 ,2.7需要配置
如果你使用的是 Springboot 2.6 / 2.7 版本,需要配置,否则报错,如果是Springboot2.5.8则省略
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
3、编写配置
在项目中新建 SwaggerConfig配置类:
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30)
.groupName("后端API分组")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
/**
* API 页面展示信息
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("测试文档")
.description("xxxx软件接口文档")
.contact(new Contact("admin","http://www.baidu.com", "*"))
.version("1.0.0")
.build();
}
}
4、浏览器访问
http://localhost:8080/swagger-ui/index.html
4、Swagger3注解
@Api:用在请求的类上,表示对类的说明
-
tags="说明该类的作用,可以在UI界面上看到的注解";
-
value="该参数没什么意义,在UI界面上也看到,所以不需要配置";
@ApiOperation:用在请求的方法上,说明方法的用途、作用
-
value="说明方法的用途、作用";
-
notes="方法的备注说明";
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
-
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
-
name:参数名
-
value:参数的汉字说明、解释
-
required:参数是否必须传
-
paramType:参数放在哪个地方
-
header --> 请求参数的获取:@RequestHeader
-
query --> 请求参数的获取:@RequestParam
-
path(用于restful接口)--> 请求参数的获取:@PathVariable
-
body(不常用)
-
form(不常用)
-
-
dataType:参数类型,默认String,其它值dataType="Integer"
-
defaultValue:参数的默认值
@ApiResponses:用在请求的方法上,表示一组响应
-
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
-
code:数字,例如400
-
message:信息,例如"请求参数没填好"
-
response:抛出异常的类
-
@ApiModel:用于响应类上(实体类),表示一个返回响应数据的信息
-
这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用
-
@ApiImplicitParam注解进行描述的时候
-
@ApiModelProperty:用在属性上,描述响应类的属性
示例代码:
第一种方式:多参数方式
@RestController
@RequestMapping("emp")
@Api(tags = "员工管理接口")
public class EmployeeController {
@ApiOperation(value = "添加员工信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "姓名", required = true, paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "age", value = "年龄", required = true, paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "tel", value = "电话", required = true, paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "email", value = "邮箱", required = true, paramType = "query", dataType = "String")
})
@ApiResponses({
@ApiResponse(code = 200, message = "成功"),
@ApiResponse(code = 400, message = "参数错误"),
@ApiResponse(code = 500, message = "服务器内部错误")
})
@RequestMapping("add")
public R test1(String name,int age,String tel, String email) {
System.out.println(name+age+tel+email);
return R.ok("添加成功");
}
}
第二种方式:实体类方式
@Data
@ApiModel
public class Employee {
@ApiModelProperty(value = "编号",required = true)
private int id;
@ApiModelProperty(value = "用户名",required = true)
private String name;
@ApiModelProperty(value = "年龄",required = true)
private int age;
@ApiModelProperty(value = "电话",required = true)
private String tel;
@ApiModelProperty(value = "邮箱",required = true)
private String email;
}
@RequestMapping("add2")
public R test1(Employee emp) {
System.out.println(emp.toString());
return R.ok("添加成功");
}
六、springboot自动装配原理
@SpringbootApplication
底层包含原注解和其他注解
@Target() 目标位置
ElementType.
TYPE, FIELD, METHOD, PARAMETER,CONSTRUCTOR,
@Retention(RetentionPolicy.RUNTIME)
SOURCE,
CLASS,
RUNTIME
@SpringBootConfiguration
@Configuration 创建ioc容器
@EnableAutoConfiguration 自动配置 自动装配核心注解
meta-inf/spring.factoies
找到自动配置的类
@ComponentScan
默认扫描的包 com.hl.springboot3
加载自动配置的类,看是否满足条件,满足条件了,就创建对象,不满足不创建
@AutoConfiguration(
after = {DataSourceAutoConfiguration.class}
)
@ConditionalOnClass({DataSource.class, JdbcTemplate.class}) 当某个类存在时
@ConditionalOnMissingClass 当某个类不存在
@ConditionalOnBean() 当某个对象存在时
@ConditionalOnMissingBean 当某个丢下不存在
@ConditionalOnSingleCandidate(DataSource.class) 存在某个唯一对象时
@EnableConfigurationProperties({JdbcProperties.class})
@Import({DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class})
总结
1、如何实现参数校验功能(掌握)
spring-boot-starter-validation
相关的注解有哪些?
针对方法参数,单独校验如何实现?
针对接收的bean对象,如何整体校验
2、springmvc异常处理的两种方式?(掌握)
局部异常处理
全局异常处理
3、log4j、logback、lombok常见的日志框架对应的日志级别有哪些?(掌握)
如何修改日志级别
logging.level.root=debug
logging.level.包名=debug
4、定时器 相关的注解,如何定时功能(掌握)
5、swagger 接口工具 了解
6、springboot自动装配原理
@EnableAutoConfiguration
条件装配注解
@ConditionalOnProperty
@ConditionalOnMissingClass
@ConditionalOnClass
@ConditionalOnBean
@ConditionalOnMissingBean
@AutoConfiguration(
after = {JdbcTemplateAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class}
)