代码生成功能

This commit is contained in:
2023-09-11 23:38:40 +08:00
parent bb0a38ebb4
commit b7aed0784e
3 changed files with 354 additions and 3 deletions

10
pom.xml
View File

@@ -107,6 +107,11 @@
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>
<dependencies> <dependencies>
<dependency>
<groupId>com.squareup</groupId>
<artifactId>javapoet</artifactId>
<version>1.13.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.groovy/groovy --> <!-- https://mvnrepository.com/artifact/org.apache.groovy/groovy -->
<dependency> <dependency>
<groupId>org.apache.groovy</groupId> <groupId>org.apache.groovy</groupId>
@@ -122,6 +127,11 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.1-jre</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId> <artifactId>spring-boot-starter-aop</artifactId>

View File

@@ -0,0 +1,341 @@
package cn.lihongjie.coal;
import cn.lihongjie.coal.annotation.OrgScope;
import cn.lihongjie.coal.annotation.SysLog;
import cn.lihongjie.coal.base.dao.BaseRepository;
import cn.lihongjie.coal.base.dto.CommonDto;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import cn.lihongjie.coal.base.entity.CommonEntity;
import cn.lihongjie.coal.base.entity.OrgCommonEntity;
import cn.lihongjie.coal.base.mapper.BaseMapper;
import cn.lihongjie.coal.base.mapper.CommonMapper;
import cn.lihongjie.coal.base.service.BaseService;
import com.google.common.base.CaseFormat;
import com.squareup.javapoet.*;
import jakarta.persistence.Entity;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.control.DeepClone;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.lang.model.element.Modifier;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Scanner;
public class Codegen {
public static final Path DIRECTORY = Path.of("src/main/java/");
@SneakyThrows
public static void main(String[] args) {
System.out.print("请输入模块名:");
String moduleName = new Scanner(System.in).nextLine();
System.out.print("请输入模块中文名:");
String moduleCNName = new Scanner(System.in).nextLine();
System.out.print("机构数据[Y]:");
boolean orgMode = Objects.equals(StringUtils.defaultIfBlank(new Scanner(System.in).nextLine(), "Y"), "Y");
String lModuleName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, moduleName);
String prefix = Codegen.class.getPackage().getName() + "." + lModuleName;
String entityPackage = prefix + ".entity";
String dtoPackage = prefix + ".dto";
String repoPackage = prefix + ".repository";
String mapperPackage = prefix + ".mapper";
String servicePackage = prefix + ".service";
String controllerPackage = prefix + ".controller";
// 生成entity
TypeSpec entity = TypeSpec.classBuilder(StringUtils.capitalize(moduleName) + "Entity")
.addModifiers(Modifier.PUBLIC)
.superclass(orgMode ? OrgCommonEntity.class: CommonEntity.class)
.addAnnotation(Data.class)
.addAnnotation(Entity.class)
.build();
JavaFile.builder(entityPackage, entity)
.build()
.writeTo(DIRECTORY);
// 生成dto
TypeSpec dto = TypeSpec.classBuilder(StringUtils.capitalize(moduleName) + "Dto")
.addModifiers(Modifier.PUBLIC)
.superclass(orgMode ? OrgCommonDto.class:CommonDto.class)
.addAnnotation(Data.class)
.build();
JavaFile.builder(dtoPackage, dto)
.build()
.writeTo(DIRECTORY);
// 生成createDto
TypeSpec createDto = TypeSpec.classBuilder("Create" + StringUtils.capitalize(moduleName) + "Dto")
.addModifiers(Modifier.PUBLIC)
.superclass(orgMode ? OrgCommonDto.class:CommonDto.class)
.addAnnotation(Data.class)
.build();
JavaFile.builder(dtoPackage, createDto)
.build()
.writeTo(DIRECTORY);
// 生成updateDto
TypeSpec updateDto = TypeSpec.classBuilder("Update" + StringUtils.capitalize(moduleName) + "Dto")
.addModifiers(Modifier.PUBLIC)
.superclass(orgMode ? OrgCommonDto.class:CommonDto.class)
.addAnnotation(Data.class)
.build();
JavaFile.builder(dtoPackage, updateDto)
.build()
.writeTo(DIRECTORY);
// 生成repository
TypeSpec repository = TypeSpec.interfaceBuilder(StringUtils.capitalize(moduleName) + "Repository")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Repository.class)
.addSuperinterface(ParameterizedTypeName.get(ClassName.get(BaseRepository.class), ClassName.get(entityPackage, entity.name)))
.build();
JavaFile.builder(repoPackage, repository)
.build()
.writeTo(DIRECTORY);
// 生成mapper
TypeSpec mapper = TypeSpec.interfaceBuilder(StringUtils.capitalize(moduleName) + "Mapper")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(AnnotationSpec.builder(Mapper.class)
.addMember("componentModel", "org.mapstruct.MappingConstants.ComponentModel.SPRING", "")
.addMember("uses", "{$T.class}", CommonMapper.class)
.addMember("mappingControl", "$T.class", DeepClone.class)
.build())
.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(BaseMapper.class),
ClassName.get(entityPackage, entity.name),
ClassName.get(dtoPackage, dto.name),
ClassName.get(dtoPackage, createDto.name),
ClassName.get(dtoPackage, updateDto.name)
)
)
.build();
JavaFile.builder(mapperPackage, mapper)
.build()
.writeTo(DIRECTORY);
// 生成service
TypeSpec service = TypeSpec.classBuilder(StringUtils.capitalize(moduleName) + "Service")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Service.class)
.addAnnotation(Slf4j.class)
.superclass(ParameterizedTypeName.get(
ClassName.get(BaseService.class),
ClassName.get(entityPackage, entity.name),
ClassName.get(repoPackage, repository.name)
)
)
.addField(FieldSpec.builder(ClassName.get(repoPackage, repository.name), "repository", Modifier.PRIVATE).addAnnotation(Autowired.class).build())
.addField(FieldSpec.builder(ClassName.get(mapperPackage, mapper.name), "mapper", Modifier.PRIVATE).addAnnotation(Autowired.class).build())
.addField(FieldSpec.builder(ClassName.get(ConversionService.class), "conversionService", Modifier.PRIVATE).addAnnotation(Autowired.class).build())
.addMethod(MethodSpec.methodBuilder("create")
.addModifiers(Modifier.PUBLIC)
.returns(ClassName.get(dtoPackage, dto.name))
.addParameter(ClassName.get(dtoPackage, createDto.name), "request")
.addStatement("""
$T entity = mapper.toEntity(request);
this.repository.save(entity);
return getById(entity.getId())
""", ClassName.get(entityPackage, entity.name))
.build()
)
.addMethod(MethodSpec.methodBuilder("update")
.addModifiers(Modifier.PUBLIC)
.returns(ClassName.get(dtoPackage, dto.name))
.addParameter(ClassName.get(dtoPackage, updateDto.name), "request")
.addStatement("""
$T entity = this.repository.get(request.getId());
this.mapper.updateEntity(entity, request);
this.repository.save(entity);
return getById(entity.getId())
""", ClassName.get(entityPackage, entity.name))
.build()
)
.addMethod(MethodSpec.methodBuilder("delete")
.addModifiers(Modifier.PUBLIC)
.returns(void.class)
.addParameter(ClassName.get(IdRequest.class), "request")
.addStatement("""
this.repository.deleteAllById(request.getIds())
""")
.build()
)
.addMethod(MethodSpec.methodBuilder("getById")
.addModifiers(Modifier.PUBLIC)
.returns(ClassName.get(dtoPackage, dto.name))
.addParameter(ClassName.get(String.class), "id")
.addStatement("""
$T entity = repository.get(id);
return mapper.toDto(entity)
""", ClassName.get(entityPackage, entity.name))
.build()
)
.addMethod(MethodSpec.methodBuilder("list")
.addModifiers(Modifier.PUBLIC)
.returns(ParameterizedTypeName.get(ClassName.get(Page.class), ClassName.get(dtoPackage, dto.name)))
.addParameter(ClassName.get(CommonQuery.class), "query")
.addStatement(
"""
$T<$T> page = repository.findAll(query.specification(conversionService), $T.of(query.getPageNo(), query.getPageSize(), $T.by(query.getOrders())));
return page.map(this.mapper::toDto)
""", ClassName.get(Page.class),ClassName.get(entityPackage, entity.name), ClassName.get(PageRequest.class), ClassName.get(Sort.class))
.build()
)
.build();
JavaFile.builder(servicePackage, service)
.build()
.writeTo(DIRECTORY);
// 生成controller
TypeSpec controller = TypeSpec.classBuilder(StringUtils.capitalize(moduleName) + "Controller")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(RestController.class)
.addAnnotation(AnnotationSpec.builder(RequestMapping.class).addMember("value", "$S", "/" + lModuleName).build())
.addAnnotation(AnnotationSpec.builder(SysLog.class).addMember("module", "$S", StringUtils.defaultIfBlank(moduleCNName, "")).build())
.addAnnotation(Slf4j.class)
.addAnnotation(orgMode ? OrgScope.class : Slf4j.class)
.addField(FieldSpec.builder(ClassName.get(servicePackage, service.name), "service", Modifier.PRIVATE).addAnnotation(Autowired.class).build())
.addMethod(MethodSpec.methodBuilder("create")
.addModifiers(Modifier.PUBLIC)
.returns(ClassName.get(dtoPackage, dto.name))
.addAnnotation(AnnotationSpec.builder(PostMapping.class).addMember("value", "$S", "/create").build())
.addParameter(ParameterSpec.builder(ClassName.get(dtoPackage, createDto.name), "request").addAnnotation(RequestBody.class).build())
.addStatement("""
return this.service.create(request)
""")
.build()
)
.addMethod(MethodSpec.methodBuilder("update")
.addModifiers(Modifier.PUBLIC)
.returns(ClassName.get(dtoPackage, dto.name))
.addAnnotation(AnnotationSpec.builder(PostMapping.class).addMember("value", "$S", "/update").build())
.addParameter(ParameterSpec.builder(ClassName.get(dtoPackage, updateDto.name), "request").addAnnotation(RequestBody.class).build())
.addStatement("""
return this.service.update(request)
""")
.build()
)
.addMethod(MethodSpec.methodBuilder("delete")
.addModifiers(Modifier.PUBLIC)
.returns(Object.class)
.addAnnotation(AnnotationSpec.builder(PostMapping.class).addMember("value", "$S", "/delete").build())
.addParameter(ParameterSpec.builder(ClassName.get(IdRequest.class), "request").addAnnotation(RequestBody.class).build())
.addStatement("""
this.service.delete(request);
return true
""")
.build()
)
.addMethod(MethodSpec.methodBuilder("getById")
.addModifiers(Modifier.PUBLIC)
.returns(ClassName.get(dtoPackage, dto.name))
.addParameter(ParameterSpec.builder(ClassName.get(String.class), "request").addAnnotation(RequestBody.class).build())
.addStatement("""
return this.service.getById(request)
""")
.build()
)
.addMethod(MethodSpec.methodBuilder("list")
.addModifiers(Modifier.PUBLIC)
.returns(ParameterizedTypeName.get(ClassName.get(Page.class), ClassName.get(dtoPackage, dto.name)))
.addParameter( ParameterSpec.builder(ClassName.get(CommonQuery.class), "request").addAnnotation(RequestBody.class).build() )
.addStatement(
"""
return this.service.list(request)
""", ClassName.get(Page.class), ClassName.get(entityPackage, entity.name), ClassName.get(PageRequest.class), ClassName.get(Sort.class))
.build()
)
.build();
JavaFile.builder(controllerPackage, controller)
.build()
.writeTo(DIRECTORY);
}
}

View File

@@ -8,12 +8,12 @@ import cn.lihongjie.coal.supplier.dto.SupplierDto;
import cn.lihongjie.coal.supplier.dto.UpdateSupplierDto; import cn.lihongjie.coal.supplier.dto.UpdateSupplierDto;
import cn.lihongjie.coal.supplier.entity.SupplierEntity; import cn.lihongjie.coal.supplier.entity.SupplierEntity;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.MappingTarget;
import org.mapstruct.control.DeepClone; import org.mapstruct.control.DeepClone;
import static org.mapstruct.MappingConstants.ComponentModel.SPRING;
@Mapper( @Mapper(
componentModel = MappingConstants.ComponentModel.SPRING, componentModel = SPRING,
uses = {CommonMapper.class}, uses = {CommonMapper.class},
mappingControl = DeepClone.class mappingControl = DeepClone.class