Hot-swappable component customization - on Spring-boot-starter implementation

1. Pre-knowledge points

To learn this tutorial, certain pre-knowledge points are required

1> Proficiency in using Maven

2> Familiar with the web system

3> Skilled use of Spring/SpringMVC framework

4> Proficiency in using the SpringBoot framework

5> Familiar with java log (demonstration case)

2. Lead out the starter

Let’s take an example to feel the simplicity of Spring-boot-starter

Requirement: Build a web project, visit: http://localhost:8080/hello Return: Hello, Langfei yes

2.1 Traditional Spring MVC

Step 1: Create project-mvc-demo

Step 2: Import dependent packages

<properties>
	<spring.version>5.0.8.RELEASE</spring.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>javax.servlet-api</artifactId>
		<version>3.0.1</version>
		<scope>provided</scope>
	</dependency>
</dependencies>
<build>
	<plugins>
		<plugin>
			<groupId>org.apache.tomcat.maven</groupId>
			<artifactId>tomcat7-maven-plugin</artifactId>
			<version>2.1</version>
			<configuration>
				<port>8080</port>
				<path>/</path>
				<uriEncoding>UTF-8</uriEncoding>
			</configuration>
		</plugin>
	</plugins>
</build>

Step 3: web configuration

Create a new mvc.xml in the resources directory, and configure it as follows:

<!-- 配置 IoC DI 注解解析器,让 Spring 我们创建 HelloController 类的对象 -->
<context:component-scan base-package="com.langfeiyes.mvc.controller"/>
<!-- MVC 注解解析器 -->
<mvc:annotation-driven/>

Create a new webapp/WEB-INF/web.xml in the main directory, the content is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <!-- Spring MVC 前端控制器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定 Spring 容器启动加载的配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:mvc.xml</param-value>
        </init-param>
        <!-- Tomcat 启动初始化 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Step 4: Write the Code

package com.langfeiyes.mvc.controller;

@RestController
public class HelloController {
    // 提供方法处理请求,在浏览器地址栏输入如下 localhost/hello,就会执行下面的方法
    @RequestMapping("/hello") 
    public String save() {
        return "hello, 浪飞yes";
    }
}

Step 5: Test

Open the browser, enter http://localhost:8080/hello in the address bar , and visit to see the effect.

2.2 Overlay SpringBoot's Starter

Step 1: Create project-starter-demo

Step 2: Import dependent packages


<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
</parent>

<dependencies>    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

Step 3: Write the Code

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
        return "Hello,浪飞yes";
    }
}

Step 4: Test

Write a startup class startup project

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

Open the browser, enter http://localhost:8080/hello in the address bar , and visit to see the effect.

Here first remember the most notable feature of Starter: making development easier

3. What is a Starter

From the comparison of the above two web projects, you will find that the SpringMVC operation superimposed with SpringBoot will be easier to use, unlike the traditional Spring MVC, a bunch of xml configuration files, once the xml configuration is neglected, the entire project It may hang up inexplicably. If there are many and complicated xml files, you don’t know how to solve them. It feels uncomfortable to have nothing to love in this life.

However, since you have SpringBoot + Starter, you will find that the world couldn't be better~

So what is SpringBoot and what is Starter?

3.1 Spring Boot review

SpringBoot simply sums up a few points:

1> Jar collectors, collecting jars of various common third-party frameworks/components

2> Gadget lovers, classify and summarize the collected jars according to modules/functions, and get larger functional jar packages: Starter

3>Automatically configure small experts, according to the introduction of jar, automatically load various functions into the project

The detailed SpringBoot operation will not be discussed here. It belongs to the pre-knowledge points. Friends who have no foundation can go to my B station space to watch the SpringBoot introductory video. <<SpringBoot entry to enterprise actual combat, from rookie to veteran, only takes 6 hours~>>

or csdn course

Take you from entry to proficiency in 8 hours-SpringBoot

3.2 Spring Boot starter

Spring-boot-starter is called the SpringBoot starter. Spring Boot customizes the collection of dependency libraries (jar) based on the basic dependencies (jar) required by the application, which can be used to quickly start the Spring application. For example: importing spring-boot-starter-web can introduce the entire mvc environment, and importing: spring-boot-starter-Redis can directly use the Redis database.

Spring-boot-starter is designed as a separable and reusable hot-swappable module, which greatly simplifies the construction process of Spring programs and improves the flexibility of program design.

3.3 Common Spring-Boot-Starter

There are 2 types of starters,

  • SpringBoot default, customized by Spring official

Naming format: spring-boot-starter-{module name}

Common Starter

spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置、日志和YAML。
spring-boot-starter-actuator 帮助监控和管理应用。
spring-boot-starter-amqp 通过spring-rabbit来支持AMQP协议
spring-boot-starter-aop 支持面向方面的编程即AOP,包括spring-aop和AspectJ。
spring-boot-starter-artemis 通过Apache Artemis支持JMS的API(Java Message Service API)。
spring-boot-starter-batch 支持Spring Batch,包括HSQLDB数据库。
spring-boot-starter-cache 支持Spring的Cache抽象。
spring-boot-starter-cloud-connectors 支持Spring Cloud Connectors,简化了在像Cloud Foundry或Heroku这样的云平台上连接服务。
spring-boot-starter-data-elasticsearch 支持ElasticSearch搜索和分析引擎,包括spring-data-elasticsearch。
spring-boot-starter-data-gemfire 支持GemFire分布式数据存储,包括spring-data-gemfire。
spring-boot-starter-data-jpa 支持JPA(Java Persistence API),包括spring-data-jpa、spring-orm、hibernate。
spring-boot-starter-data-MongoDB 支持MongoDB数据,包括spring-data-mongodb。
spring-boot-starter-data-rest 通过spring-data-rest-webmvc,支持通过REST暴露Spring Data数据仓库。
spring-boot-starter-data-solr 支持Apache Solr搜索平台,包括spring-data-solr。
spring-boot-starter-freemarker 支持FreeMarker模板引擎。
spring-boot-starter-groovy-templates 支持Groovy模板引擎。
spring-boot-starter-hateoas 通过spring-hateoas支持基于HATEOAS的RESTful Web服务。
spring-boot-starter-hornetq 通过HornetQ支持JMS。
spring-boot-starter-integration 支持通用的spring-integration模块。
spring-boot-starter-jdbc 支持JDBC数据库。
spring-boot-starter-jersey 支持Jersey RESTful Web服务框架。
spring-boot-starter-jta-atomikos 通过Atomikos支持JTA分布式事务处理。
spring-boot-starter-jta-bitronix 通过Bitronix支持JTA分布式事务处理。
spring-boot-starter-mail 支持javax.mail模块。
spring-boot-starter-mobile 支持spring-mobile。
spring-boot-starter-mustache 支持Mustache模板引擎。
spring-boot-starter-Redis 支持Redis键值存储数据库,包括spring-redis。
spring-boot-starter-security 支持spring-security。
spring-boot-starter-social-facebook 支持spring-social-facebook
spring-boot-starter-social-linkedin 支持pring-social-linkedin
spring-boot-starter-social-twitter 支持pring-social-twitter
spring-boot-starter-test 支持常规的测试依赖,包括JUnit、Hamcrest、Mockito以及spring-test模块。
spring-boot-starter-thymeleaf 支持Thymeleaf模板引擎,包括与Spring的集成。
spring-boot-starter-velocity 支持Velocity模板引擎。
spring-boot-starter-web S支持全栈式Web开发,包括Tomcat和spring-webmvc。
spring-boot-starter-websocket 支持WebSocket开发。
spring-boot-starter-ws 支持Spring Web Services。
spring-boot-starter-remote-shell 增加了远程ssh shell的支持。
spring-boot-starter-jetty 引入了Jetty HTTP引擎(用于替换Tomcat)。
spring-boot-starter-log4j 支持Log4J日志框架。
spring-boot-starter-logging 引入了Spring Boot默认的日志框架Logback。
spring-boot-starter-tomcat 引入了Spring Boot默认的HTTP引擎Tomcat。
spring-boot-starter-undertow 引入了Undertow HTTP引擎(用于替换Tomcat)
  • Third party customization

According to the Starter customization rules developed by SpringBoot, many third-party organizations combine SpringBoot to customize their own starters.

Naming format: {module name}-spring-boot-starter

mybatis-spring-boot-starter:该starter提供了MyBatis框架的集成支持,可以帮助开发人员更快地搭建基于MyBatis的应用程序。

dubbospring-boot-starter:该starter提供了Dubbo分布式服务框架的集成支持,可以帮助开发人员更快地实现微服务架构。

elasticsearch-spring-boot-starter:该starter提供了Elasticsearch搜索引擎的集成支持,可以帮助开发人员更快地搭建基于Elasticsearch的搜索服务。

logstash-spring-boot-starter:该starter提供了Logstash日志收集框架的集成支持,可以帮助开发人员更快地集成Logstash服务。

druid-spring-boot-starter:该starter提供了Druid数据库连接池的集成支持,可以帮助开发人员更快地实现数据库连接池功能。

4. How to customize Starter

Before answering how to customize Starter, we must first figure out one thing: why customize?

4.1 Why customize

In daily development work, there are often some functional modules that are independent of the business. The traditional approach is to code directly in the project. If another project needs to reuse this functional module, it is necessary to hard copy the code and then reintegrate it again. This repeated operation is extremely troublesome. Wouldn't it be cool if these functional modules that can be independent of the business are encapsulated into starters, and only need to reference dependencies in the pom when reused?

