SpringBoot

0.SpringBoot模块汇总

在这里插入图片描述

1.Webjars是什么?有什么用?

  • Webjars 是将web前端资源(例如jquery/BookStrap/等css和js文件)打成jar包文件,然后借助Maven工具,以jar包的形式对web前端资源进行统一管理,保证这些web资源的唯一性。Webjars的jar包部署在Maven中央仓库上。
  • 用过SpringMVC的人都知道,静态的js、css等文件都需要配置静态资源的映射;但在SpringBoot中不需要进行此项的配置,因为SpringBoot已经内置对Webjars的支持。SpringBoot自动将 /webjars/ ** 请求 映射到classpath:/META-INF/resources/webjars/ 目录下。
        <!--Webjar官网:https://www.webjars.org/-->
        <!--Webjars版本定位工具:省略版本号-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
        </dependency>
        <!--Jquery3.3.1-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1</version>
        </dependency>
        <!--bootstrap3.3.7-1-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7-1</version>
        </dependency>
<!--忽略版本号之前的URL请求-->
<script src="/webjars/jquery/3.1.1/jquery.min.js"></script> 
<script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script> 
<title>WebJars</title> 
<link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css" /> 

<!--忽略版本号之后URL请求,忽略版本号有利于后续的版本升级,而不需要修改URL请求地址-->
<script src="/webjars/jquery/jquery.min.js"></script> 
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script> 
<title>WebJars</title> 
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css" />

2.SpringBoot 2.0监听器(ApplicationListener)的使用:ApplicationReadyEvent事件

  • 好处:该事件在SpringBoot程序启动后触发,配合日志在控制台打印Swagger2访问地址,项目访问地址,Druid监控地址。
  • ① 编写监听器类,实现ApplicationListener<>接口,重写onApplicationEvent方法。
package com.wpq.listener;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
@Slf4j
public class ApplicationInitListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        log.info(".......程序初始化成功,SpringBoot启动后执行......");
        log.info("Swagger2接口文档查看:http://localhost:8080/swagger-ui.html");
        log.info("角色页面访问:http://localhost:8080/role.html");
        log.info("Druid监控页面:http://localhost:8080/druid/sql.html");
    }
}
  • ② SpringBoot启动类中添加监听器。
package com.wpq;

import com.wpq.config.EnableNetWorkServiceAutoConfiguration;
import com.wpq.listener.ApplicationInitListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication
@MapperScan(basePackages ="com.wpq.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication application =new SpringApplication(Application.class);
        application.addListeners(new ApplicationInitListener());
        application.run(args);

        //SpringApplication.run(Application.class, args);


    }
}
  • ③ SpringBoot程序启动后,控制台打印访问地址,可直接访问。
2020-02-18 14:21:56.510  INFO 10052 --- [main] c.wpq.listener.ApplicationInitListener: .......程序初始化成功,SpringBoot启动后执行......

2020-02-18 14:21:56.510  INFO 10052 --- [main] c.wpq.listener.ApplicationInitListener: Swagger2接口文档查看:http://localhost:8080/swagger-ui.html

2020-02-18 14:21:56.510  INFO 10052 --- [main] c.wpq.listener.ApplicationInitListener: 角色页面访问:http://localhost:8080/role.html

2020-02-18 14:21:56.510  INFO 10052 --- [main] c.wpq.listener.ApplicationInitListener: Druid监控页面:http://localhost:8080/druid/sql.html

3.热部署是什么?SpringBoot怎么开启热部署?

  • 概念: 项目启动之后,如果内容有更改,项目会自动地实现及时更新,而不需要从新手动启动这个项目。
  • SpringBoot有几种方式开启热部署,下面推荐一种最为常用的方式。
  • 方式:手动进行热部署的触发。
  • ① 导包
 <!--导包
     下面的这个包是咋们开发的时候 需要的所有的工具 在这里面都是有的。
     热部署的这个工具也是位于这个包里面
        -->
 <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-devtools</artifactId>
 </dependency>

② pom.xml中配置plugin。

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
</build>

③ 配置触发。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.SpringBoot内置日志框架logback的详细配置和说明

  • ① application.yml文件中设置logback配置文件位置。
logging:
  config: classpath:logback-spring.xml  #指定logback配置文件的位置
  • ② logback-spring.xml文件中进行细节配置(文件名以spring结尾可以享受SpringBoot的高级特性)
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="60 seconds">
    <!-- 1. scan :设置是否动态加载该配置,设置为true的时候,只要文件改变,该文件就会被重新加载-->
    <!-- 2. scanPeriod :设置监听配置文件是否有修改的时间间隔,没有给定时间单位的话那么默认时间单位是毫秒。
    当scan为true的时候,此属性生效。-->
    <!-- 3. debug:当此属性设置为true的时候,将打印出logback内部日志信息,实时查看logback的运行状态。默认false-->
    <!-- 4. contextName :设置上下文名称,默认上下文名称为"default",可自定义,
    用于区分不同应用程序的记录,一旦设置,不能修改-->
    <contextName>logback</contextName>
    <!-- 5. property :设置变量,name是键,value是值,设置之后可以在其它标签中使用${name值}引用-->
    <property name="log.path" value="./logs/spring.log"/>
    <!-- 6. appender : 定义日志组件-->
    <!-- 7. ConsoleAppender :输出日志到控制台的类 -->
    <!-- 8. encoder:指定日志的输出格式(pattern)和编码格式(charset)-->
    <!-- 9. springProfile: SpringBoot高级标签,用于多环境的配置,name属性指定环境名称-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
                              <!--表示的是输出日志的格式
                                    %d{yyyy-MM-dd-HH:mm:ss.SSS}:时间引用
                                    %level:日志的级别
                                    %contextName:上下文名称
                                    [%thread]:线程名字
                                    %class:打印对象的全类名
                                    %logger{36}: 打印日志的类的全类名,并限定不能超过36个字符
                                    %file:打印日志的类的.java文件  xxxController.java
                                    %line:打印日志的代码的行号(一般不要)
                                    %msg:日志记录的信息
                                    %n:换行
                               -->
            <!--默认环境-->
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>

            <!--dev环境-->
            <springProfile name="dev">
                <pattern>%d{HH:mm:ss} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
            </springProfile>

            <!--prod环境-->
            <springProfile name="prod">
                <pattern>%d{HH:mm:ss.SSS} ======= %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
            </springProfile>

            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 10. RollingFileAppender:滚动输出日志到文件夹的类,当达到一定条件的时候日志会输出到其它文件中 -->
    <!-- 11. file标签:设置日志文件的生成路径和名称 -->
    <!-- 12. rollingPolicy:设置滚动策略 -->
    <!-- 13. TimeBasedRollingPolicy:(常用)时间滚动策略,根据时间进行滚动,当达到一定的时间后,
                                     会自动开辟一个新的日志文件 ,最小的滚动单位是天,每天生成一个日志文件-->
    <!-- 14. fileNamePattern:文件名匹配:滚动生成的日志文件,会按照这个格式命名,
    引用时间来使文件名不重复-->
    <!-- 15. maxHistory: 设置生成日志的最大保留时间,单位为天,过期删除-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n </pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!-- 16. FixedWindowRollingPolicy:索引滚动策略,定义文件名称的时候使用%i作为占位符,滚动后会用角标替换 -->
    <!-- 17. minIndex:设置生成日志文件数量的最小值-->
    <!-- 18. maxIndex:设置生成日志文件数量的最大值-->
    <!-- 19. triggeringPolicy:滚动策略的触发器,可设置触发条件-->
    <!-- 20. maxFileSize:设置单个日志文件占用硬盘空间的最大值-->
    <appender name="fixedFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>./logs/spring-controller.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <!--%i:会调用索引,1>>2>>3循环-->
            <fileNamePattern>./logs/spring-controller.log%i.log</fileNamePattern>
            <minIndex>1</minIndex>
        <!-- 21. 最多生成三个日志文件,当三个日志文件的大小都为5M的时候,新的日志信息会覆盖第一个日志的内容-->
            <maxIndex>3</maxIndex>
        </rollingPolicy>

        <!-- 22. 触发器说明:单个日志文件的大小达到5M的时候会触发 索引滚动策略,生成新的日志文件继续记录-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>5MB</maxFileSize>
        </triggeringPolicy>

        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--23. appender整合过滤器,日志信息先经过过滤器的筛选,再交给logger或者root(调用者),
    调用者再用level属性进行二次过滤-->
    <appender name="fileFilter" class="ch.qos.logback.core.FileAppender">
        <file>./logs/spring-mapper.log</file>
        <!--append:设置新日志信息是否追加到旧日志信息,默认为true,false表示覆盖-->
        <append>true</append>

        <!-- 24. LevelFilter:日志级别过滤器。
            如果日志信息的级别等于配置(level)的级别。那么则执行onMatch里面的配置
            否则执行 onMismatch中的内容
        -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <!--
                 ACCEPT:当前日志信息被保存,不再经过其它的过滤器了
                 DENY:当前日志信息被删除,不再经过其它的过滤器了
                 NEUTRAL:将当前日志信息抛给下一个过滤器、如果是最后一个过滤器的话那么日志信息将会被保存
            -->
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>

        <!-- 25. ThresholdFilter:临界值过滤器:如果日志信息的级别低于配置(level)级别,将被过滤掉-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>

        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 26. prudent:设置是否线程安全,推荐关闭,设置线程安全会影响日志信息输出的效率-->
        <prudent>false</prudent>
    </appender>

    <!--27.
        logger:代表一个日志输出对象
        name: 指定包名
        level:指定日志级别
        appender-ref:表示对appender的引用
        additivity:设置是否向root(根logger)传递日志信息,false不传递,true传递
                    默认为true,即默认子logger是向root传递日志信息的
    -->

    <!--局部logger(子logger):记录controller层日志信息-->
    <logger name="com.wpq.controller" level="info" additivity="false">
        <appender-ref ref="fixedFile"/>
    </logger>


    <!--局部logger(子logger):记录mapper层日志信息-->
    <logger name="com.wpq.mapper" level="debug" additivity="false">
        <appender-ref ref="fileFilter"/>
    </logger>

    <!-- 28. root:可以理解为一个根节点,而其他的logger都可以看做root的子节点-->

    <!--全局logger(父logger):打印整个项目的所有日志信息-->
    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>

</configuration>

5.SpringBoot自动配置原理?

  • ① SpringBoot启动类中的@SpringBootApplication注解中包含了@EnableAutoConfiguration注解。

  • ② @EnableAutoConfiguration注解中包含了@Import(AutoConfigurationImportSelector.class)。

  • ③ AutoConfigurationImportSelector类中–>selectImports()方法。

  • ④ selectImports()方法中–>getCandidateConfigurations方法。

  • ④ getCandidateConfigurations方法中–>SpringFactoriesLoader.loadFactoryNames方法。

  • ⑤ SpringFactoriesLoader.loadFactoryNames方法中–>loadSpringFactories方法。

  • ⑥ loadSpringFactories方法中–classLoader.getResources(“META-INF/spring.factories”)

  • ⑦ 扫描所有jar包路径下的spring.factories文件

  • ⑧ 找到spring.factories文件,获取文件中列表清单,加载自动配置类。实现自动配置。

  • ⑨ 自动配置类是否生效又取决于条件注解。如@ConditionalOnBean,@ConditionalOnMissingBean,@ConditionalOnClass, @ConditionalOnProperty

在这里插入图片描述

6.SpringBoot实现全局异常拦截处理?

  • @RestControllerAdvice: 只能拦截Controller层的异常。
package com.wpq.excption;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wpq.dto.ResponseBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 *
 * 全局Controller层异常拦截,统一返回数据格式
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    private static final String ERROR_INFO = "errorInfo";

    /**
     * 全局处理Controller层的业务异常
     * @param e
     * @return
     * @throws JsonProcessingException
     */
    @ExceptionHandler(value = BasicBusinessException.class)
    public ResponseBean basicBusinessExceptionHandler(BasicBusinessException e) throws JsonProcessingException {
        String errorInfo = "";
        JSONObject data = null;
        if (e.getStackTrace().length>0){
            StackTraceElement element = e.getStackTrace()[0];
            errorInfo= e.toString()+ " 错位位置:"+element.getFileName()+":"+element.getLineNumber();
            data = new JSONObject();
            data.put(ERROR_INFO,errorInfo);
        }
        ResponseBean result = ResponseBean.businessError(e.getCode(), e.getMessage()).putData(data);
        log.error(new ObjectMapper().writeValueAsString(result));
        return result;
    }

  /**
     *全局捕获Controller层的系统异常
     * @param e
     * @return
     * 完整异常信息= 异常类型 + 产生异常的类 +错误行号
     */
       @ExceptionHandler(value = Exception.class)
       public ResponseBean exceptionHandler(Exception e) {
           String errorInfo = "";
           if (e.getStackTrace().length > 0) {
               StackTraceElement element = e.getStackTrace()[0];
               errorInfo = StringUtils.isEmpty(element.getFileName())
                           ? e.toString() + " 未找到错误文件"
                           : e.toString() + " 错误位置:" + element.getFileName() + ":" + element.getLineNumber();
           }
           JSONObject data = new JSONObject();
           data.put(ERROR_INFO, errorInfo);
           ResponseBean result = ResponseBean.businessError().putData(data);
           log.error(JSON.toJSONString(result));
           return result;
       }
}

7.SpringBoot使用@ConfigurationProperties 配置模块

  • 1.搭建SpringBoot项目,导入configuration-processor依赖
  <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-configuration-processor</artifactId>
       <optional>true</optional>
    </dependency>
  • 2.编写配置类
