springboot03

发布于:2025-05-23 ⋅ 阅读:(22) ⋅ 点赞:(0)

目录

一、数据校验

引入jar包

 常用注解

使用方式

二、统一异常处理

2.1局部异常处理

@ExectionHandler

2.2全局异常处理(多)

@ExectionHanlder

@ControllerAdvice 

@RestControllerAdvice

三、定时器

3.1在启动类开启定时

3.2创建定时任务实现类

3.3启动类启动

参数说明

四、springboot日志

4.1日志级别

4.2输出日志

4.3调整日志级别

4.4日志框架关系

4.5使用logback日志

五、swagger

5.1引入jar包

5.2配置 2.6 ,2.7需要配置

5.3编写配置(固定的)

5.4Swagger3注解

六、springboot自动装配原理

@SpringbootApplication

面试

1、如何实现参数校验功能(掌握)

2、springmvc异常处理的两种方式?(掌握)

3、log4j、logback、lombok常见的日志框架对应的日志级别有哪些?(掌握)

4、定时器  相关的注解,如何定时功能(掌握)

5、swagger 接口工具  了解

6、springboot自动装配原理(看面试题,按照面试题背 )


一、数据校验

引入jar包

<!--数据校验  针对控制层参数进行校验 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

 常用注解

  1. @NotNull:用于检查被注解的元素值是否为null。适用于字符串、集合、Map等任何对象类型,但不适用于基本数据类型(如int、long等)。

  2. @NotBlank:用于检查被注解的字符串元素是否不为null且去除两端空白字符后长度大于0。只适用于字符串类型。

  3. @NotEmpty:用于检查被注解的元素不为null且不为空。适用于字符串、集合、Map等。如果是字符串,相当于同时检查null和长度大于0。

  4. @Size:用于指定字段的长度范围。可以指定最小长度(min)和最大长度(max)。

  5. @Email:用于检查被注解的字符串是否为有效的电子邮件地址。

  6. @Pattern:用于检查被注解的字符串是否符合指定的正则表达式。

  7. @Min@Max:分别用于检查被注解的数值是否大于等于最小值和小于等于最大值。

  8. @DecimalMin@DecimalMax:分别用于检查被注解的小数是否大于等于最小值和小于等于最大值。

  9. @Range 是 Hibernate Validator 提供的一个用于数据校验的注解,它主要用于对数值类型(如 intlongBigDecimal 等)的属性进行范围校验,确保属性值在指定的最小值和最大值之间。

使用方式

1. 引入依赖:在Spring Boot项目中,首先需要引入`spring-boot-starter-validation`依赖。
2. 在实体类中使用注解:在需要校验的实体类属性上添加相应的校验注解。
3. 在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);
    }
}

二、统一异常处理

控制层处理异常

2.1局部异常处理

只针对当前controller方法中的异常进行处理

@ExectionHandler

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.2全局异常处理(多)

可以对所有controller方法中的异常进行处理(也可以限制处理部分包,部分类或者特定的异常)

@ExectionHanlder

@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中,定时器是一种用于在特定时间点或按照预定时间间隔自动执行任务的机制。

周报表、月报表、年报表

3.1在启动类开启定时

@SpringBootApplication
//开启定时
@EnableScheduling
public class Application {
   public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
   }
}

3.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.3启动类启动

参数说明

`@Scheduled` 参数可以接受两种定时的设置,一种是我们常用的`cron="*/6 * * * * ?"`,一种是 `fixedRate = 6000`,两种都表示每隔六秒打印一下内容。

fixedRate 说明

  •  @Scheduled(fixedRate = 6000) :上一次开始执行时间点之后6秒再执行
  •  @Scheduled(fixedDelay = 6000) :上一次执行完毕时间点之后6秒再执行
  •  @Scheduled(initialDelay=1000, fixedRate=6000) :第一次延迟1秒后执行,之后按fixedRate的规则每6秒执行一次

四、springboot日志

4.1日志级别

info   重要信息

warn  警告信息

error  错误信息

trace < debug<  info < warn < error

默认级别为info,只有  >=info 级别的日志,才能输出。

4.2输出日志

@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("日志测试");
    }
}

4.3调整日志级别

logging:
  level:
#    root: trace #最低跟踪级别
    root: info  #  统一定义日志级别 全局
    com.hl.springboot3.web: trace  #局部日志级别

4.4日志框架关系

4.5使用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   文档详细

5.1引入jar包

<!-- swagger包 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

5.2配置 2.6 ,2.7需要配置

如果你使用的是 Springboot 2.6 / 2.7 版本,需要配置,否则报错,如果是Springboot2.5.8则省略

--application.yml

spring:
    mvc:
        pathmatch:
        	matching-strategy: ant_path_matcher

5.3编写配置(固定的)

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();
    }
}

 浏览器访问地址 http://localhost:8080/swagger-ui/index.html

具体看自己端口号更改

5.4Swagger3注解
 

@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;
}
@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;
}

六、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、如何实现参数校验功能(掌握)

1)pom.xml文件添加 spring-boot-starter-validation依赖

