共计 7656 个字符,预计需要花费 20 分钟才能阅读完成。
咱们晓得 SpringBoot Starter 也就是启动器。是 SpringBoot 组件化的一大长处。基于这个思维,基于这个思维 SpringBoot 才变得十分弱小,官网给咱们提供很多开箱即用的启动器。
Spring Boot Starter 是 Spring Boot 的一个重要个性,它有以下长处:
- 依赖治理:Starter 主动解决我的项目的依赖关系,使得开发者无需手动增加和治理每个依赖。
- 主动配置:Starter 提供了一种主动配置的形式,能够依据你的 classpath 和你定义的属性主动配置 Spring 利用。
- 简化开发:通过提供各种服务的 Starter(如数据库、平安、缓存等),极大地简化了开发过程。
- 缩小样板代码:因为 Starter 的主动配置和依赖治理,开发者能够专一于业务逻辑,而不是配置和基础设施代码。
- 疾速原型开发:应用 Starter 能够疾速创立可运行的原型。
- 易于了解和应用:Spring Boot Starter 的设计指标之一就是让非专业的开发者也能疾速上手。
- 社区反对:除了官网提供的 Starter,还有大量的社区提供的 Starter,能够满足各种特定需要。
我当初手把手教大家如何封装本人的starter 做本人的 springboot 组件,当然你也能够公布本人的starter 到 maven 地方仓库供大家应用
分析 SpringBoot 自带 Starter
咱们以 WebMvcAutoConfiguration 这个主动加载为例
主动配置类要能加载,有一个要求,源码剖析后果是,须要在 \META-INF\spring.factories 中做如下配置
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
这样 SpringBoot 在启动实现时候,会找到咱们引入,的starter 找到\META-INF\spring.factories
属性文件,找到须要主动加载配置的类门路,而后帮咱们主动注入到Spring IOC 容器,咱们在我的项目中就能够间接应用了。
这里实现主动加载还要依赖一些注解如:
@Configuration // 指定这个类是个配置类
@ConditionalOnXXX // 在指定条件成立的状况下主动配置类失效
@AutoConfigureOrder // 配置类程序
@AutoConfigureAfter // 在哪个配置类之后
@Bean // 给容器中增加组件
@ConfigurationProperties // 联合相干的 XXXProperties 类 来绑定相干的配置
@EnableConfigurationProperties // 让 XXXProperties 退出到容器中,他人就能够主动拆卸
自定义本人的 starter
分析了 SpringBoot 官网的 starter 咱们自定义本人的 starter,(咱们仿照着写)
命名标准
配置提醒
如果自定义属性文件中,须要 IDEA 智能提醒须要引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
定义 starter
这里我以本人封装总结我工作以来总结我的项目封装的一个 SpringBoot starter 为例
<dependency>
<groupId>cn.soboys</groupId>
<artifactId>rest-api-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
就是我本人封装的 start。曾经公布地方仓库。
目前更新版本 1.3.0 性能如下
- 反对一键配置自定义 RestFull API 对立格局返回
- 反对 RestFull API 谬误国际化
- 反对全局异样解决,全局参数验证解决
- 业务谬误断言工具封装,遵循谬误优先返回准则
- redis 工作封装。反对所有 key 操作工具
- RestTemplate 封装 POST,GET 申请工具
- 日志集成。自定义日志门路,依照日志等级分类,反对压缩和文件大小宰割。按工夫显示
- 工具库集成 集成了 lombok,hutool,commons-lang3,guava。不须要本人单个引入
- 集成 mybatisPlus 一键代码生成
rest-api-spring-boot-starter
仓库地址
github
- 自定义配置属性文件
rest-api:
enabled: false
logging:
path: ./logs
i18n:
# 若前端无 header 传参则返回中文信息
i18n-header: Lang
default-lang: cn
message:
# admin
internal_server_error:
en: Internal Server Error
cn: 零碎谬误
not_found:
en: Not Found
cn: 申请资源不存在
-
定义属性配置类
package cn.soboys.restapispringbootstarter.i18n; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import java.util.Map; import java.util.Optional; /** * @author 公众号 程序员三时 * @version 1.0 * @date 2023/6/26 11:55 * @webSite https://github.com/coder-amiao */ //@PropertySource(value = "classpath:i18n.yaml", factory = YamlPropertySourceFactory.class) @Configuration @ConfigurationProperties(prefix = "rest-api.i18n") @Data public class I18NMessage { /** * message-key:<lang:message> */ private Map<String, Map<String, String>> message; /** * Default language setting (Default "cn"). */ private String defaultLang = "cn"; private String i18nHeader = "Lang"; /** * get i18n message * * @param key * @param language * @return */ public String message(I18NKey key, String language) {return Optional.ofNullable(message.get(key.key())) .map(map -> map.get(language == null ? defaultLang : language)) .orElse(key.key()); } /** * get i18n message * * @param key * @param language * @return */ public String message(String key, String language) {return Optional.ofNullable(message.get(key)) .map(map -> map.get(language == null ? defaultLang : language)) .orElse(key); } }
- 定义 BeanAutoConfiguration 主动加载配置类
package cn.soboys.restapispringbootstarter.config;
import cn.soboys.restapispringbootstarter.ApplicationRunner;
import cn.soboys.restapispringbootstarter.ExceptionHandler;
import cn.soboys.restapispringbootstarter.ResultHandler;
import cn.soboys.restapispringbootstarter.aop.LimitAspect;
import cn.soboys.restapispringbootstarter.i18n.I18NMessage;
import cn.soboys.restapispringbootstarter.utils.RedisTempUtil;
import cn.soboys.restapispringbootstarter.utils.RestFulTemp;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.List;
/**
* @author 公众号 程序员三时
* @version 1.0
* @date 2023/6/27 11:36
* @webSite https://github.com/coder-amiao
*/
@Configuration
@ConditionalOnProperty(name = "rest-api.enabled", havingValue = "true")
public class BeanAutoConfiguration {
@Bean
public I18NMessage i18NMessage() {return new I18NMessage();
}
@Bean
public ResultHandler resultHandler() {return new ResultHandler();
}
@Bean
public ExceptionHandler exceptionHandler() {return new ExceptionHandler();
}
@Bean
public StartupApplicationListener startupApplicationListener() {return new StartupApplicationListener();
}
@Bean
public RestApiProperties restApiProperties() {return new RestApiProperties();
}
@Bean
public RestApiProperties.LoggingProperties loggingProperties(RestApiProperties restApiProperties) {return restApiProperties.new LoggingProperties();
}
@Bean
public ApplicationRunner applicationRunner() {return new ApplicationRunner();
}
/**
* restTemplate 主动注入
*/
@Configuration
@ConditionalOnProperty(name = "rest-api.enabled", havingValue = "true")
class RestTemplateConfig {
/**
* 第三方申请要求的默认编码
*/
private final Charset thirdRequest = Charset.forName("utf-8");
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {RestTemplate restTemplate = new RestTemplate(factory);
// 解决申请中文乱码问题
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> messageConverter : messageConverters) {if (messageConverter instanceof StringHttpMessageConverter) {((StringHttpMessageConverter) messageConverter).setDefaultCharset(thirdRequest);
}
if (messageConverter instanceof MappingJackson2HttpMessageConverter) {((MappingJackson2HttpMessageConverter) messageConverter).setDefaultCharset(thirdRequest);
}
if (messageConverter instanceof AllEncompassingFormHttpMessageConverter) {((AllEncompassingFormHttpMessageConverter) messageConverter).setCharset(thirdRequest);
}
}
return restTemplate;
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(15000);
factory.setReadTimeout(5000);
return factory;
}
@Bean
public RestFulTemp restFulTemp() {return new RestFulTemp();
}
}
}
- 主动拆卸
在我的项目
spring.factories
配置本人加载配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration,\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration.RestTemplateConfig,\
cn.soboys.restapispringbootstarter.utils.RedisTempUtil\
扩大思考, 咱们能够看到 SpringBoot 官网 stater 很多启用都相似
@Enablexxx
注解
这个怎么实现。我的rest-api-spring-boot-starter
1.3.0 曾经实现不须要在application.properties 配置一行 间接在启动类或者配置类应用EnableRestFullApi
就能够应用全副性能
欠缺文档应用能够看我
SpringBoot 定义优雅全局对立 Restful API 响应框架完结撒花篇封装 starter 组件
这篇文章
到此本人定义 starter 就写完了 接下来就是打包,公布到maven 地方仓库。
我会在 下一篇文章持续分享
留下你的思考,关注公众 程序员三时
继续输入优质内容 心愿给你带来一点启发和帮忙