@ConfigurationProperties(prefix = "config.properties")
//@Component 可以自己注入到IOC
@Data
public class MyConfig {
    private String  name;
    private String  password;
    private Integer code;
}

@Configuration
@EnableConfigurationProperties(MyConfig.class)//讲Myconfig类注入到IOC容器
@Data
public class MyConfigSS {

    private MyConfig myConfig;
    private String   configName;
    private Integer  code;

    MyConfigSS(MyConfig config){
        this.myConfig = config;
        this.configName=config.getName();
        this.code=config.getCode();
    }
}

  • 3.yml或者properties中配置MyConfig的属性值,实现自动注入
config.properties.code=200
config.properties.password=12345
config.properties.name=jack

8.SpringBoot监视器actuator的使用

  • 1.搭建SpringBoot项目,导入actuator依赖
 <!--actuator-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  • 2.application配置文件中配置
# 监视器运行端口
management.server.port=8090

# 激活所有的内置Endpoints
management.endpoints.web.exposure.include=*

# 开启shutdown这个endpoint
management.endpoint.shutdown.enabled=true
  • 3.开启程序,浏览器地址栏输入http://localhost:8099/actuator/,后面可以加Endpoints

9.SpringBoot项目基础依赖

<!--spring boot parent-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
    </parent>
    
<!--properties-->    
    <properties>
        <spring-boot.version>2.0.4.RELEASE</spring-boot.version>
    </properties>
    
<!--dependencies-->
        <dependencies>
            <!--test-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--web-->
            <dependency>
	            <groupId>org.springframework.boot</groupId>
	            <artifactId>spring-boot-starter-web</artifactId>
           </dependency>
            <!--热部署-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>

        </dependencies>

<!--build-->
    <build>
    
         <!--指定jar包名为项目唯一ID加上项目版本号-->
        <finalName>${project.artifactId}-${project.version}</finalName>
          <plugins>
              <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <!--要和springboot版本号相匹配-->
                    <version>${spring-boot.version}</version>
                    <!--配置mvn package的时候执行springboot maven plugin
                    的repackage命令-->
                    <!--配置mvn install的时候执行springboot maven plugin
                    的repackage命令-->
                    <!--将项目重新打包成可运行的jar包-->
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                    <!--开启支持devtools 热部署-->
                    <configuration>
                        <fork>true</fork>
                    </configuration>
                </plugin>
            </plugins>
            
        <!--编译的时候同时也把包下面的xml同时编译进去-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
  </build>

10.SpringBoot获取服务器信息

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

@Slf4j
public class ServerConfig {

    private static final String serverPort;
    private static final String applicationName;

    static {
        Properties pro = new Properties();
        InputStream in = ServerConfig.class
        .getClassLoader().getResourceAsStream("application.properties");
        try
        {
            pro.load(in);
        }
        catch (IOException e)
        {
            log.error(e.getMessage(),e);
        }
        serverPort      = pro.getProperty("server.port");
        applicationName = pro.getProperty("spring.application.name");
    }

    public static String getServerInfo(){
        return applicationName+":"+serverPort;
    }
}

11.java -jar命令启动一个SpringBoot

java -jar [jar包绝对路径] CMD启动一个SpringBoot项目
将JAR包放在指定文件下: java -jar [jar包相对路径]   

12.SpringBoot内置Tomcat配置

#配置 Web 容器的端口号(默认为 8080)
server.port:

#配置当前项目出错时跳转去的页面
server.error.path:

#配置 session 失效时间。30m 表示 30 分钟,如果不写单位则默认单位是秒。(注意:由于 Tomcat 中配置 session 过期时间是以分钟为单位,如果我们这里设置是秒的话,那么会自动转换为一个不超过所配置秒数的最大分钟数。比如配置了 119 秒,那么实际 session 过期时间是 1 分钟)
server.servlet.session.timeout:

#配置项目名称(默认为 /),如果配置了项目名称,那么在访问路径中要加上配置的路径
server.servlet.context-path:

#配置 Tomcat 请求编码
server.tomcat.uri-encoding:

#配置 Tomcat 的最大线程数
server.tomcat.max-threads:

#配置 Tomcat 运行日志和临时文件的目录。若不配置,则默认使用系统的临时目录
server.tomcat.basedir:

13.EnvironmentAware

  • 根据application.yml或者application.properties文件中spring.active.profiles环境参数变量,加载对应环境变量结尾的properties或者yml配置文件。