2)相关的注解有哪些? 

  1. @NotNull:用于检查被注解的元素值是否为null。适用于字符串、集合、Map等任何对象类型,但不适用于基本数据类型(如int、long等)。

  2. @NotBlank:用于检查被注解的字符串元素是否不为null且去除两端空白字符后长度大于0。只适用于字符串类型。

  3. @NotEmpty:用于检查被注解的元素不为null且不为空。适用于字符串、集合、Map等。如果是字符串,相当于同时检查null和长度大于0。

  4. @Size:用于指定字段的长度范围。可以指定最小长度(min)和最大长度(max)。

  5. @Email:用于检查被注解的字符串是否为有效的电子邮件地址。

  6. @Pattern:用于检查被注解的字符串是否符合指定的正则表达式。

  7. @Min@Max:分别用于检查被注解的数值是否大于等于最小值和小于等于最大值。

  8. @DecimalMin@DecimalMax:分别用于检查被注解的小数是否大于等于最小值和小于等于最大值。

  9. @Range 是 Hibernate Validator 提供的一个用于数据校验的注解,它主要用于对数值类型(如 intlongBigDecimal 等)的属性进行范围校验,确保属性值在指定的最小值和最大值之间。

3)针对方法参数,单独校验如何实现?----在Controller的方法参数上使用`@Valid`或`@Validated`注解来触发校验。`@Valid`通常用于方法参数,而`@Validated`可以用于方法参数或类上。

4)针对接收的bean对象,如何整体校验---接受对象定义(在对象属性上添加相应注解,比如

 @Email
 private String email;,然后在controller上使用,例如public R m2(@Valid User user))

2、springmvc异常处理的两种方式?(掌握)

局部异常处理----@ExceptionHandler(Exception.class)

全局异常处理----可以限制特定的包、特定的类、使用了特定注解的类, 还可以限制只处理特定的异常-----@RestControllerAdvice(annotations = RestController.class,
        basePackages = "com.hl.springboot3.web",
        basePackageClasses = {UserController.class})

        @ExceptionHandler(Exception.class)

@RestControllerAdvice=@ControllerAdvice+@ResponseBody

3、log4j、logback、lombok常见的日志框架对应的日志级别有哪些?(掌握)

属于lombok注解👇

特性 / 框架 Log4j 1.x Logback Log4j 2.x
日志级别(从高到低) FATAL
ERROR
WARN
INFO
DEBUG
TRACE
OFF
ERROR
WARN
INFO
DEBUG
TRACE
ALL
OFF
FATAL
ERROR
WARN
INFO
DEBUG
TRACE
ALL
级别 描述 适用场景
OFF 关闭所有日志输出 生产环境临时关闭日志
FATAL 系统无法继续运行的严重错误 记录导致系统崩溃的错误
ERROR 运行时错误,但不影响系统继续运行 业务异常、数据库连接失败等
WARN 潜在问题,不影响当前功能 废弃 API 调用、配置不合理
INFO 系统运行状态信息 服务启动、用户登录等关键操作
DEBUG 开发调试信息 变量值、方法调用流程
TRACE 更细粒度的追踪信息 复杂业务流程追踪(极少使用)
ALL 启用所有日志级别 测试环境全量日志收集

如何输出日志---加@Slf4j注解    log.error、log.warn等

如何修改日志级别 ---👇

logging.level.root=debug

logging.level.包名=debug

4、定时器  相关的注解,如何定时功能(掌握)

//开启定时----在启动类上添加该注解
@EnableScheduling

//表示每隔6秒打印一次
@Scheduled(cron = "*/6(秒) *(分) *(时) *(日) *(月) *(周)")(再往后加*还有年,但老师没演示成功,好像不可用)

//表示每隔6秒打印一次
@Scheduled(fixedRate = 6000)

//第一次延迟5秒执行,之后10秒执行一次
@Scheduled(initialDelay = 5000, fixedDelay = 10000)

@Scheduled(fixedRate = 6000) :上一次开始执行时间点之后6秒再执行
@Scheduled(fixedDelay = 6000) :上一次执行完毕时间点之后6秒再执行

5、swagger 接口工具  了解

引入jar包----pom.xml文件导入依赖

springboot 2.6  2.7配置  application.yml文件


6、springboot自动装配原理(看面试题,按照面试题背 )

@EnableAutoConfiguration

条件装配注解,今天讲的见上六👆

整合好的面试题👇

1.当启动项目时,会执行@SpringbootApplication

2.该注解会启动其下的@EnableAutoConfiguration(自动装配)

3.自动装配的注解就是从 组件自动装配选择器(AutoConfigurationImportSelector)中读取组件列表

4.组件列表(META-INF/spring.factories)中就列举了众多需要进行整合的组件

5.就会找到对一个的组件类(xxxAutoConfiguration)

6.在组件类的上方就会判断当前项目是否需要与此组件整合 (@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}))

7.如果判断当前项目没有此类,则不会进行该组件的加载

8.如果判断当前项目有此类,则会读取与该组件整合的配置文件 (@EnableConfigurationProperties({DataSourceProperties.class}))

9.如果读取失败,则装配失败,项目报错

10,如果读取成功,则装配成功,springboot与该技术即整合成功

总结:整合什么技术 -- 导入该技术的jar包(场景包) -- 设置相关的属性 -- 整合成功

结论:

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration;
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。

                     Properties里面拿。

                    Properties和配置文件进行了绑定;

  • 生效的配置类就会给容器中装配很多组件;
  • 只要容器中有这些组件,相当于这些功能就有了;

网站公告

今日签到

点亮在社区的每一天
去签到