zl程序教程

您现在的位置是:首页 >  后端

当前栏目

springboot自定义starter

SpringBoot 自定义 Starter
2023-09-11 14:16:49 时间

springboot自定义starter

创建自己的Starter

一个完整的Spring Boot Starter可能包含以下组件:

  • autoconfigure模块:包含自动配置的代码
  • starter模块:提供对autoconfigure模块的依赖,以及一些其它的依赖

简而言之,starter应该提供使用该库所需的一切

autoconfigure模块

它是一个springboot项目

    <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>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.58</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

注意:如果你是直接建的boot项目,把xml的插件去掉,不然会提示找不到main类。

整体结果如下:

image-20210309155830480

下面就把demo的代码和进阶的代码一起粘贴一下。

/**
 * @author WGR
 * @create 2021/3/8 -- 17:06
 */
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
    private String prefix;
    private String suffix;

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}

/**
 * @author WGR
 * @create 2021/3/8 -- 17:05
 */
@Configuration
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {

    @ConditionalOnMissingBean(HelloService.class)
    @Bean
    public HelloService helloService(){
        HelloService helloService = new HelloService();
        return helloService;
    }
}


/**
 * @author WGR
 * @create 2021/3/9 -- 13:47
 */
@Configuration
public class MyLogAutoConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration interceptorRegistration = registry.addInterceptor(new MyLogInterceptor());
        interceptorRegistration.addPathPatterns("/**");
    }
}

/**
 * @author WGR
 * @create 2021/3/9 -- 13:48
 */
@Slf4j
public class MyLogInterceptor implements HandlerInterceptor {

    //线程隔离,每个线程都有自己的其实时间,但是它有内存泄漏的风险。
    private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //其实在请求的时候,requestMapping会把所有的方法封装成HandlerMethod,最后放到拦截器中,一起返回。
        if(handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();

            if (method.isAnnotationPresent(Log.class)) {
                //  设置开始时间
                long startTime = System.currentTimeMillis();
                threadLocal.set(startTime);
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            Log log = method.getAnnotation(Log.class);
            if(method.isAnnotationPresent(Log.class)){
                //  设置开始时间
                Long startTime = threadLocal.get();
                Long endTime = System.currentTimeMillis();
                Long expendTime = endTime - startTime;

                // 方法参数
                String uri = request.getRequestURI();
                String methodName = method.getDeclaringClass().getName() + "#" + method.getName();
                String methodDesc = log.value();
                String parameters = JSON.toJSONString(request.getParameterMap());
                MyLogInterceptor.log.info("\n描述:{}\n路径: {}\n方法: {}\n参数:{}\n耗时:{}", methodDesc, uri, methodName, parameters, expendTime);
            }
        }

    }
}

/**
 * @author WGR
 * @create 2021/3/9 -- 13:42
 */

import org.springframework.stereotype.Component;

import java.lang.annotation.*;

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

    String value() default "";
}


/**
 * @author WGR
 * @create 2021/3/8 -- 17:10
 */
public class HelloService {

    @Autowired
    HelloProperties helloProperties;

    public String sayHello(String userName){
        return helloProperties.getPrefix() + ":"+userName+"》"+helloProperties.getSuffix();
    }
}

配置文件:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.dalianpai.hello.configuration.HelloServiceAutoConfiguration, \
  com.dalianpai.hello.configuration.MyLogAutoConfiguration

最后在maven install打入本地仓库。

starter模块

事实上,starter是一个空jar。它唯一的目的是提供这个库所必须的依赖。它依赖autoconfigure就可以了。

结构如下:

image-20210309160328741

    <dependencies>
        <dependency>
            <groupId>com.dalianpai</groupId>
            <artifactId>dalianpai-hello-spring-boot-starter-autoconfigure</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

进行测试:

引入starter

 <dependency>
            <groupId>org.example</groupId>
            <artifactId>dalianpai-hello-spring-boot-starter</artifactId>
            <version>1.0.0</version>
        </dependency>

测试类


/**
 * @author WGR
 * @create 2021/3/8 -- 17:29
 */
@RestController
public class HelloController {

    @Autowired
    HelloService helloService;

    @GetMapping("/hello")
    @Log("测试")
    public String sayHello(){

        String s = helloService.sayHello("张三");
        return s;
    }
}

image-20210309160628023

image-20210309160646550