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类。
整体结果如下:
下面就把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("
描述:{}
路径: {}
方法: {}
参数:{}
耗时:{}", 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就可以了。
结构如下:
<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;
}
}