代码生成器
在 framework-generator util 文件夹下有个CodeGenerator
类,部分代码如下:
java
public static void main(String[] args) {
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> {
builder.author(author)
.commentDate(DatePattern.NORM_DATETIME_PATTERN)
.enableSwagger()
.disableOpenDir()
.outputDir(outputDir);
})
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}).keyWordsHandler(new MySqlKeyWordsHandler()))
.packageConfig(builder -> {
builder.parent(parentPackageName) // 设置父包名
.moduleName(moduleName) // 设置父包模块名
.entity("core.entity")
.mapper("dao.mapper")
.pathInfo(Collections.singletonMap(OutputFile.xml, Paths.get(
outputDir,
parentPackageName.replace(".", "//"),
moduleName,
"dao").toString())); // 设置mapperXml生成路径
})
.injectionConfig(consumer -> {
Map<String, Object> customMap = new HashMap<>();
customMap.put("Dto", "service.dto");
customMap.put("Core", "core");
consumer.customMap(customMap);
List<CustomFile> customFileList = new ArrayList<>();
customFileList.add(new CustomFile.Builder()
.fileName("AddDto")
.templatePath("/templates/addDto.java.ftl")
.enableFileOverride()
.packageName((String) customMap.get("Dto"))
.build());
customFileList.add(new CustomFile.Builder()
.fileName("UpdateDto")
.templatePath("/templates/updateDto.java.ftl")
.enableFileOverride()
.packageName((String) customMap.get("Dto"))
.build());
customFileList.add(new CustomFile.Builder()
.fileName("Dto")
.templatePath("/templates/outputDto.java.ftl")
.enableFileOverride()
.packageName((String) customMap.get("Dto"))
.build());
customFileList.add(new CustomFile.Builder()
.fileName("Query")
.templatePath("/templates/query.java.ftl")
.enableFileOverride()
.packageName(customMap.get("Core") + ".query")
.build());
customFileList.add(new CustomFile.Builder()
.fileName(StrUtil.EMPTY)
.templatePath("/templates/core.java.ftl")
.enableFileOverride()
.packageName(customMap.get("Core") + ".core")
.build());
customFileList.add(new CustomFile.Builder()
.fileName("Repository")
.templatePath("/templates/repository.java.ftl")
.enableFileOverride()
.packageName(customMap.get("Core") + ".repository")
.build());
customFileList.add(new CustomFile.Builder()
.fileName("RepositoryImpl")
.templatePath("/templates/repositoryImpl.java.ftl")
.enableFileOverride()
.packageName("dao.repository")
.build());
consumer.customFile(customFileList);
})
.strategyConfig(builder -> {
builder.entityBuilder()
.addIgnoreColumns(
"id",
"create_user",
"gmt_created",
"gmt_modified",
"modify_user",
"version",
"deleted"
)
.enableFileOverride()
.enableTableFieldAnnotation()
.formatFileName("%sPO")
.build();
builder.controllerBuilder()
.superClass("com.wmeimob.infra.common.web.BaseController")
.enableRestStyle()
.enableHyphenStyle()
.enableFileOverride()
.build();
builder.serviceBuilder()
.superServiceImplClass("com.wmeimob.infra.common.context.ApplicationService")
.formatServiceFileName("%sService")
.enableFileOverride()
.build();
builder.mapperBuilder()
.superClass("com.wmeimob.spring.boot.mybatis.core.mapper.tk.CrudMapper")
.enableFileOverride()
.build();
builder.addInclude(tableNames);
})
.templateConfig(builder -> {
builder
.service(basicCurdWithPage ? "/templates/service-page.java" : "/templates/service-crud.java")
.serviceImpl("/templates/serviceImpl.java")
.controller(basicCurdWithPage ? "/templates/controller-page.java" : "/templates/controller-crud.java")
.entity("/templates/entity.java")
.mapper("/templates/mapper.java")
.build();
})
.templateEngine(new EnhanceFreemarkerTemplateEngine())
.execute();
}
这几个模板文件可以很轻松的修改定制
先看下效果,生成的代码文件长什么样:
java
/**
* 横幅 前端控制器
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
@Api(tags = "banner 管理接口")
@RestController
@RequestMapping("/v1/api/banner")
public class BannerController extends CrudPageController<BannerQuery, BannerAddDto, BannerUpdateDto> {
private final BannerService bannerService;
public BannerController(BannerService bannerService) {
super(bannerService);
this.bannerService = bannerService;
}
}
java
/**
*
* 横幅 服务类
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
public interface BannerService extends CrudPageService<BannerQuery, BannerAddDto, BannerUpdateDto> {
}
java
/**
*
* 横幅 服务实现类
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
@Service
@RequiredArgsConstructor
public class BannerServiceImpl extends ApplicationService {
private final BannerRepository bannerRepository;
@Override
public Long add(BannerAddDto dto) {
Banner banner = new Banner(
// 业务字段初始化
);
this.bannerRepository.saveChanges(banner);
return banner.getId();
}
@Override
public void update(BannerUpdateDto dto) {
Banner banner = this.bannerRepository.get(dto.getId());
// 业务字段变更
banner.setXXX(dto.getTitle());
this.bannerRepository.saveChanges(banner);
}
@Override
public BannerDto get(Long id) {
Banner banner = this.bannerRepository.get(id);
return BeanCopierUtil.copy(banner.getBannerPO(), BannerDto.class);
}
@Override
public void delete(Long id) {
Banner banner = this.bannerRepository.get(id);
banner.setDeleted();
this.bannerRepository.saveChanges(banner);
}
@Override
public List<BannerDto> list(BannerQuery query) {
List<Banner> list = this.bannerRepository.list(query);
return list
.stream()
.map(x -> BeanCopierUtil.copy(x.getBannerPO(), BannerDto.class))
.collect(Collectors.toList());
}
}
java
/**
*
* 横幅 请求添加对象
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
@Getter
@Setter
@ApiModel(value = "BannerAddDto", description = "横幅 请求添加对象")
public class BannerAddDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@ApiModelProperty("名称", required = true)
@NotBlank(message = "名称不能为空")
@Length(max = 32, message = "名称不能超过32个字符")
private String name;
/**
* 图片链接
*/
@ApiModelProperty("图片链接", required = true)
@NotBlank(message = "图片链接不能为空")
@Length(max = 255, message = "图片链接不能超过255个字符")
private String imgUrl;
}
/**
*
* 横幅 请求响应对象
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
@Getter
@Setter
@ApiModel(value = "BannerDto", description = "横幅 请求响应对象")
public class BannerDto extends BannerAddDto implements Serializable, Id {
private static final long serialVersionUID = 1L;
/**
* id
*/
@ApiModelProperty(value = "id")
private Long id;
}
/**
*
* 横幅 请求修改对象
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
@Getter
@Setter
@ApiModel(value = "BannerUpdateDto", description = "横幅 请求修改对象")
public class BannerUpdateDto extends BannerAddDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@ApiModelProperty(value = "id", hidden = true)
private Long id;
}
java
/**
* 横幅 Mapper 接口
*
* @author xxx
* @since 2024-05-07 14:47:19
*/
public interface BannerMapper extends CrudMapper<BannerPO, Long> {
}
java
/**
*
* 横幅
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
@Getter
@Setter
@ToString(callSuper = true)
@Table(name ="banner")
public class BannerPO extends CreationAuditedAggregateRoot implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@Column(name = "`name`")
private String name;
/**
* 图片链接
*/
@Column(name = "img_url")
private String imgUrl;
/**
* 外链类型
*/
@Column(name = "url_type")
private Integer urlType;
/**
* 外链地址
*/
@Column(name = "url")
private String url;
/**
* 位置
*/
@Column(name = "position")
private String position;
/**
* 排序
*/
@Column(name = "sort")
private Integer sort;
/**
* 显示状态
*/
@Column(name = "`show`")
private Boolean show;
}
java
/**
*
* 横幅 仓储接口类
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
public interface BannerRepository {
/**
* 分页查询
*
* @param query query
* @return List<Banner>
*/
List<Banner> list(BannerQuery query);
/**
* 详情
*
* @param id id
*/
Banner get(Long id);
/**
* 数据变更
*
* @param banner banner
*/
void saveChanges(Banner banner);
}
java
/**
*
* 横幅 仓储接口实现类
*
* @author xxx
* @date 2024-05-07 14:47:19
*/
@Repository
@RequiredArgsConstructor
public class BannerRepositoryImpl implements BannerRepository {
private final BannerMapper bannerMapper;
/**
* 分页查询
*
* @param query query
* @return List<Banner>
*/
@Override
public List<Banner> list(BannerQuery query) {
ExampleLambda<BannerPO> exampleLambda = new ExampleLambda<>(BannerPO.class);
exampleLambda
// xxx 你的业务条件
.orderByDesc(BannerPO::getId);
return this.bannerMapper.selectByExample(exampleLambda.end())
.stream()
.map(Banner::new)
.collect(Collectors.toList());
}
/**
* 详情
*
* @param id id
*/
@Override
public Banner get(Long id) {
BannerPO entity = this.bannerMapper.selectByPrimaryKey(id);
Assert.notNull(entity, "找不到对应的数据");
return new Banner(entity);
}
/**
* 数据变更
*
* @param banner banner
*/
@Override
public void saveChanges(Banner banner) {
if (banner.getBannerPO().isTransient()) {
bannerMapper.insertSelective(banner.getBannerPO());
} else if (banner.getBannerPO().getDeleted()) {
bannerMapper.deleteByPrimaryKey(banner.getId());
} else if (banner.getBannerPO().isModified()) {
bannerMapper.updateByPrimaryKeySelective(banner.getBannerPO());
}
}
}
这里没有全部列出来,只罗列了部分
其中核心的模板类有:
java
package com.wmeimob.fastboot.util.web;
/**
* 基础抽象 crud 接口
*
* @author mjyang
* @date 2023/8/1 13:51
*/
public interface CrudService<TAddDto, TUpdateDto extends Id> {
/**
* 详情
*
* @param id id
* @return dto
*/
default Object get(Long id) {
return null;
}
/**
* 新增
*
* @param dto dto
* @return long
*/
Object add(TAddDto dto);
/**
* 编辑
*
* @param dto dto
*/
void update(TUpdateDto dto);
/**
* 删除
*
* @param id id
*/
void delete(Long id);
}
java
package com.wmeimob.fastboot.util.web;
import com.wmeimob.fastboot.util.pager.BaseDTO;
import java.util.List;
/**
* 基础抽象 crud page 接口
*
* @author mjyang
* @date 2023/8/1 13:51
*/
public interface CrudPageService<TQuery extends BaseDTO, TAddDto, TUpdateDto extends Id>
extends CrudService<TAddDto, TUpdateDto> {
/**
* 分页查询
*
* @param query query
* @return list dto
*/
default List<?> list(TQuery query) {
throw new UnsupportedOperationException("不支持该方式");
}
/**
* 滚动分页查询
*
* @param query query
* @return list dto
*/
default <T extends NextToken> List<T> scrollList(TQuery query) {
throw new UnsupportedOperationException("不支持该方式");
}
}
java
/**
* 基础抽象 crud 控制器
*
* @author mjyang
* @date 2023/8/1 13:47
*/
@RequiredArgsConstructor
public abstract class CrudController<TAddDto, TUpdateDto extends Id> {
private final CrudService<TAddDto, TUpdateDto> service;
@GetMapping("/get/{id}")
@ApiOperation("详情")
public JsonResult<?> get(@PathVariable("id") Long id) {
return JsonResult.ok(this.service.get(id));
}
@PostMapping
@ApiOperation("添加")
public JsonResult<?> add(@RequestBody @Validated TAddDto dto) {
return JsonResult.ok(this.service.add(dto));
}
@PutMapping("/update/{id}")
@ApiOperation("编辑")
public JsonResult<Void> update(@PathVariable("id") Long id, @RequestBody @Validated TUpdateDto dto) {
dto.setId(id);
this.service.update(dto);
return JsonResult.ok();
}
@DeleteMapping("/delete/{id}")
@ApiOperation("删除")
public JsonResult<Void> delete(@PathVariable("id") Long id) {
this.service.delete(id);
return JsonResult.ok();
}
}
java
/**
* 基础抽象 crud page 控制器
*
* @author mjyang
* @date 2023/8/1 13:47
*/
public abstract class CrudPageController<TQuery extends BaseDTO, TAddDto, TUpdateDto extends Id>
extends CrudController<TAddDto, TUpdateDto> {
private final CrudPageService<TQuery, TAddDto, TUpdateDto> service;
protected CrudPageController(CrudPageService<TQuery, TAddDto, TUpdateDto> service) {
super(service);
this.service = service;
}
@GetMapping
@ApiOperation("分页查询")
public JsonResult<PagedResult<?>> list(TQuery query) {
try (Page<?> page = PagedResult.startPage(query)) {
List<?> list = this.service.list(query);
return JsonResult.ok(PagedResult.of(page.getTotal(), list));
}
}
}
java
/**
* 基础抽象 crud scroll page 控制器
*
* @author mjyang
* @date 2023/8/1 13:47
*/
public abstract class CrudScrollPageController<TQuery extends BaseDTO, TAddDto, TUpdateDto extends Id>
extends CrudController<TAddDto, TUpdateDto> {
private final CrudPageService<TQuery, TAddDto, TUpdateDto> service;
protected CrudScrollPageController(CrudPageService<TQuery, TAddDto, TUpdateDto> service) {
super(service);
this.service = service;
}
@GetMapping
@ApiOperation("滚动分页查询")
public <T extends NextToken> JsonResult<PagedScrollResult<T>> list(TQuery query) {
try (Page<T> page = PagedScrollResult.startPage(query)) {
List<T> list = this.service.scrollList(query);
return JsonResult.ok(PagedScrollResult.of(list));
}
}
}
这个模板生成的是伪 DDD 代码,代码书写上并不强制要求符合 DDD 习惯。
该生成器生成的代码包含基础的增删改查业务,更多的细节可以查阅代码。同时希望提供一种模板化标准,以减少前后端沟通成本,并带来开发效率的提升。