Sabemos que SpringBoot Starter también es el iniciador. Es una gran ventaja de la creación de componentes de SpringBoot. Sobre la base de esta idea, sobre la base de esta idea, SpringBoot se ha vuelto muy poderoso, y el oficial nos proporciona muchos arrancadores listos para usar.
Spring Boot Starter es una característica importante de Spring Boot, que tiene las siguientes ventajas:
-
Administración de dependencias : Starter maneja automáticamente las dependencias del proyecto, de modo que los desarrolladores no necesitan agregar y administrar manualmente cada dependencia.
-
Configuración automática : Starter proporciona un método de configuración automática, que puede configurar automáticamente las aplicaciones de Spring de acuerdo con su classpath y las propiedades que defina.
-
Desarrollo simplificado : al proporcionar iniciadores de varios servicios (como base de datos, seguridad, caché, etc.), el proceso de desarrollo se simplifica enormemente.
-
Reduzca el código repetitivo : gracias a la configuración automática y la gestión de dependencias de Starter, los desarrolladores pueden centrarse en la lógica empresarial en lugar de la configuración y el código de infraestructura.
-
Creación rápida de prototipos : use Starter para crear rápidamente prototipos que funcionen.
-
Fácil de entender y usar : uno de los objetivos de diseño de Spring Boot Starter es permitir que los desarrolladores no profesionales comiencen rápidamente.
-
Apoyo de la comunidad : además de los Starters proporcionados oficialmente, también hay una gran cantidad de Starters proporcionados por la comunidad que pueden satisfacer diversas necesidades específicas.
Ahora le enseñaré cómo empaquetar su propio iniciador para hacer sus propios componentes springboot. Por supuesto, también puede publicar su propio iniciador en el almacén central de maven para que todos lo usen.
Análisis del propio Starter de SpringBoot
Tomemos como ejemplo la carga automática de WebMvcAutoConfiguration
Existe un requisito para que las clases de configuración automática puedan cargarse. El resultado del análisis del código fuente es que se debe realizar la siguiente configuración en \META-INF\spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
De esta manera, cuando se inicia SpringBoot, encontrará nuestra introducción, el iniciador encuentra \META-INF\spring.factories
el archivo de propiedades, encuentra la ruta de clase que debe cargarse y configurarse automáticamente, y luego lo inyecta automáticamente en el contenedor Spring IOC para nosotros, y nosotros puede usarlo directamente en el proyecto.
La carga automática aquí también depende de algunas anotaciones como:
@Configuration // 指定这个类是个配置类
@ConditionalOnXXX // 在指定条件成立的情况下自动配置类生效
@AutoConfigureOrder //配置类顺序
@AutoConfigureAfter // 在哪个配置类之后
@Bean //给容器中添加组件
@ConfigurationProperties //结合相关的XXXProperties类 来绑定相关的配置
@EnableConfigurationProperties // 让XXXProperties加入到容器中,别人就可以自动装配
Personaliza tu propio arrancador
Después de analizar el iniciador oficial de SpringBoot, personalizamos nuestro propio iniciador (lo copiamos)
Convenciones de nombres
consejos de configuración
Si en el archivo de propiedades personalizadas, se debe introducir el aviso inteligente de IDEA
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
definir arranque
Aquí tomo un iniciador SpringBoot que resume el paquete del proyecto ya que encapsulé y resumí mi trabajo como ejemplo.
<dependency>
<groupId>cn.soboys</groupId>
<artifactId>rest-api-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
Es el comienzo empaquetado por mí mismo. El repositorio central ha sido liberado.
Las características actuales de la versión actualizada 1.3.0 son las siguientes
- Admite la configuración con un solo clic para personalizar la devolución del formato uniforme de la API RestFull
- Admite la internacionalización de errores de la API RestFull
- Admite manejo de excepciones globales, procesamiento de verificación de parámetros globales
- Encapsulación de herramientas de afirmación de errores comerciales, siguiendo el principio de devolver los errores primero
- paquete de trabajo redis. Admite todas las herramientas de operación clave
- RestTemplate encapsula la herramienta de solicitud POST, GET
- Integración de registros. Personalice la ruta del registro, clasifíquelo según el nivel del registro, admita la compresión y la segmentación del tamaño del archivo. mostrar por tiempo
- La biblioteca de herramientas integra lombok, hutool, commons-lang3 y guava. No es necesario importarlos individualmente
- Generación de código mybatisPlus integrada con un solo clic
rest-api-spring-boot-starter
Dirección del almacén
github
- Archivo de propiedades de configuración personalizado
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: 请求资源不存在
- Definir clase de configuración de propiedad
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);
}
}
- Defina BeanAutoConfiguration para cargar automáticamente las clases de configuración
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();
}
}
}
- Autocableado
en proyecto
spring.factories
Configúrate para cargar la clase de configuración
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration,\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration.RestTemplateConfig,\
cn.soboys.restapispringbootstarter.utils.RedisTempUtil\
Ampliando el pensamiento, podemos ver que muchos de los estados oficiales de SpringBoot son similares a
@Enablexxx
las anotaciones
. Myrest-api-spring-boot-starter
1.3.0 ya se implementó y todas las funciones se pueden usar directamente en la clase de inicio o la clase de configuración sin configurar una línea en application.propertiesEnableRestFullApi
El uso perfecto del documento me puede ver
SpringBoot define un marco de respuesta de API Restful elegante y globalmente unificado Finaliza el capítulo Sprinkle Encapsula el componente de inicio
Este artículo
En este punto, la definición del iniciador está terminada y el siguiente paso es empaquetarlo y publicarlo en el almacén central de maven .
Continuaré compartiendo en el próximo artículo.
Deja tus pensamientos y presta atención a los programadores públicos durante tres horas
Continúe produciendo contenido de alta calidad y espero brindarle un poco de inspiración y ayuda.