| |
|
开发:
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图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 13:07:35- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |