基于spring-initializr的脚手架项目定制

10 篇文章 0 订阅
5 篇文章 0 订阅

文档资料和参考

https://docs.spring.io/initializr/docs/current/reference/html/

这是一个用于快速生成spring项目的工程,从github下载源码即可运行https://github.com/spring-io/start.spring.io/tree/main/start-site/src,运行效果:https://start.spring.io/

 页面渲染所需要的数据源修改非常简单,只需要修改application.yml配置文件即可.

项目主要接口有两个,位于:依赖项io.spring.initializr:initializr-web的jar包中.

分别是位于ProjectGenerationController类的"/starter.zip"和位于ProjectMetadataController类的"/metadata/client"

@RequestMapping("/starter.zip")
public ResponseEntity<byte[]> springZip(R request) throws IOException {
   ProjectGenerationResult result = this.projectGenerationInvoker.invokeProjectStructureGeneration(request);
   Path archive = createArchive(result, "zip", ZipArchiveOutputStream::new, ZipArchiveEntry::new,
         ZipArchiveEntry::setUnixMode);
   return upload(archive, result.getRootDirectory(), generateFileName(request, "zip"), "application/zip");
}
@RequestMapping(path = { "/", "/metadata/client" }, produces = { "application/vnd.initializr.v2.2+json" })
public ResponseEntity<String> serviceCapabilitiesV22() {
   return serviceCapabilitiesFor(InitializrMetadataVersion.V2_2);
}

1.数据源通过InitializrAutoConfiguration类加载配置文件到源数据的InitializrProperties配置类

@Configuration
@EnableConfigurationProperties(InitializrProperties.class)
@AutoConfigureAfter({ JacksonAutoConfiguration.class, RestTemplateAutoConfiguration.class })
public class InitializrAutoConfiguration {

2.当打包请求发出后,会根据用户request和加载到的源数据去生成项目描述ProjectDescription

public ProjectGenerationResult invokeProjectStructureGeneration(R request) {
   //配置文件加载后的源数据
   InitializrMetadata metadata = this.parentApplicationContext.getBean(InitializrMetadataProvider.class).get();
   try {
      //根据配置文件生成的源数据
      ProjectDescription description = this.requestConverter.convert(request, metadata);
      ProjectGenerator projectGenerator = new ProjectGenerator((
            projectGenerationContext) -> customizeProjectGenerationContext(projectGenerationContext, metadata));
      //文件生成
      ProjectGenerationResult result = projectGenerator.generate(description,
            generateProject(description, request));
      addTempFile(result.getRootDirectory(), result.getRootDirectory());
      return result;
   }
   catch (ProjectGenerationException ex) {
      publishProjectFailedEvent(request, metadata, ex);
      throw ex;
   }
}
因为ProjectGenerationController是被@ConditionalOnMissingBean修饰的,所以可以通过@Bean的方式,重写这个类实现自定义入参到项目描述ProjectDescription的转换

3.自定义application配置文件,pom文件或者代码生成方式有很多,pom文件我使用的是实现BuildCustomizer<Build>接口,重写其中的customize(Build build)方法,代码我通过模板去实现,

配置文件通过去覆盖io.spring.initializr.generator.spring.configuration包下的类去实现自己想要的效果(原本的扩展太好)

以swagger为例:加载顺序为spring.factories-->DependencyProjectGenerationConfiguration -->SwaggerBuildCustomizer

 

@ProjectGenerationConfiguration
public class DependencyProjectGenerationConfiguration {
@Bean
@ConditionalOnRequestedDependency("swagger")
public SwaggerBuildCustomizer springSwaggerBuildCustomizer(ProjectDescription description,
      TemplateRenderer templateRenderer) {
   return new SwaggerBuildCustomizer(description, templateRenderer);
}

}

@Log4j2
public class SwaggerBuildCustomizer implements BuildCustomizer<Build>, ProjectContributor {

   private final CustomMutableProjectDescription description;

   private final TemplateRenderer templateRenderer;

   private final String SOURCE_PATH = "src/main/java/";

   @Override
   public void customize(Build build) {
      if (build.dependencies().has("swagger")) {
         build.dependencies().add("swagger-ui", Dependency.withCoordinates("io.springfox", "springfox-swagger-ui")
               .version(build.dependencies().get("swagger").getVersion()));
      }
   }

   @Override
   public int getOrder() {
      return BuildCustomizer.super.getOrder();
   }

   public SwaggerBuildCustomizer(ProjectDescription description, TemplateRenderer templateRenderer) {
      this.description = (CustomMutableProjectDescription) description;
      this.templateRenderer = templateRenderer;
   }

