Ensine como personalizar sua própria análise de código-fonte do componente SpringBoot Starter

Sabemos que o SpringBoot Starter também é o iniciador. É uma grande vantagem da componentização do SpringBoot. Com base nessa ideia, com base nessa ideia, o SpringBoot se tornou muito poderoso, e o oficial nos fornece muitos iniciantes prontos para uso.

O Spring Boot Starter é um recurso importante do Spring Boot, que possui as seguintes vantagens:

  1. Gerenciamento de dependências : O Starter lida automaticamente com as dependências do projeto, para que os desenvolvedores não precisem adicionar e gerenciar manualmente cada dependência.

  2. Configuração automática : O Starter fornece um método de configuração automática, que pode configurar automaticamente os aplicativos Spring de acordo com seu caminho de classe e as propriedades definidas por você.

  3. Desenvolvimento simplificado : Ao fornecer iniciadores de vários serviços (como banco de dados, segurança, cache, etc.), o processo de desenvolvimento é bastante simplificado.

  4. Reduza o código clichê : graças à configuração automática e ao gerenciamento de dependências do Starter, os desenvolvedores podem se concentrar na lógica de negócios em vez da configuração e do código de infraestrutura.

  5. Prototipagem rápida : Use o Starter para criar rapidamente protótipos funcionais.

  6. Fácil de entender e usar : um dos objetivos de design do Spring Boot Starter é permitir que desenvolvedores não profissionais comecem rapidamente.

  7. Apoio da comunidade : Além dos Starters fornecidos oficialmente, há também um grande número de Starters fornecidos pela comunidade que podem atender a várias necessidades específicas.

Agora vou ensiná-lo a empacotar seu próprio iniciador para criar seus próprios componentes springboot. Claro, você também pode publicar seu próprio iniciador no armazém central do maven para que todos possam usar.

Análise do próprio Starter do SpringBoot

Vamos pegar o carregamento automático do WebMvcAutoConfiguration como exemplo

Existe um requisito para que as classes de configuração automática possam ser carregadas. O resultado da análise do código-fonte é que a seguinte configuração precisa ser feita em \META-INF\spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

Dessa forma, quando o SpringBoot for iniciado, ele encontrará nossa introdução, o iniciador encontrará \META-INF\spring.factorieso arquivo de propriedades, encontrará o caminho de classe que precisa ser carregado e configurado automaticamente e, em seguida, o injetará automaticamente no contêiner Spring IOC para nós e nós pode usá-lo diretamente no projeto.

O carregamento automático aqui também depende de algumas anotações como:

@Configuration // 指定这个类是个配置类
@ConditionalOnXXX // 在指定条件成立的情况下自动配置类生效
@AutoConfigureOrder //配置类顺序
@AutoConfigureAfter // 在哪个配置类之后
@Bean //给容器中添加组件

@ConfigurationProperties //结合相关的XXXProperties类 来绑定相关的配置
@EnableConfigurationProperties // 让XXXProperties加入到容器中,别人就可以自动装配

Personalize seu próprio iniciador

Depois de analisar o starter oficial do SpringBoot, customizamos nosso próprio starter, (copiamos)

Convenções de nomenclatura

dicas de configuração

Se estiver no arquivo de propriedades personalizadas, o prompt inteligente IDEA precisa ser introduzido

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

definir iniciador

Aqui eu pego um iniciador do SpringBoot que resume o pacote do projeto desde que encapsulei e resumi meu trabalho como um exemplo.

 <dependency>
            <groupId>cn.soboys</groupId>
            <artifactId>rest-api-spring-boot-starter</artifactId>
            <version>1.2.0</version>
        </dependency>

É o início embalado por mim. O repositório central foi liberado.

Os recursos atualizados da versão 1.3.0 atual são os seguintes

  1. Suporte à configuração com um clique para personalizar o retorno do formato uniforme da API RestFull
  2. Suporte à internacionalização de erros da API RestFull
  3. Suporta manipulação de exceção global, processamento de verificação de parâmetro global
  4. Encapsulamento de ferramentas de asserção de erros de negócios, seguindo o princípio de retornar erros primeiro
  5. pacote de trabalho redis. Suporta todas as principais ferramentas de operação
  6. RestTemplate encapsula a ferramenta de solicitação POST e GET
  7. Integração de log. Personalize o caminho de log, classifique de acordo com o nível de log, suporte a compactação e segmentação de tamanho de arquivo. exibir por tempo
  8. A biblioteca de ferramentas integra lombok, hutool, commons-lang3 e goiaba. Não há necessidade de importá-los individualmente
  9. Geração de código de um clique mybatisPlus integrada

rest-api-spring-boot-starter
Endereço do depósito
github

  1. Arquivo de propriedades de configuração customizado
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: 请求资源不存在

  1. Definir classe de configuração de propriedade
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);
    }

}

  1. Defina BeanAutoConfiguration para carregar automaticamente as classes de configuração
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();
        }

    }

}
  1. Autoligação
    no projeto

spring.factoriesConfigure-se para carregar a classe de configuração

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration,\
cn.soboys.restapispringbootstarter.config.BeanAutoConfiguration.RestTemplateConfig,\
cn.soboys.restapispringbootstarter.utils.RedisTempUtil\

Expandindo o pensamento, podemos ver que muitos dos estados oficiais do SpringBoot são semelhantes a @Enablexxxanotações.
Como conseguir isso. Meu rest-api-spring-boot-starter1.3.0 já foi implementado, e todas as funções podem ser usadas diretamente na classe de inicialização ou classe de configuração sem configurar uma linha em application.propertiesEnableRestFullApi

O uso perfeito de documentos pode me ver

SpringBoot define uma estrutura de resposta de API Restful elegante e globalmente unificada Termina o capítulo Sprinkle Encapsula o componente inicial

Este artigo

Neste ponto, a definição do iniciador está concluída e a próxima etapa é empacotá-lo e publicá-lo no maven central warehouse .

Vou continuar a compartilhar no próximo artigo

Deixe seus pensamentos e preste atenção aos programadores públicos por três horas

Continue a produzir conteúdo de alta qualidade e espero trazer um pouco de inspiração e ajuda

Acho que você gosta

Origin blog.csdn.net/u011738045/article/details/131589843
Recomendado
Clasificación