通用許可權系統-Spring-Boot-Starter

2023-07-08 21:00:46

Spring-Boot-Starter

自定義Starter

案例一:讀取application.yml中的引數

1、建立

1、建立maven工程hello-spring-boot-starter

2、pom中新增依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>hello-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.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-autoconfigure</artifactId>
        </dependency>
    </dependencies>
</project>

3、建立HelloProperties
設定屬性類,用於封裝組態檔中設定的引數資訊

package org.example.config;

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

/**
 * TODO 設定屬性類,用於封裝組態檔中設定的引數資訊
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 13:55
 */
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
    private String name;
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "HelloProperties{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

4、建立HelloService
這個類用於對讀取到的引數進行一些業務上的操作

package org.example.service;

/**
 * TODO
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 14:03
 */
public class HelloService {
    private String name;
    private String address;

    public HelloService(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String sayHello(){
        return "你好!我的名字叫做"+name+",地址是" + address;
    }
}

5、建立HelloServiceAutoConfiguration(用於自動設定HelloService物件)

package org.example.config;

import org.example.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * TODO 自動設定類
 * 通過@Configuration + @Bean 實現自動建立物件
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 14:06
 */
@Configuration
// 一定要加上這個註解,否則Spring找不到這個設定類
@EnableConfigurationProperties(value = HelloProperties.class)
public class HelloServiceAutoConfiguration {


    private HelloProperties helloProperties;

    // 通過構造方法注入設定屬性物件HelloProperties
    public HelloServiceAutoConfiguration(HelloProperties helloProperties) {
        this.helloProperties = helloProperties;
    }
    // 範例化HelloService並載入Spring IOC 容器
    @Bean
    @ConditionalOnMissingBean// Spring中沒有這個範例的時候再去建立
    public HelloService helloService(){
        return new HelloService(helloProperties.getName(), helloProperties.getAddress());
    }
}

6、在resources目錄下建立META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.example.config.HelloServiceAutoConfiguration

7、將工程打包到maven倉庫中

2、使用

1、建立專案,匯入自定義starter

2、建立application.yml組態檔

3、建立啟動類

package org.example;

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

/**
 * TODO
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 14:39
 */
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class,args);
    }
}

4、建立測試Controller

package org.example.controller;

import org.example.annotaion.MyLog;
import org.example.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * TODO
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 14:36
 */
@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private HelloService helloService;

    @GetMapping("/sayHello")
    
    public String sayHello() {
     return helloService.sayHello();
    }
}

5、測試

案例二:通過自動設定來建立一個攔截器物件,通過此攔截器物件來實現記錄紀錄檔功能

1、建立

1、建立maven專案並且引入依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>org.example</groupId>
    <artifactId>log-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

2、建立MyLog註解

package org.example.annotaion;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    /**
     * 方法描述
     * @return
     */
    String desc() default "";
}

3、建立紀錄檔攔截器

package org.example.interceptor;

import org.example.annotaion.MyLog;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * TODO 自定義紀錄檔攔截器
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 17:43
 */
public class MyLogInterceptor extends HandlerInterceptorAdapter {
    private static final ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();// 記錄時間毫秒值

    /**
     * 執行之前
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 進行轉換
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 獲取方法上的註解MyLog
        MyLog annotation = method.getAnnotation(MyLog.class);
        if(annotation != null){
            // 說明當前攔截到的方法上加入了MyLog註解
            long currentTimeMillis = System.currentTimeMillis();
            startTimeThreadLocal.set(currentTimeMillis);
        }
        return true;
    }

    /**
     * 執行之後
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        // 獲取方法上的註解MyLog
        MyLog annotation = method.getAnnotation(MyLog.class);
        if(annotation != null){
            // 說明當前攔截到的方法上加入了MyLog註解
            Long startTime = startTimeThreadLocal.get();
            long endTime = System.currentTimeMillis();
            long optTime =  endTime - startTime;

            String requestUri = request.getRequestURI();
            String methodName = method.getDeclaringClass().getName() + "."+
                                method.getName()+"()";
            String methodDesc = annotation.desc();

            System.out.println("請求uri:"+requestUri);
            System.out.println("請求方法名:"+methodName);
            System.out.println("方法描述:"+methodDesc);
            System.out.println("方法執行時間:"+optTime+"ms");

        }
        super.postHandle(request, response, handler, modelAndView);
    }
}

4、建立自動裝配物件

package org.example.config;

import org.example.interceptor.MyLogInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * TODO
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 18:08
 */
@Configuration
public class MyLogAutoConfiguration implements WebMvcConfigurer {
    /**
     * 註冊自定義紀錄檔攔截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyLogInterceptor());
    }
}

5、在resources下建立META-INF,在該資料夾下建立spring.factories
該組態檔用於掃描自動裝配類

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.example.config.MyLogAutoConfiguration  

2、使用

1、建立一個web專案,並且引入依賴,pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>use-my-spring-boot-starter-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>log-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>hello-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

2、建立測試Controller
在測試的方法上新增上自定義的MyLog註解,當該方法執行的時候就會在控制檯輸出對應資訊

package org.example.controller;

import org.example.annotaion.MyLog;
import org.example.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * TODO
 *
 * @author ss_419
 * @version 1.0
 * @date 2023/7/8 14:36
 */
@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private HelloService helloService;

    @GetMapping("/sayHello")
    @MyLog(desc = "sayHello方法")
    public String sayHello() {
     return helloService.sayHello();
    }
}

3、測試

到這裡,對於自定義starter的案例就結束了。