   @Override
   public void contribute(Path projectRoot) throws IOException {
      log.info("swagger 扩展加载");
      Map<String, Object> data = new HashMap<>();
      
      String groupId = description.getGroupId();
      String artifactId = description.getArtifactId();
      String pre = SOURCE_PATH + groupId.replace(".", "/") + "/" + artifactId;
      data.put("groupId", groupId);
      data.put("artifactId", artifactId);
      data.put("package", groupId + "." + artifactId);
      data.put("description", description.getSwaggerParams().getDescription());
      data.put("title", description.getSwaggerParams().getTitle());
      data.put("version", description.getSwaggerParams().getVersion());

      Files.createDirectories(projectRoot.resolve(pre + "/config/"));
      Path codeFile = Files.createFile(projectRoot.resolve(pre + "/config/SwaggerConfig.java"));
      String code = this.templateRenderer.render("SwaggerConfig.java", data);
      try (PrintWriter codeWriter = new PrintWriter(Files.newBufferedWriter(codeFile));) {
         codeWriter.print(code);
      }
   }

}
package {{package}}.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket customDocket(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors
                        .basePackage("{{package}}"))
                .paths(PathSelectors.any()).build();
    }

    private ApiInfo apiInfo(){
        Contact contact = new Contact("author",
                "https://confluence.enncloud.cn/#all-updates",
                "author@ennew.cn");
        return new ApiInfoBuilder()
                .title("{{title}}")
                .description("{{description}}")
                .contact(contact)
                .version("{{version}}")
                .build();
    }
}

 application配置文件自定义扩展核心类如下,我是根据io.spring.initializr.generator.spring.scm.git包下的逻辑进行重写的

 

@ProjectGenerationConfiguration
public class ApplicationConfigurationProjectGenerationConfiguration {
    public ApplicationConfigurationProjectGenerationConfiguration() {
    }

    @Bean
    public ApplicationPropertiesContributor applicationPropertiesContributor(ApplicationProperties properties) {
        return new ApplicationPropertiesContributor(properties);
    }

    @Bean
    public WebFoldersContributor webFoldersContributor(Build build, InitializrMetadata metadata) {
        return new WebFoldersContributor(build, metadata);
    }

    @Bean
    public ApplicationProperties applicationProperties(ObjectProvider<ApplicationPropertiesCustomizer> applicationPropertiesCustomizers) {
        ApplicationProperties applicationProperties = this.createApplicationProperties();
        applicationPropertiesCustomizers.orderedStream().forEach((customizer) -> {
            customizer.customize(applicationProperties);
        });
        return applicationProperties;
    }

    private ApplicationProperties createApplicationProperties() {
        ApplicationProperties applicationProperties = new ApplicationProperties();
        Map stringConfig = new HashMap<String ,String>();
        stringConfig.put("server.port","8080");
        applicationProperties.getSpring().add(stringConfig);
        return applicationProperties;
    }
}

4.其他自定义:

plugins自定义:实现implements BuildCustomizer<MavenBuild>接口

重写:

@Override
public void customize(MavenBuild build) {
   if (build.dependencies().has("myBatisGenerator")){
      build.dependencies().remove("myBatisGenerator");
      build.plugins().add("org.mybatis.generator",
            "mybatis-generator-maven-plugin",(plugin) -> plugin
                  .dependency("mysql","mysql-connector-java","${mysql.version}"));
   }
}

主类自定义注解:实现implements MainApplicationTypeCustomizer接口

重写:

@Override
public void customize(TypeDeclaration typeDeclaration) {
   String groupId = description.getGroupId();
   String artifactId = description.getArtifactId();
   String path = groupId + "." + artifactId;
   String value = path+".dao";
   Annotation annotation =Annotation.name("org.mybatis.spring.annotation.MapperScan",
         (ann) -> ann.attribute("basePackages",String.class,value));
   typeDeclaration.annotate(annotation);
}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Spring Initializr是一个由Spring官方提供的快速创建Spring项目脚手架工具。它可以帮助开发者快速创建项目,并提供了可视的界面来选择项目的构建工具、打包方式、Spring版本、语言等。使用Spring Initializr,开发者可以省去手动创建项目和添加集成配置项的繁琐步骤,简项目的搭建过程。 你可以通过访问Spring官网(https://spring.io/)或者GitHub上的Spring Initializr项目(https://github.com/spring-io/initializr/)来获取更多关于Spring Initializr的详细信息和文档。在Spring Initializr的界面上,你可以直接创建项目,并选择适合你的配置项,然后进行打包和下载。如果在使用过程中遇到问题,你可以通过在GitHub上提交ISSUE或在公众号「杨同学technotes」后台留言来寻求帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Spring Initializr](https://blog.csdn.net/qq_26012495/article/details/129227034)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [spring initializr脚手架搭建详解](https://blog.csdn.net/BASK2311/article/details/128092245)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值