For example, the following functional modules outside of business

1>General module - SMS sending module

2> Based on AOP technology log aspect

3> Distributed snowflake Long type ID precision loss problem

4> Database connection pool configuration for microservice projects

5> Introduction of Redis database for microservice projects

6> Problems introduced by multi-module project authentication components

4.2 Starter custom implementation

In the first case, the design is simpler, and the printing operation is simply intercepted.

4.2.1 Requirements description

Requirements : Design an interception starter, intercept all requests in the project, and print the configured info information.

Requirements :

Determine whether to enable or disable by configuring the value of mvc.interceptor.show in yml

mvc:
  interceptor:
    info: hello,浪飞yes
    show: true

 

4.2.2 Implementation steps

1> Create a project: intercept-show-spring-boot-starter

2> Import related dependencies

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.2.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

3> Define the receiving resource configuration ShowProperties configuration class

There are 2 resource configurations: info/show

mvc:
  interceptor:
    info: hello,浪飞yes...
    show: true

Receiving class

package com.langfeiyes.mvc.prop;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "mvc.interceptor")
public class ShowProperties {
    private boolean show = true;

    private String info;

    public boolean isShow() {
        return show;
    }

    public void setShow(boolean show) {
        this.show = show;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

4>Define the interceptor-ShowInfoInterceptor

package com.langfeiyes.mvc.interceptor;

import com.langfeiyes.mvc.prop.ShowProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ShowInfoInterceptor implements HandlerInterceptor {

    @Autowired
    private ShowProperties showProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (showProperties.isShow()){
            if (StringUtils.hasText(showProperties.getInfo())) {
                System.out.println(showProperties.getInfo());
            }else{
                System.out.println("Hello,浪飞yes....");
            }
        }

        return true;
    }
}

5> Define the configuration interceptor class -- WebConfig

package com.langfeiyes.mvc.config;

import com.langfeiyes.mvc.interceptor.ShowInfoInterceptor;
import com.langfeiyes.mvc.prop.ShowProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public ShowProperties showProperties(){
        return new ShowProperties();
    }

    @Bean
    public ShowInfoInterceptor showInfoInterceptor(){
        return new ShowInfoInterceptor();
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(showInfoInterceptor())
                .addPathPatterns("/**");
    }
}

6> Configure the starter entry startup class/configuration class-ShowInfoAutConfig

package com.langfeiyes.mvc.config;


import com.langfeiyes.mvc.interceptor.ShowInfoInterceptor;
import com.langfeiyes.mvc.prop.ShowProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


@ConditionalOnProperty(name = "mvc.interceptor.show", matchIfMissing = false)
@Configuration
@ComponentScan("com.langfeiyes.mvc")
public class ShowInfoAutConfig {

}

ConditionalOnProperty: The show attribute is required in the configuration file. If it does not exist, it defaults to false, indicating that the interceptor does not take effect.

ComponentScan: Scan the specified package to realize the loading of each component

7> Configure starter starter entry --resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.langfeiyes.mvc.config.ShowInfoAutConfig

4.2.3 Use test

1> Create a project: mvc-starter-demo

2> Import related dependencies

<!--父工程-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.2.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>com.langfeiyes.mvc</groupId>
        <artifactId>show-spring-boot-starter</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

3> Configure interception starter

mvc:
  interceptor:
    info: hello,dafei...
    show: true

4> Write a controller to initiate a web request


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(){
        return "hello...fei~";
    }
}

5> Start the project and test

package com.langfei.mvc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

1: Open the browser, enter http://localhost:8080/hello in the address bar , and visit to see the effect.

2: Open the console and see the print of the interceptor

3: Change the show of the configuration file to false and test again

mvc:
  interceptor:
    info: hello,dafei...
    show: false

4: Delete the configuration file directly, and try again

5. What is the principle of Starter

To talk about the principle of requesting a starter, you must first understand the principle of SpringBoot automatic configuration.

SpringBoot automatic configuration principle

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

Vernacular:

1> After the project is started, SpringBoot will find all META-INF/spring.factories under the jar package, and read the preset candidate configuration classes.

2> Then match the @ConditionalOnXxx conditions set by the candidate configuration class according to the imported dependency/configuration file

3> When the preset conditions of the candidate configuration class are met, the candidate configuration class will be activated, and SpringBoot will immediately assemble all the information for the configuration class.

Image source network

 The above figure is simplified:

The implementation principle of Starter is actually the principle of SpringBoot’s automatic assembly. The difference is that you need to manually customize the subsequent configuration classes of the starter itself.

Example Starter execution process in the case

SpringBoot---->spring.factories--->candidate ShowInfoAutConfig configuration class

