快速生成通用接口業(yè)務(wù)配置
這個是干什么的?
簡單介紹下:
作用:通過插件一鍵生成某個表對應(yīng)的增刪改查等基礎(chǔ)或者說通用接口,這里面的代碼是基礎(chǔ)版的,后續(xù)改良后,很多業(yè)務(wù)的通用功能,比如流程的啟動,自動下一步,通用導(dǎo)出,通用導(dǎo)入等等。
原理:核心就是BasicControllerPostProcessor
,通過動態(tài)生成代理對象,完成邏輯實(shí)現(xiàn)。這里呢經(jīng)過實(shí)踐呢后續(xù)也有不少優(yōu)化的,后續(xù)我總結(jié)后發(fā)一個新版的
一、核心處理類
package?com.nari.core.handler;
import?cn.hutool.core.collection.ListUtil;
import?cn.hutool.core.date.DateUtil;
import?cn.hutool.core.date.TimeInterval;
import?lombok.extern.slf4j.Slf4j;
import?org.apache.commons.lang3.StringUtils;
import?org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import?org.springframework.core.Ordered;
import?org.springframework.core.annotation.Order;
import?org.springframework.stereotype.Component;
import?javax.annotation.Resource;
import?java.lang.reflect.Field;
import?java.lang.reflect.InvocationHandler;
import?java.lang.reflect.Proxy;
import?java.util.List;
import?java.util.Map;
/**
?*?動態(tài)加載baseMapper,baseDao,baseService
?*
?*?@author?<a?href="mailto:njpkhuan@gmail.com">朱永勝</a>
?*?@version?1.0.0
?*?@since?2021/3/2
?*/
4j
(Ordered.HIGHEST_PRECEDENCE)
public?class?BasicControllerPostProcessor?extends?CommonAnnotationBeanPostProcessor?{
????private?static?final?long?serialVersionUID?=?-945664767382485314L;
???? ("NullableProblems")
????
????public?Object?postProcessBeforeInstantiation(Class<?>?beanClass,?String?beanName)?{
????????String?packageName?=?beanClass.getPackage().getName();
????????log.trace("beanName---{},packageName:{}",?beanName,?packageName);
????????List<String>?per?=?ListUtil.of("com.nari.supervision.daily");
????????List<String>?tail?=?ListUtil.of("outbound","personal");
????????if?(per.stream().anyMatch(packageName::contains))?{
????????????if?(tail.stream().map(v?->?v?+?".controller").anyMatch(packageName::contains))?{
????????????????try?{
????????????????????updateResourceName(beanClass,?beanName,?"basicService",?"Controller",?"Service");
????????????????}?catch?(Exception?e)?{
????????????????????e.printStackTrace();
????????????????????return?null;
????????????????}
????????????}
????????????if?(tail.stream().map(v?->?v?+?".service").anyMatch(packageName::contains))?{
????????????????try?{
????????????????????updateResourceName(beanClass,?beanName,?"basicMapper",?"Service",?"TransformImpl");
????????????????????updateResourceName(beanClass,?beanName,?"basicDao",?"Service",?"Mapper");
????????????????}?catch?(Exception?e)?{
????????????????????e.printStackTrace();
????????????????????return?null;
????????????????}
????????????}
????????????if?(tail.stream().map(v?->?v?+?"serviceImpl").anyMatch(packageName::contains))?{
????????????????try?{
????????????????????updateResourceName(beanClass,?beanName,?"basicMapper",?"Service",?"TransformImpl");
????????????????????updateResourceName(beanClass,?beanName,?"basicDao",?"Service",?"Mapper");
????????????????}?catch?(Exception?e)?{
????????????????????e.printStackTrace();
????????????????????return?null;
????????????????}
????????????}
????????}
????????return?null;
????}
????private?void?updateResourceName(Class<?>?beanClass,?String?beanName,?String?destField,?String?searchString,?String?replaceString)
????????????throws?NoSuchFieldException,?IllegalAccessException?{
????????Field?field?=?beanClass.getSuperclass().getDeclaredField(destField);
????????Resource?basicMapper?=?field.getAnnotation(Resource.class);
????????InvocationHandler?invocationHandler?=?Proxy.getInvocationHandler(basicMapper);
????????Field?memberValues?=?invocationHandler.getClass().getDeclaredField("memberValues");
????????memberValues.setAccessible(true);
????????//noinspection?unchecked
????????Map<String,?Object>?map?=?(Map<String,?Object>)?memberValues.get(invocationHandler);
????????map.put("name",?StringUtils.replace(beanName,?searchString,?replaceString));
????}
}
二、基礎(chǔ)類
BasicController
package?com.nari.core.basic;
import?com.nari.core.annotation.OperationLog;
import?com.nari.core.groups.basic.InsertGroup;
import?com.nari.core.groups.basic.UpdateGroup;
import?com.nari.core.groups.query.PageQueryGroup;
import?com.nari.core.web.ApiResult;
import?com.nari.core.web.BaseParam;
import?com.nari.core.web.PageResult;
import?io.swagger.annotations.ApiOperation;
import?io.swagger.annotations.ApiSort;
import?lombok.extern.slf4j.Slf4j;
import?org.springframework.validation.annotation.Validated;
import?org.springframework.web.bind.annotation.*;
import?javax.annotation.Resource;
import?javax.validation.Valid;
import?java.util.List;
/**
?*?基礎(chǔ)接口管理
?*
?*?@author?<a?href="mailto:njpkhuan@gmail.com">朱永勝</a>
?*?@version?1.0.0
?*?@since?2021/3/1
?*/
4j
public?class?BasicController<T?extends?BasicModel,?Q?extends?BaseParam,?V,?D,?M?extends?BasicMapper<T,?Q,?D,?V>>?extends?com.nari.core.web.BaseController?{
????
????private?BasicService<T,?Q,?V,?D,?M>?basicService;
????/**
?????*?添加
?????*
?????*?@param?query?{@link?Q}
?????*/
????
???? (value?=?"1.1?添加")
???? (value?=?"添加")
???? (value?=?InsertGroup.class)
????public?ApiResult?insert(@RequestBody?Q?query)?{
????????basicService.insert(query);
????????return?success("添加成功!");
????}
????/**
?????*?根據(jù)id刪除
?????*
?????*?@param?id?主鍵
?????*/
???? ("/{id}")
???? (value?=?"1.2?根據(jù)id刪除")
???? (value?=?"根據(jù)id刪除")
????public?ApiResult?del(@PathVariable("id")?String?id)?{
????????basicService.del(id);
????????return?success("刪除成功!");
????}
????/**
?????*?根據(jù)id刪除-軟刪除,實(shí)際修改標(biāo)識符
?????*
?????*?@param?id?主鍵
?????*/
???? ("/{id}/weak")
???? (value?=?"1.3?根據(jù)id刪除-軟刪除,實(shí)際修改標(biāo)識符")
???? (value?=?"根據(jù)id刪除-軟刪除,實(shí)際修改標(biāo)識符")
????public?ApiResult?delWeak(@PathVariable("id")?String?id)?{
????????basicService.delWeak(id);
????????return?success("刪除成功!");
????}
????/**
?????*?根據(jù)id更新信息
?????*
?????*?@param?query?{@link?Q}
?????*/
???? ("update")
???? (value?=?"1.4?根據(jù)id更新信息")
???? (value?=?"根據(jù)id更新信息")
???? (value?=?UpdateGroup.class)
????public?ApiResult<V>?update(@RequestBody?Q?query)?{
????????return?success(basicService.update(query));
????}
????/**
?????*?根據(jù)id更新信息-批量
?????*
?????*?@param?query?{@link?Q}
?????*/
???? ("updateBatch")
???? (value?=?"1.5?根據(jù)id更新信息-批量")
???? (value?=?"根據(jù)id更新信息-批量")
???? (value?=?UpdateGroup.class)
????public?ApiResult?updateBatch(@RequestBody?List<Q>?query)?{
????????basicService.updateBatch(query);
????????return?success();
????}
????/**
?????*?查詢單個數(shù)據(jù)
?????*
?????*?@param?id?主鍵
?????*/
???? ("/{id}")
???? (value?=?"1.6?查詢單個數(shù)據(jù)")
???? (value?=?"查詢單個數(shù)據(jù)")
????public?ApiResult<V>?select(@PathVariable("id")?String?id)?{
????????return?success(basicService.select(id));
????}
????/**
?????*?分頁
?????*
?????*?@param?query?{@link?Q}
?????*/
???? ("page")
???? (value?=?"1.7?分頁")
???? (value?=?"分頁")
???? (value?=?PageQueryGroup.class)
????public?ApiResult<PageResult<V>>?listUser(Q?query)?{
????????return?success(basicService.page(query));
????}
}
BasicDao
package?com.nari.core.basic;
import?com.baomidou.mybatisplus.core.mapper.BaseMapper;
import?com.nari.core.web.BaseParam;
import?com.nari.core.web.PageParam;
import?org.apache.ibatis.annotations.Param;
import?java.util.List;
/**
?*?基礎(chǔ)接口
?*
?*?@author?<a?href="mailto:njpkhuan@gmail.com">朱永勝</a>
?*?@version?1.0.0
?*?@since?2021/3/1
?*/
public?interface?BasicDao<T?extends?BasicModel,?D,?Q?extends?BaseParam>?extends?BaseMapper<T>?{
????List<D>?selectPageRel(@Param("page")?PageParam<D,?Q>?page,?@Param("param")?Q?param);
}
BasicEnum
package?com.nari.core.basic;
/**
?*?基礎(chǔ)枚舉
?*?主要用來配合apijson實(shí)現(xiàn)枚舉展示
?*
?*?@author?<a?href="mailto:17602556550@189.cn">朱永勝</a>
?*?@version?1.0.0
?*?@since?2023/5/25
?*/
public?interface?BasicEnum?{
????String?getName();
????Integer?getValue();
}
BasicMapper
package?com.nari.core.basic;
import?org.mapstruct.MappingTarget;
import?java.util.List;
/**
?*?基礎(chǔ)轉(zhuǎn)換
?*
?*?@author?<a?href="mailto:njpkhuan@gmail.com">朱永勝</a>
?*?@version?1.0.0
?*?@since?2021/3/1
?*/
public?interface?BasicMapper<T,?Q,?D,?V>?{
????T?query2do(Q?query);
????V?dto2View(D?dto);
????D?do2dto(T?role);
????void?update(Q?query,?@MappingTarget?T?t);
????List<V>?dto2ViewPage(List<D>?dto);
}
BasicModel
package?com.nari.core.basic;
import?io.swagger.annotations.ApiModelProperty;
import?lombok.Data;
/**
?*?通用模型
?*
?*?@author?<a?href="mailto:17602556550@189.cn">朱永勝</a>
?*?@version?1.0.0
?*?@since?2023/5/26
?*/
public?class?BasicModel?{
????/**
?????*?主鍵
?????*/
????private?String?id;
????/**
?????*?刪除標(biāo)識
?????*/
???? (value?=?"刪除標(biāo)識")
????private?String?deleted;
}
BasicService
package?com.nari.core.basic;
import?cn.hutool.core.util.IdUtil;
import?com.nari.core.web.BaseParam;
import?com.nari.core.web.PageParam;
import?com.nari.core.web.PageResult;
import?lombok.extern.slf4j.Slf4j;
import?org.springframework.transaction.annotation.Transactional;
import?javax.annotation.Resource;
import?javax.validation.Valid;
import?javax.validation.constraints.NotNull;
import?java.util.List;
/**
?*?基礎(chǔ)服務(wù)
?*
?*?@author?<a?href="mailto:njpkhuan@gmail.com">朱永勝</a>
?*?@version?1.0.0
?*?@since?2021/3/1
?*/
4j
public?class?BasicService<T?extends?BasicModel,?Q?extends?BaseParam,?V,?D,?M?extends?BasicMapper<T,?Q,?D,?V>>?{
????
????private?BasicDao<T,?D,?Q>?basicDao;
????
????private?BasicMapper<T,?Q,?D,?V>?basicMapper;
????/**
?????*?添加
?????*
?????*?@param?query?{@link?Q}
?????*?@author?<a?href?=?"mailto:njpkhuan@gmail.com"?>朱永勝</a?>
?????*?@since?2021/3/1
?????*?@since?1.0.0
?????*/
???? (rollbackFor?=?Exception.class)
????public?void?insert(@Valid?Q?query)?{
????????T?t?=?basicMapper.query2do(query);
????????t.setId(IdUtil.simpleUUID());
????????basicDao.insert(t);
????}
????/**
?????*?刪除
?????*
?????*?@param?id?{@link?Q}
?????*?@author?<a?href?=?"mailto:njpkhuan@gmail.com"?>朱永勝</a?>
?????*?@since?2021/3/1
?????*?@since?1.0.0
?????*/
???? (rollbackFor?=?Exception.class)
????public?void?del(@NotNull?String?id)?{
????????basicDao.deleteById(id);
????}
????/**
?????*?根據(jù)用戶id更新
?????*
?????*?@param?query?@{@link?Q}
?????*?@author?<a?href?=?"mailto:njpkhuan@gmail.com"?>朱永勝</a?>
?????*?@since?2021/3/1
?????*?@since?1.0.0
?????*/
???? (rollbackFor?=?Exception.class)
????public?V?update(@Valid?Q?query)?{
????????T?data?=?basicMapper.query2do(query);
????????basicDao.updateById(data);
????????D?d?=?basicMapper.do2dto(data);
????????return?basicMapper.dto2View(d);
????}
????/**
?????*?查詢
?????*
?????*?@param?id?主鍵
?????*?@author?<a?href?=?"mailto:njpkhuan@gmail.com"?>朱永勝</a?>
?????*?@since?2021/3/1
?????*?@since?1.0.0
?????*/
????public?V?select(@NotNull?String?id)?{
????????T?data?=?basicDao.selectById(id);
????????D?d?=?basicMapper.do2dto(data);
????????return?basicMapper.dto2View(d);
????}
????/**
?????*?查詢多條記錄
?????*
?????*?@param?query?{@link?Q}
?????*?@author?<a?href?=?"mailto:njpkhuan@gmail.com"?>朱永勝</a?>
?????*?@since?2021/2/23
?????*?@since?1.0.0
?????*/
????public?PageResult<V>?page(@Valid?Q?query)?{
????????PageParam<D,?Q>?page?=?new?PageParam<>(query);
????????page.setDefaultOrder("create_time?desc");
????????List<D>?list?=?basicDao.selectPageRel(page,?query);
????????List<V>?vList?=?basicMapper.dto2ViewPage(list);
????????log.trace("{}",?list);
????????return?new?PageResult<>(vList,?page.getTotal());
????}
????/**
?????*?軟刪除
?????*
?????*?@author?<a?href="mailto:17602556550@189.cn">朱永勝</a>
?????*?@since?2023/5/26
?????*/
???? (rollbackFor?=?Exception.class)
????public?void?delWeak(String?id)?{
????????T?t?=?basicDao.selectById(id);
????????t.setDeleted("1");
????????basicDao.updateById(t);
????}
????/**
?????*?批量更新
?????*
?????*?@author?<a?href="mailto:17602556550@189.cn">朱永勝</a>
?????*?@since?2023/6/6
?????*/
???? (rollbackFor?=?Exception.class)
????public?void?updateBatch(List<Q>?query)?{
????????query.forEach(this::update);
????}
}
GenericSuperclassUtil
package?com.nari.core.basic;
import?java.lang.reflect.ParameterizedType;
import?java.lang.reflect.Type;
public?class?GenericSuperclassUtil?{
????/*
?????*?獲取泛型類Class對象,不是泛型類則返回null
?????*/
????public?static?Class<?>?getActualTypeArgument(Class<?>?clazz)?{
????????Class<?>?entitiClass?=?null;
????????Type?genericSuperclass?=?clazz.getGenericSuperclass();
????????if?(genericSuperclass?instanceof?ParameterizedType)?{
????????????Type[]?actualTypeArguments?=?((ParameterizedType)?genericSuperclass)
????????????????????.getActualTypeArguments();
????????????if?(actualTypeArguments?!=?null?&&?actualTypeArguments.length?>?0)?{
????????????????entitiClass?=?(Class<?>)?actualTypeArguments[0];
????????????}
????????}
????????return?entitiClass;
????}
????/*
?????*?獲取泛型類Class對象,不是泛型類則返回null
?????*/
????static?Class<?>?getActualTypeArgument(Class<?>?clazz,?Integer?pos)?{
????????Class<?>?entitiClass?=?null;
????????Type?genericSuperclass?=?clazz.getGenericSuperclass();
????????if?(genericSuperclass?instanceof?ParameterizedType)?{
????????????Type[]?actualTypeArguments?=?((ParameterizedType)?genericSuperclass)
????????????????????.getActualTypeArguments();
????????????if?(actualTypeArguments?!=?null?&&?actualTypeArguments.length?>?pos)?{
????????????????entitiClass?=?(Class<?>)?actualTypeArguments[pos];
????????????}
????????}
????????return?entitiClass;
????}
}
三、POM
??<org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
??
??<dependency>
??????<groupId>org.mapstruct</groupId>
??????<artifactId>mapstruct</artifactId>
??????<version>${org.mapstruct.version}</version>
??</dependency><plugin>
????<groupId>org.apache.maven.plugins</groupId>
????<artifactId>maven-compiler-plugin</artifactId>
????<version>3.8.1</version>
????<configuration>
????????<source>1.8</source>
????????<target>1.8</target>
????????<annotationProcessorPaths>
????????????<path>
????????????????<groupId>org.projectlombok</groupId>
????????????????<artifactId>lombok</artifactId>
????????????????<version>${lombok.version}</version>
????????????</path>
????????????<path>
????????????????<groupId>org.projectlombok</groupId>
????????????????<artifactId>lombok-mapstruct-binding</artifactId>
????????????????<version>0.2.0</version>
????????????</path>
????????????<path>
????????????????<groupId>org.mapstruct</groupId>
????????????????<artifactId>mapstruct-processor</artifactId>
????????????????<version>${org.mapstruct.version}</version>
????????????</path>
????????</annotationProcessorPaths>
????</configuration>
</plugin>