一、创建
我们之前的文章自定义了 archetype , 这个是很重要的步骤哦 ,不理解的可以先看:(十二)Alian 的 Spring Cloud 自定义Archetype,然后又自动生成接口API,其实有了这些基础,这章就很简单了。我们知道在微服务中有很多的服务,每个服务都要去创建 domain 和 project ,可能都由不同的人开发,就可能出现整个项目规范不一致或者创建一堆东西很繁琐,本文主要就是为解决这个问题。为了简便,我们还是在文档服务中心修改。
1.1、第一步
二、mvn命令
mvn语法结构
mvn archetype:generate \
-DarchetypeGroupId=<archetype-groupId> \
-DarchetypeArtifactId=<archetype-artifactId> \
-DarchetypeVersion=<archetype-version> \
-DinteractiveMode=<interactiveMode> \
-DarchetypeCatalog=<archetype-catalog> \
-DgroupId=<groupId> \
-DartifactId=<artifactId> \
-Dversion=<version> \
-Dpackage=<package>
三、生成项目
3.1、配置
继续改进我们的文档服务中心,增加生成项目的接口,数据库配置如下:
3.1、属性配置
AppProperties.java
package cn.alian.microservice.doc.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
@Data
@RefreshScope
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String mvn;
private String swaggerTemplatePath;
private String swaggerJarPath;
private String configUri;
private String remoteRepositories;
private String tmpDir;
private Gav domain;
private Gav project;
@Data
public static class Gav{
private String groupId;
private String artifactId;
private String version;
private String packaging;
}
}
具体的配置值,在我上面的截图里都有。不要后面用到的时候,这个参数是什么,这些都是在配置中心配置的。
3.2、控制层
CreateProjectController.java
package cn.alian.microservice.doc.controller;
import cn.alian.microservice.common.dto.ApiResponseDto;
import cn.alian.microservice.doc.service.GenerateProjectService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RequestMapping("api/v1/project")
@Api(description = "创建项目")
@RestController
public class CreateProjectController {
@Autowired
private GenerateProjectService generateProjectService;
@ApiOperation(value = "生成项目", notes = "生成项目")
@GetMapping(value = "/generate")
public synchronized Object generateProject(
@ApiParam(example = "cn.alian.mall"") @RequestParam String groupId,
@ApiParam(example = "user") @RequestParam String artifactId,
@ApiParam(example = "1.0.0-SNAPSHOT") @RequestParam String version) throws Exception {
log.info("请求的参数: groupId = [" + groupId + "], artifactId = [" + artifactId + "], version = [" + version + "]");
//参数判断
if (StringUtils.isAnyBlank(groupId, artifactId, version)) {
return ApiResponseDto.fail("无效的参数");
}
return generateProjectService.generateProject(groupId, artifactId, version);
}
}
3.3、服务层
GenerateProjectService.java
package cn.alian.microservice.doc.service;
import cn.alian.microservice.common.dto.ApiResponseDto;
import cn.alian.microservice.doc.config.AppProperties;
import cn.alian.microservice.doc.utils.CmdUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
@Slf4j
@Service
public class GenerateProjectService extends BaseService{
@Autowired
private AppProperties appProperties;
public Object generateProject(String groupId, String artifactId, String version) throws Exception{
//获取java临时目录
File tmpDir = SystemUtils.getJavaIoTmpDir();
//项目生成的目录
String outputDir = tmpDir.getAbsolutePath() + File.separator + artifactId + System.currentTimeMillis();
log.info("项目生成的目录:{}", outputDir);
//domain生成目录
String domainOutputDir = outputDir + File.separator + this.appProperties.getDomain().getArtifactId();
log.info("domain生成目录:{}", domainOutputDir);
//生成domain
boolean generateDomain = generate(groupId, artifactId, version, this.appProperties.getDomain(), domainOutputDir);
if (!generateDomain) {
return ApiResponseDto.fail("生成domain工程失败");
}
//domain压缩包目录
String toZipDomainDir = outputDir + File.separator + "domain-" + artifactId;
log.info("domain压缩包目录:{}", toZipDomainDir);
//domain工程的文件拷贝到domain压缩包目录
FileUtils.copyDirectory(new File(domainOutputDir + File.separator + artifactId), new File(toZipDomainDir));
//project生成目录
String projectOutputDir = outputDir + File.separator + this.appProperties.getProject().getArtifactId();
log.info("project生成目录:{}", projectOutputDir);
//生成project
boolean generateProject = generate(groupId, artifactId, version, this.appProperties.getProject(), projectOutputDir);
if (!generateProject) {
return ApiResponseDto.fail("生成domain工程失败");
}
//project压缩包目录
String toZipProjectDir = outputDir + File.separator + artifactId;
log.info("project压缩包目录:{}", toZipProjectDir);
//project工程的文件拷贝到project压缩包目录
FileUtils.copyDirectory(new File(projectOutputDir + File.separator + artifactId), new File(toZipProjectDir));
//压缩包文件
String outputZip = outputDir + ".zip";
//把两个工程文件,压缩到压缩包并返回
return generateZipReponse(outputZip, artifactId + "-" + version, toZipDomainDir, toZipProjectDir);
}
private boolean generate(String groupId, String artifactId, String version, AppProperties.Gav gav, String outputDir) throws Exception {
log.info("generate groupId = [" + groupId + "], artifactId = [" + artifactId + "], version = [" + version + "], gav = [" + gav + "]");
//获取mvn依赖的cmd
String mvnDependencyCmd = CmdUtil.getMvnDependencyCmd(appProperties.getMvn(), appProperties.getRemoteRepositories(), gav);
//执行获取mvn依赖命令
Process exec = Runtime.getRuntime().exec(mvnDependencyCmd);
//打印结果
printProcess(exec);
//获取生成项目的cmd
String generateProjectCmd = CmdUtil.getGenerateProjectCmd(appProperties.getMvn(), groupId, artifactId, version, gav, outputDir, appProperties.getConfigUri());
//执行生成项目cmd命令
Process process = Runtime.getRuntime().exec(generateProjectCmd);
//返回结果
return printProcess(process);
}
}
大致的步骤:
- 定义好临时生成目录及要生成两个工程的目录
- 生成的domain和project,这里或获取相关依赖,然后调用响应cmd命令(具体的命令在我之前的文章(十三)Alian 的 Spring Cloud 生成接口调用(swagger codegen) 的 BaseService.java 中),把生成的文件拷贝到要压缩的目录
- 把压缩目录中的文件压缩返回给客户端
四、验证
4.1、请求生成项目
输入参数:
- groupId :cn.alian.mall
- artifactId :user
- version :1.0.0-SNAPSHOT
4.2、生成项目结果
执行结果:
4.3、项目结构
相对来说还是比较方便的,对一个大的团队来说,还是蛮有必要的,如果大家都是手动创建,难免规范不一致。