@Component
public class EnvObj implements EnvironmentAware {
    private static Environment environment;//根据 spring.profile.active激活的环境,加载对应的yml和properties配置文件
    @Override
    public void setEnvironment(@NonNull Environment environment) {
        EnvObj.environment = environment;
        String property = environment.getProperty("APP.a");
        System.out.println("property = " + property);
        String property1 = environment.getProperty("APP.b");
        System.out.println("property1 = " + property1);
    }
}

14.AopContext.getCurrentProxy

  • 拿到当前类的代理类的实例来调用该类中方法。如带有日志自定义注解方法,直接被本类其它方法调用会丢失日志打印功能。可用该API解决该问题。Spring boot启动类注解记得要加上 @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) 来暴露AOP的代理对象,否则会报异常。
  • service层
@Service
public class TestLogService {

    @Log
    public Object test_a(){
        return "test_a";
    }

    //本类中AOP增强方法b调用本类另外一个AOP增强方法a,要使用代理对象去调用,否则a的日志将不会打印
    @Log
    public Object test_b(){
        TestLogService testLogService = (TestLogService) AopContext.currentProxy();
        return testLogService.test_a()+"_for_"+"test_b";
    }
}
  • 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    boolean printLog() default true;
}

  • AOP切面
@Aspect
@Component
@Slf4j
@Order(1)
public class LogAspect {
    @Pointcut("@annotation(com.wpq.hibernate.log.Log)")
    public void pc(){}

    @Around("pc()&& @annotation(lg)")
    public Object around(ProceedingJoinPoint jp,Log lg) throws Throwable {
        Object proceed = jp.proceed();
        boolean printLog = lg.printLog();
        if (printLog)
            log.info("result = {}",proceed.toString());
        return proceed;
    }
}
  • Controller层
    @RequestMapping(value = "logTest",
                    method = {RequestMethod.POST,RequestMethod.GET})
    public Object logT(Demo demo){
        Object o = testLogService.test_b();
    }    
  • 日志打印结果
LogAspect          : result = test_a
LogAspect          : result = test_a_for_test_b

15.SpringBoot使用Hibernate Validate

  • 1.SpringBoot配置类
import org.hibernate.validator.HibernateValidator;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

@SpringBootConfiguration
public class HibernateValidateConfig {

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
        postProcessor.setValidator(validator()); //设置validator模式为快速失败返回
        return postProcessor;
    }

    @Bean
    public Validator validator(){
        ValidatorFactory validatorFactory =
                Validation.byProvider( HibernateValidator.class )
                .configure()
                .failFast(false)//快速失败:遇到一个错误就立马中断检测
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }
}

  • 2.创建组接口和定义组顺序
public interface GroupA {}
public interface GroupB {}

 //指定组的验证顺序,前面组验证不通过的,后面组不进行验证:
 //组的意义:比如插入和更新验证的字段不同,组的概念
 @GroupSequence({GroupA.class, GroupB.class, javax.validation.groups.Default.class})
 public interface GroupOrder {}
  • 3.实体类
 @Data
 public static class Demo {
      @Length(min = 5,
              max = 17,
              message = "length长度在[5,17]之间!!",
              groups = {GroupA.class})
      private String length;

      @NotBlank(message="年龄不能为空!!"
               ,groups = GroupA.class)
      @Pattern(regexp="^[0-9]{1,2}$",
               message="年龄必须是0~99!!"
              ,groups = {GroupA.class})
      private String age;

      @Range(min = 150,
             max = 250,
             message = "高度在[150,250]之间",
             groups = {Default.class})
      private int high;


      @NotNull(message = "list cannot be null!",
                groups = {Default.class})
      //@Size适用于String, 集合, Map ,数组
      @Size(min = 3,
            max = 5,
            message = "list的Size在[3,5]",
            groups = {Default.class})
      private List<String> list;

      //只有一个@Pattern得话,如果是空,则不校验,如果不为空,则校验
      @Pattern(regexp="^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
               message="出生日期格式不正确",
               groups = {GroupB.class})
      @NotBlank(message = "出生日期必须填写!!",
                groups = {GroupB.class})
      private String birthday;
  }
  • 4.Controller层注入验证器,校验接口入参实体
 @Autowired
 Validator validator;//HibernateValidator 校验器
 @RequestMapping(value = "logTest",
                 method = {RequestMethod.POST,RequestMethod.GET})
 public Object logT(Demo demo){
        Set<ConstraintViolation<Demo>> validate =
                validator.validate(demo,GroupA.class);//也可以同时校验多个组
        for (ConstraintViolation<Demo> demo2ConstraintViolation : validate)   {
            String message = demo2ConstraintViolation.getMessage();
            System.out.println("message = " + message);
        }
}

16. bootstrap.yml优先application.yml(或properties)加载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值