| |
|
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
| -> Java知识库 -> 进阶篇-SpringBoot2.x自定义starter启动器 -> 正文阅读 |
|
|
[Java知识库]进阶篇-SpringBoot2.x自定义starter启动器 |
1、本篇前言Spring Boot为我们提供了简化企业级开发绝大多数场景的 (1)Starter的概念SpringBoot之所以大大地简化了我们的开发,用到的一个很重要的技术就是Starter机制! (2)Starter的优点
(3)自定义Starter的场景在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放到一个特定的包下,然后如果另一个工程需要复用这块功能的时候,只需要将其在pom中引用依赖即可,利用SpringBoot为我们完成自动装配即可。 常见的自定义Starter场景比如:
(4)自定义Starter命名规范SpringBoot官方建议其官方推出的starter以spring-boot-starter-xxx的格式来命名,而第三方开发者自定义的starter则以xxxx-spring-boot-starter的规则来命名,比如 mybatis-spring-boot-starter。 (5)自定义starter中几个重要注解
2、自定义Starter记录日志案例(1)项目结构两个工程如下:log-spring-boot-starter[starter模块],spring-boot-demo-starter-test[starter使用演示工程]。
(2)log-spring-boot-starter项目pom文件添加依赖<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
(3)编写请求日志注解/**
* 功能描述: 请求日志注解
* @author TuYong
* @date 2022/9/7 20:48
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLog {
//接口方法上的描述信息
String desc() default "";
}
(4)编写配置类@Setter
@Getter
@ConfigurationProperties(prefix = "request.log")
public class LogProperties {
private Boolean enabled = Boolean.FALSE;
}
(5)编写日志拦截器/**
* 功能描述: 日志拦截器
* @author TuYong
* @date 2022/9/7 20:49
*/
@Slf4j
public class LogInterceptor implements HandlerInterceptor {
private static final ThreadLocal<Long> THREAD_LOCAL = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
RequestLog methodAnnotation = handlerMethod.getMethodAnnotation(RequestLog.class);
if(methodAnnotation != null){
long start = System.currentTimeMillis();
THREAD_LOCAL.set(start);
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
RequestLog methodAnnotation = handlerMethod.getMethodAnnotation(RequestLog.class);
if(methodAnnotation != null){
Method method = handlerMethod.getMethod();
String requestUri = request.getRequestURI();
String methodName = method.getDeclaringClass().getName()+":"+method.getName();
String desc = methodAnnotation.desc();
long end = System.currentTimeMillis();
long start = THREAD_LOCAL.get();
long l = end - start;
THREAD_LOCAL.remove();
log.info("请求路径:{},请求方法:{},描述信息:{},总计耗时:{}",requestUri,methodName,desc,l);
}
}
}
(6)编写自动配置类/**
* 功能描述: 自动配置
* @author TuYong
* @date 2022/9/7 20:55
*/
@Configuration
@EnableConfigurationProperties({LogProperties.class})
@ConditionalOnProperty(
prefix = "request.log",
name = {"enabled"},
havingValue = "true"
)
public class LogAutoConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor()).addPathPatterns("/api/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
(7)编写spring.factories在resources/META-INF/下建立spring.factories文件,配置自动装配类路径 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ cn.javaxxw.springboot.LogAutoConfiguration (8)创建starter演示工程引入starter依赖<dependencies>
<dependency>
<groupId>cn.javaxxw</groupId>
<artifactId>log-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
(9)编写测试接口并使用starter中定义的注解@RestController
@RequestMapping("api")
public class ApiController {
@GetMapping("test")
@RequestLog(desc = "测试接口")
public Object test(){
return "test api!";
}
}
(10)配置文件server:
port: 8080
# 开启starter组件
request:
log:
enabled: true
(11)功能测试通过请求测试接口,我们可以看到starter中的拦截器已经生效
(12)演示工程代码gitee: https://gitee.com/trazen/springboot-demo.git 3、原理解析第二章节中的开发流程,有两个地方需要我们了解一下: (1)配置类自动加载机制在SpringBoot的启动类都会加上?@SpringBootApplication?注解。这个注解会引入?@EnableAutoConfiguration?注解。然后?@EnableAutoConfiguration?会?@Import(AutoConfigurationImportSelector.class)?。 AutoConfigurationImportSelector.class?的?selectImports?方法最终会通过?SpringFactoriesLoader.loadFactoryNames?,加载?META-INF/spring.factories?里的?EnableAutoConfiguration?配置值,也就是我们上文中设置的资源文件。 (2)自动加载的智能化可配置化实际项目中,我们并不总是希望使用默认配置。比如有时候我想自己配置相关功能,或者只有某些bean没有被加载时才会加载starter配置类。这些常见的场景Starter都可以实现,并提供了如下的解决方案: @Conditional*注解 springboot starter提供了一系列的@Conditional*注解,代表什么时候启用对应的配置,具体的可以去查看springboot的官方文档。常用注解如下:
比如我们案例中的??@ConditionalOnProperty(prefix = "request.log", name = {"enabled"},havingValue = "true")?,只有在应用配置??request.log.enabled = true?时该请求日志拦截功能才会生效。 @ConfigurationProperties注解 这个注解主要是为了解决如下场景:我想要使用starter的默认配置类,但是又想对配置中的某些参数进行自定义配置。@ConfigurationProperties类就是做这个工作的。例如上述例子中,我们在配置中使用enabled参数来决定是否启动该组件的日志拦截功能。 |
|
|
|
|
| 上一篇文章 下一篇文章 查看所有文章 |
|
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
| 360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年12日历 | -2025/12/7 20:53:12- |
|
| 网站联系: qq:121756557 email:121756557@qq.com IT数码 |