--->Matching: @ConditionalOnClass/@ConditionalOnProperty--->Satisfies the conditions to start assembly

--->@ComponentScan("com.langfeiyes.mvc")--->Load configuration: WebConfig--->Interceptor configured successfully

6. Starter actual combat case

6.1 Requirements description

Requirements: Customize a starter, when the request mapping method needs to log, just paste the @Log annotation.

Requirement: Determine whether to enable or disable by configuring the value of mvc.log.enabled in yml

mvc:
  log:
    enabled: true

6.2 Implementation steps

1> Create a project: log-aspect-spring-boot-starteer

2> Import related dependencies

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.2.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

</dependencies>

3> Define the receiving resource configuration JobProperties configuration class

There is 1 provisional resource configuration: enabled

mvc:
  log:
    enabled: true

Receiving class

package com.langfeiyes.log.prop;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "mvc.log")
public class LogProperties {
    private boolean enabled;
    public boolean isEnabled() {
        return enabled;
    }
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

4> Define the log annotation - @Log

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
}

5> Define the log aspect class -LogAspect

package com.langfeiyes.log.aspectj;

import com.langfeiyes.log.annotation.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
public class LogAspect{

    @Pointcut("@annotation(log)")
    public void webLog(Log log) {
    }

    @Before("webLog(log)")
    public void doBefore(JoinPoint joinPoint, Log log) {
        // 打印请求日志
        System.out.println("before" + log);
    }

    @AfterReturning(returning = "ret", pointcut = "webLog(log)")
    public void doAfterReturning(Object ret, Log log) {
        // 打印响应结果日志
        System.out.println("doAfterReturning" + log);
    }
}

6> Configure the starter entry startup class/configuration class -LogAspectEnableAutoConfiguration

package com.langfeiyes.log.config;


import com.langfeiyes.log.aspectj.LogAspect;
import com.langfeiyes.log.prop.LogProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(LogProperties.class)
@ConditionalOnProperty(name = "mvc.log.enabled", matchIfMissing = true)
@ComponentScan("com.langfeiyes.log")
public class LogAspectEnableAutoConfiguration {

    @Bean
    public LogProperties logProperties(){
        return  new LogProperties();
    }

    @Bean
    public LogAspect logAspect(){
        return  new LogAspect();
    }
}

ConditionalOnProperty: The enabled attribute is required in the configuration file. If it does not exist, it defaults to false, indicating that the log does not take effect.

ComponentScan: Scan the specified package to realize the loading of each component

7> Configure starter starter entry --resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.langfeiyes.log.config.LogAspectEnableAutoConfiguration

6.3 Use test

1> Create a project: mvc-log-demo

2> Import related dependencies

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.2.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>com.langfeiyes.log</groupId>
        <artifactId>log-aspect-spring-boot-starteer</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

3> Configure the log starter

mvc:
  log:
    enabled: true

4> Write a controller to initiate a web request

package com.langfei.mvc.controller;

import com.langfeiyes.log.annotation.Log;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Log
    @GetMapping("/hello")
    public String hello(){
        return "ok-aspect";
    }
}

5> Start the project and test

package com.langfei.mvc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

1: Open the browser, enter http://localhost:8080/hello in the address bar , and visit to see the effect.

2: Open the console and see the print of the log

3: Change the enabled of the configuration file to false and test again

mvc:
  log:
    enabled: false

4: Delete the configuration file directly, and try again

6.4 Upgrading

Transform the @Log annotation to make the logging content richer

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    //日志标题
    String title() default "";

    //操作类别
    OperType  type() default OperType.OTHER;
}

New type enumeration class

package com.langfeiyes.log.annotation;

/**
 * 业务操作类型
 */
public enum OperType
{
    /**
     * 其他
     */
    OTHER,
    /**
     * 查
     */
    QUERY,

    /**
     * 新增
     */
    INSERT,

    /**
     * 修改
     */
    UPDATE,

    /**
     * 删除
     */
    DELETE,
}

Transform the HelloController class

package com.langfei.mvc.controller;

import com.langfeiyes.log.annotation.Log;
import com.langfeiyes.log.annotation.OperType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        return "ok-aspect";
    }

    @Log(title = "员工查询", type = OperType.QUERY)
    @GetMapping("/emps/detail")
    public String detail(){
        return "ok-detail";
    }

    @Log(title = "员工添加", type = OperType.INSERT)
    @GetMapping("/emps/save")
    public String save(){
        return "ok-save";
    }
}

Start the App class to access the following path and observe the results:

http://localhost:8080/emps/detail --- "The current operation is: employee query-QUERY

http://localhost:8080/emps/save --- "The current execution operation is: employee addition - INSERT

At this point, the introduction of the spring-boot-starter starter is over~

Guess you like

Origin blog.csdn.net/langfeiyes/article/details/130038798
Recommended