commit:集成knife4j

This commit is contained in:
Jerry
2020-10-29 18:53:09 +08:00
parent 6e57f10dfc
commit 96fddccc47
208 changed files with 1072 additions and 361 deletions

View File

@@ -12,7 +12,7 @@ import java.util.Date;
* Controller的环绕拦截类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@ControllerAdvice
public class MyControllerAdvice {

View File

@@ -24,7 +24,7 @@ import java.util.concurrent.TimeoutException;
* 用不同的函数,处理不同类型的异常。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
@RestControllerAdvice("com.orange.demo")

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 主要用于标记逻辑删除字段。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 主要用于标记更新字段。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 主要用于标记Service所依赖的数据源类型。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -9,7 +9,7 @@ import java.lang.annotation.Target;
* 标记Controller中的方法参数参数解析器会根据该注解将请求中的JSON数据映射到参数中的绑定字段。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 主要用于标记无需Token验证的接口
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 标识Model和常量字典之间的关联关系。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 标识Model之间的字典关联关系。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -4,9 +4,11 @@ import java.lang.annotation.*;
/**
* 标注多对多的Model关系。
* 重要提示:由于多对多关联表数据,很多时候都不需要跟随主表数据返回,所以该注解不会在
* 生成的时候自动添加到实体类字段上,需要的时候,用户可自行手动添加。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 主要用于多对多的Model关系。标注通过从表关联字段或者关联表关联字段计算主表聚合计算字段的规则。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 主要用于一对多的Model关系。标注通过从表关联字段计算主表聚合计算字段的规则。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -6,7 +6,7 @@ import java.lang.annotation.*;
* 标识Model之间的一对一关联关系。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -8,7 +8,7 @@ import java.lang.annotation.*;
* 用于标记支持数据上传和下载的字段。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -24,7 +24,7 @@ import java.util.List;
* 记录接口的链路traceId、请求参数、应答数据、错误信息和调用时长。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Aspect
@Component

View File

@@ -14,7 +14,7 @@ import java.util.Map;
*
* @param <M> 主Model实体对象。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@RegisterMapper
public interface BaseDaoMapper<M> extends Mapper<M>, InsertListMapper<M> {

View File

@@ -12,7 +12,7 @@ import java.util.stream.Collectors;
* @param <D> Domain域对象类型。
* @param <M> Model实体对象类型。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public interface BaseModelMapper<D, M> {

View File

@@ -8,7 +8,7 @@ import java.util.List;
*
* @param <M> 数据类型。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class DummyModelMapper<M> implements BaseModelMapper<M, M> {

View File

@@ -16,7 +16,7 @@ import java.util.List;
* @param <M> Model实体对象的类型。
* @param <K> Model对象主键的类型。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public abstract class BaseDictService<M, K> extends BaseService<M, K> {

View File

@@ -34,7 +34,7 @@ import static java.util.stream.Collectors.*;
* @param <M> Model对象的类型。
* @param <K> Model对象主键的类型。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public abstract class BaseService<M, K> {

View File

@@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
* 使用Caffeine作为本地缓存库
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Configuration
@EnableCaching

View File

@@ -9,7 +9,7 @@ import java.util.Set;
* @param <K> 字典表主键类型。
* @param <V> 字典表对象类型。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public interface DictionaryCache<K, V> {

View File

@@ -9,7 +9,7 @@ import java.util.function.Function;
* @param <K> 字典表主键类型。
* @param <V> 字典表对象类型。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class MapDictionaryCache<K, V> implements DictionaryCache<K, V> {

View File

@@ -12,7 +12,7 @@ import java.util.function.Function;
* @param <K> 字典表主键类型。
* @param <V> 字典表对象类型。
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class MapTreeDictionaryCache<K, V> extends MapDictionaryCache<K, V> {

View File

@@ -13,7 +13,7 @@ import java.util.Set;
* Session数据缓存辅助类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@SuppressWarnings("unchecked")
@Component

View File

@@ -21,7 +21,7 @@ import java.util.List;
* 所有的项目拦截器、参数解析器、消息对象转换器都在这里集中配置。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Configuration
public class CommonWebMvcConfig implements WebMvcConfigurer {

View File

@@ -8,7 +8,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
* 目前用于用户密码加密UAA接入应用客户端的client_secret加密。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Configuration
public class EncryptConfig {

View File

@@ -24,7 +24,7 @@ import java.util.List;
* RestTemplate连接池配置对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Configuration
public class RestTemplateConfig {

View File

@@ -10,7 +10,7 @@ import org.springframework.context.annotation.Configuration;
* tomcat配置对象。当前配置禁用了PUT和DELETE方法防止渗透攻击。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Configuration
public class TomcatConfig {

View File

@@ -7,7 +7,7 @@ import java.util.Map;
* 聚合计算的常量类型对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public final class AggregationType {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.constant;
* 应用程序的常量声明对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public final class ApplicationConstant {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.constant;
* 返回应答中的错误代码和错误信息。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public enum ErrorCodeEnum {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.constant;
* 数据记录逻辑删除标记常量。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public final class GlobalDeletedFlag {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.exception;
* 数据验证失败的自定义异常。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class DataValidationException extends RuntimeException {

View File

@@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode;
* 无效的类对象字段的自定义异常。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode;
* 无效的实体对象字段的自定义异常。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode;
* 无效的实体对象的自定义异常。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
@EqualsAndHashCode(callSuper = true)

View File

@@ -5,7 +5,7 @@ package com.orange.demo.common.core.exception;
* NOTE主要是为了避免SonarQube进行代码质量扫描时给出警告。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class MyRuntimeException extends RuntimeException {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.exception;
* 没有数据被修改的自定义异常。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class NoDataAffectException extends RuntimeException {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.exception;
* 没有数据访问权限的自定义异常。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class NoDataPermException extends RuntimeException {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.exception;
* Redis缓存访问失败。比如获取分布式数据锁超时、等待线程中断等。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class RedisCacheAccessException extends RuntimeException {

View File

@@ -29,7 +29,7 @@ import java.util.*;
* 2、多个对象需要封装到一个对象里才可以用@RequestBody接收。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class MyRequestArgumentResolver implements HandlerMethodArgumentResolver {

View File

@@ -11,7 +11,7 @@ import java.util.Map;
* 应用程序启动后的事件监听对象。主要负责加载Model之间的字典关联和一对一关联所对应的Service结构关系。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Component
public class LoadCachedDataListener implements ApplicationListener<ApplicationReadyEvent> {

View File

@@ -11,7 +11,7 @@ import java.util.Map;
* 应用程序启动后的事件监听对象。主要负责加载Model之间的字典关联和一对一关联所对应的Service结构关系。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Component
public class LoadServiceRelationListener implements ApplicationListener<ApplicationReadyEvent> {

View File

@@ -8,7 +8,7 @@ import lombok.Data;
* 同时为了提升效率减少查询次数可以根据具体的需求将部分验证关联对象存入data字段以供Controller使用。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
public class CallResult {

View File

@@ -7,7 +7,7 @@ import lombok.Data;
* Mybatis Mapper.xml中所需的分组条件对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
@AllArgsConstructor

View File

@@ -20,7 +20,7 @@ import java.util.List;
* 查询分组参数请求对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@EqualsAndHashCode(callSuper = true)
@Slf4j

View File

@@ -18,7 +18,7 @@ import java.util.*;
* Controller参数中的排序请求对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@EqualsAndHashCode(callSuper = true)
@Slf4j
@@ -44,6 +44,9 @@ public class MyOrderParam extends ArrayList<MyOrderParam.OrderInfo> {
int i = 0;
StringBuilder orderBy = new StringBuilder(128);
for (OrderInfo orderInfo : orderParam) {
if (StringUtils.isBlank(orderInfo.getFieldName())) {
continue;
}
OrderBaseData orderBaseData = parseOrderBaseData(orderInfo, modelClazz);
if (StringUtils.isBlank(orderBaseData.tableName)) {
throw new InvalidDataModelException(orderBaseData.modelName);
@@ -83,9 +86,6 @@ public class MyOrderParam extends ArrayList<MyOrderParam.OrderInfo> {
private static OrderBaseData parseOrderBaseData(OrderInfo orderInfo, Class<?> modelClazz) {
OrderBaseData orderBaseData = new OrderBaseData();
if (StringUtils.isBlank(orderInfo.getFieldName())) {
return orderBaseData;
}
orderBaseData.fieldName = StringUtils.substringBefore(orderInfo.fieldName, DICT_MAP);
String[] stringArray = StringUtils.split(orderBaseData.fieldName, '.');
if (stringArray.length == 1) {
@@ -230,7 +230,7 @@ public class MyOrderParam extends ArrayList<MyOrderParam.OrderInfo> {
@Data
public static class OrderInfo {
/**
* Java对象的字段名。目前主要包含三种格式
* Java对象的字段名。如果fieldName为空则忽略跳过。目前主要包含三种格式:
* 1. 简单的属性名称如userId将会直接映射到与其关联的数据库字段。表名为当前ModelClazz所对应的表名。
* 映射结果或为 my_main_table.user_id
* 2. 字典属性名称如userIdDictMap.id由于仅仅支持字典中Id数据的排序所以直接截取DictMap之前的字符串userId作为排序属性。

View File

@@ -0,0 +1,23 @@
package com.orange.demo.common.core.object;
import lombok.Data;
import java.util.List;
/**
* 分页数据的应答返回对象。
*
* @author Jerry
* @date 2020-09-24
*/
@Data
public class MyPageData<T> {
/**
* 数据列表。
*/
private List<T> dataList;
/**
* 数据总数量。
*/
private Long totalCount;
}

View File

@@ -6,7 +6,7 @@ import lombok.Getter;
* Controller参数中的分页请求对象
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Getter
public class MyPageParam {

View File

@@ -8,7 +8,7 @@ import lombok.Data;
* BaseService中的实体对象数据组装函数会根据该参数对象进行数据组装。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
@Builder

View File

@@ -16,7 +16,7 @@ import java.util.List;
* Where中的条件语句。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
@Data

View File

@@ -13,7 +13,7 @@ import java.io.PrintWriter;
* 接口返回对象
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
public class ResponseResult<T> {

View File

@@ -10,7 +10,7 @@ import javax.servlet.http.HttpServletRequest;
* 基于Jwt用于前后端传递的令牌对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
@ToString

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.object;
* 二元组对象。主要用于可以一次返回多个结果的场景,同时还能避免强制转换。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class Tuple2<T1, T2> {

View File

@@ -19,7 +19,7 @@ import java.util.List;
* 包含存储本地文件的功能,以及上传和下载所需的通用方法。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public abstract class BaseUpDownloader {

View File

@@ -22,7 +22,7 @@ import java.util.Objects;
* 存储本地文件的上传下载实现类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
@Component
@@ -75,7 +75,7 @@ public class LocalUpDownloader extends BaseUpDownloader {
i = bis.read(buff);
}
} catch (IOException e) {
log.error("Failed to call UpDownloadUtil.doDownload", e);
log.error("Failed to call LocalUpDownloader.doDownload", e);
}
}

View File

@@ -9,7 +9,7 @@ import java.util.Map;
* 业务对象根据上传下载存储类型,获取上传下载对象的工厂类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Component
public class UpDownloaderFactory {

View File

@@ -6,7 +6,7 @@ import lombok.Data;
* 数据上传操作的应答信息对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
public class UploadResponseInfo {

View File

@@ -6,7 +6,7 @@ import lombok.Data;
* 上传数据存储信息对象。这里之所以使用对象,主要是便于今后扩展。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
public class UploadStoreInfo {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.upload;
* 上传数据存储介质类型枚举。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public enum UploadStoreTypeEnum {

View File

@@ -11,7 +11,7 @@ import java.lang.reflect.Field;
* 获取JDK动态代理/CGLIB代理对象代理的目标对象的工具类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public class AopTargetUtil {

View File

@@ -10,7 +10,7 @@ import org.springframework.stereotype.Component;
* Spring 系统启动应用感知对象主要用于获取Spring Bean的上下文对象后续的代码中可以直接查找系统中加载的Bean对象。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Component
public class ApplicationContextHolder implements ApplicationContextAware {

View File

@@ -10,7 +10,7 @@ import javax.servlet.http.HttpServletResponse;
* 获取Servlet HttpRequest和HttpResponse的工具类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class ContextUtil {

View File

@@ -23,7 +23,7 @@ import java.util.*;
* 导出工具类目前支持xlsx和csv两种类型。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public class ExportUtil {

View File

@@ -22,7 +22,7 @@ import java.util.stream.Collectors;
* 导入工具类目前支持xlsx和csv两种类型。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public class ImportUtil {
@@ -122,7 +122,7 @@ public class ImportUtil {
* @param rowIndex 当前行号。
* @param row 当前行数据列表对象。
*/
public void doImport(int rowIndex, List<Object> row) {
public void doImport(long rowIndex, List<Object> row) {
if (row == null) {
doProcess(batchRowList);
doFinish();

View File

@@ -16,7 +16,7 @@ import java.util.List;
* Ip工具类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public class IpUtil {

View File

@@ -12,7 +12,7 @@ import java.util.Map;
* 基于JWT的Token生成工具类
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public class JwtUtil {

View File

@@ -6,7 +6,7 @@ package com.orange.demo.common.core.util;
* 提高代码的规范度和可维护性。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class LogMessageUtil {

View File

@@ -16,7 +16,7 @@ import java.util.UUID;
* 脚手架中常用的基本工具方法集合,一般而言工程内部使用的方法。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class MyCommonUtil {

View File

@@ -16,7 +16,7 @@ import static org.joda.time.PeriodType.days;
* 日期工具类主要封装了部分joda-time中的方法让很多代码一行完成同时统一了日期到字符串的pattern格式。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class MyDateUtil {

View File

@@ -28,7 +28,7 @@ import java.util.stream.Collectors;
* 负责Model数据操作、类型转换和关系关联等行为的工具类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Slf4j
public class MyModelUtil {

View File

@@ -3,6 +3,7 @@ package com.orange.demo.common.core.util;
import cn.jimmyshi.beanquery.BeanQuery;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.orange.demo.common.core.object.MyPageData;
import java.util.List;
@@ -10,7 +11,7 @@ import java.util.List;
* 生成带有分页信息的数据列表
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class MyPageUtil {
@@ -37,13 +38,13 @@ public class MyPageUtil {
* 用户构建带有分页信息的数据列表。
*
* @param dataList 数据列表该参数必须是调用PageMethod.startPage之后立即执行mybatis查询操作的结果集。
* @return 返回结果集和TotalCount
* @return 返回分页数据对象
*/
public static <T> JSONObject makeResponseData(List<T> dataList) {
JSONObject pageData = new JSONObject();
pageData.put(DATA_LIST_LITERAL, dataList);
public static <T> MyPageData<T> makeResponseData(List<T> dataList) {
MyPageData<T> pageData = new MyPageData<>();
pageData.setDataList(dataList);
if (dataList instanceof Page) {
pageData.put(TOTAL_COUNT_LITERAL, ((Page<?>)dataList).getTotal());
pageData.setTotalCount(((Page<?>)dataList).getTotal());
}
return pageData;
}
@@ -53,13 +54,13 @@ public class MyPageUtil {
*
* @param dataList 数据列表该参数必须是调用PageMethod.startPage之后立即执行mybatis查询操作的结果集。
* @param totalCount 总数量。
* @return 返回结果集和TotalCount
* @return 返回分页数据对象
*/
public static <T> JSONObject makeResponseData(List<T> dataList, Long totalCount) {
JSONObject pageData = new JSONObject();
pageData.put(DATA_LIST_LITERAL, dataList);
public static <T> MyPageData<T> makeResponseData(List<T> dataList, Long totalCount) {
MyPageData<T> pageData = new MyPageData<>();
pageData.setDataList(dataList);
if (totalCount != null) {
pageData.put(TOTAL_COUNT_LITERAL, totalCount);
pageData.setTotalCount(totalCount);
}
return pageData;
}

View File

@@ -15,7 +15,7 @@ import java.util.Map;
* Java RSA 加密工具类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class RsaUtil {

View File

@@ -15,7 +15,7 @@ import java.util.function.Function;
* @param <K> 节点之间关联键的类型。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
public class TreeNode<T, K> {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.validator;
* 数据增加的验证分组。通常用于数据新增场景。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public interface AddGroup {
}

View File

@@ -11,7 +11,7 @@ import java.lang.annotation.Target;
* 定义在Model对象中标注字段值引用自指定的常量字典和ConstDictRefValidator对象配合完成数据验证。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -10,7 +10,7 @@ import java.lang.reflect.Method;
* 数据字段自定义验证用于验证Model中字符串字段的最大长度和最小长度。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class ConstDictValidator implements ConstraintValidator<ConstDictRef, Object> {

View File

@@ -11,7 +11,7 @@ import java.lang.annotation.Target;
* 定义在Model或Dto对象中UTF-8编码的字符串字段长度的上限和下限和TextLengthValidator对象配合完成数据验证。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -9,7 +9,7 @@ import javax.validation.ConstraintValidatorContext;
* 数据字段自定义验证用于验证Model中UTF-8编码的字符串字段的最大长度和最小长度。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class TextLengthValidator implements ConstraintValidator<TextLength, String> {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.core.validator;
* 数据修改的验证分组。通常用于数据更新的场景。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public interface UpdateGroup {

View File

@@ -6,7 +6,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
* common-sequence模块的自动配置引导类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@EnableConfigurationProperties({IdGeneratorProperties.class})
public class IdGeneratorAutoConfigure {

View File

@@ -7,7 +7,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
* common-sequence模块的配置类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Data
@ConfigurationProperties(prefix = "sequence")

View File

@@ -9,7 +9,7 @@ import cn.hutool.core.util.IdUtil;
* WorkNodeId是通过配置文件静态指定的。而SnowflakeIdGenerator的WorkNodeId是由zk生成的。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public class BasicIdGenerator implements MyIdGenerator {

View File

@@ -4,7 +4,7 @@ package com.orange.demo.common.sequence.generator;
* 分布式Id生成器的统一接口。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
public interface MyIdGenerator {

View File

@@ -12,7 +12,7 @@ import javax.annotation.PostConstruct;
* 分布式Id生成器的封装类。该对象可根据配置选择不同的生成器实现类。
*
* @author Jerry
* @date 2020-10-19
* @date 2020-09-24
*/
@Component
public class IdGeneratorWrapper {

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>common</artifactId>
<groupId>com.orange.demo</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-swagger</artifactId>
<version>1.0.0</version>
<name>common-swagger</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>com.orange.demo</groupId>
<artifactId>common-core</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,56 @@
package com.orange.demo.common.swagger.config;
import com.orange.demo.common.core.annotation.MyRequestBody;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 自动加载bean的配置对象。
*
* @author Jerry
* @date 2020-09-24
*/
@EnableSwagger2
@EnableKnife4j
@EnableConfigurationProperties(SwaggerProperties.class)
@ConditionalOnProperty(prefix = "swagger", name = "enabled")
public class SwaggerAutoConfiguration {
@Bean
public Docket upmsDocket(SwaggerProperties properties) {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("1. 用户权限分组接口")
.ignoredParameterTypes(MyRequestBody.class)
.apiInfo(apiInfo(properties))
.select()
.apis(RequestHandlerSelectors.basePackage(properties.getBasePackage() + ".upms.controller"))
.paths(PathSelectors.any()).build();
}
@Bean
public Docket bizDocket(SwaggerProperties properties) {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("2. 业务应用分组接口")
.ignoredParameterTypes(MyRequestBody.class)
.apiInfo(apiInfo(properties))
.select()
.apis(RequestHandlerSelectors.basePackage(properties.getBasePackage() + ".app.controller"))
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo(SwaggerProperties properties) {
return new ApiInfoBuilder()
.title(properties.getTitle())
.description(properties.getDescription())
.version(properties.getVersion()).build();
}
}

View File

@@ -0,0 +1,44 @@
package com.orange.demo.common.swagger.config;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.ArrayList;
import java.util.List;
/**
* 配置参数对象。
*
* @author Jerry
* @date 2020-09-24
*/
@Data
@ConfigurationProperties("swagger")
public class SwaggerProperties {
/**
* 是否开启Swagger。
*/
private Boolean enabled;
/**
* Swagger解析的基础包路径。
**/
private String basePackage = "";
/**
* ApiInfo中的标题。
**/
private String title = "";
/**
* ApiInfo中的描述信息。
**/
private String description = "";
/**
* ApiInfo中的版本信息。
**/
private String version = "";
}

View File

@@ -0,0 +1,85 @@
package com.orange.demo.common.swagger.plugin;
import cn.hutool.core.lang.Assert;
import com.orange.demo.common.core.annotation.MyRequestBody;
import com.github.xiaoymin.knife4j.core.conf.Consts;
import javassist.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import springfox.documentation.service.ResolvedMethodParameter;
import java.util.List;
/**
* 通过字节码方式动态创建接口参数封装对象。
*
* @author Jerry
* @date 2020-09-24
*/
@Slf4j
public class ByteBodyUtils {
private static final ClassPool CLASS_POOL = ClassPool.getDefault();
public static Class<?> createDynamicModelClass(String name, List<ResolvedMethodParameter> parameters) {
String clazzName = Consts.BASE_PACKAGE_PREFIX + name;
try {
CtClass tmp = CLASS_POOL.getCtClass(clazzName);
if (tmp != null) {
tmp.detach();
}
} catch (NotFoundException e) {
// 需要吃掉这个异常。
}
CtClass ctClass = CLASS_POOL.makeClass(clazzName);
try {
int fieldCount = 0;
for (ResolvedMethodParameter dynamicParameter : parameters) {
// 因为在调用这个方法之前这些参数都包含MyRequestBody注解。
MyRequestBody myRequestBody =
dynamicParameter.findAnnotation(MyRequestBody.class).orNull();
Assert.notNull(myRequestBody);
String fieldName = dynamicParameter.defaultName().isPresent()
? dynamicParameter.defaultName().get() : "parameter";
if (StringUtils.isNotBlank(myRequestBody.value())) {
fieldName = myRequestBody.value();
}
ctClass.addField(createField(dynamicParameter, fieldName, ctClass));
fieldCount++;
}
if (fieldCount > 0) {
return ctClass.toClass();
}
} catch (Throwable e) {
log.error(e.getMessage());
}
return null;
}
private static CtField createField(ResolvedMethodParameter parameter, String parameterName, CtClass ctClass)
throws NotFoundException, CannotCompileException {
CtField field = new CtField(getFieldType(parameter.getParameterType().getErasedType()), parameterName, ctClass);
field.setModifiers(Modifier.PUBLIC);
return field;
}
private static CtClass getFieldType(Class<?> propetyType) {
CtClass fieldType = null;
try {
if (!propetyType.isAssignableFrom(Void.class)) {
fieldType = CLASS_POOL.get(propetyType.getName());
} else {
fieldType = CLASS_POOL.get(String.class.getName());
}
} catch (NotFoundException e) {
//抛异常
ClassClassPath path = new ClassClassPath(propetyType);
CLASS_POOL.insertClassPath(path);
try {
fieldType = CLASS_POOL.get(propetyType.getName());
} catch (NotFoundException e1) {
log.error(e1.getMessage(), e1);
}
}
return fieldType;
}
}

View File

@@ -0,0 +1,61 @@
package com.orange.demo.common.swagger.plugin;
import com.orange.demo.common.core.annotation.MyRequestBody;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.CaseFormat;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationModelsProviderPlugin;
import springfox.documentation.spi.service.contexts.RequestMappingContext;
import java.util.List;
import java.util.stream.Collectors;
/**
* 生成参数包装类的插件。
*
* @author Jerry
* @date 2020-09-24
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE + 200)
@ConditionalOnProperty(prefix = "swagger", name = "enabled")
public class DynamicBodyModelPlugin implements OperationModelsProviderPlugin {
private final TypeResolver typeResolver;
public DynamicBodyModelPlugin(TypeResolver typeResolver) {
this.typeResolver = typeResolver;
}
@Override
public void apply(RequestMappingContext context) {
List<ResolvedMethodParameter> parameterTypes = context.getParameters();
if (CollectionUtils.isEmpty(parameterTypes)) {
return;
}
List<ResolvedMethodParameter> bodyParameter = parameterTypes.stream()
.filter(p -> p.hasParameterAnnotation(MyRequestBody.class)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(bodyParameter)) {
return;
}
String groupName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, context.getGroupName());
String clazzName = groupName + StringUtils.capitalize(context.getName());
Class<?> clazz = ByteBodyUtils.createDynamicModelClass(clazzName, bodyParameter);
if (clazz != null) {
context.operationModelsBuilder().addInputParam(typeResolver.resolve(clazz));
}
}
@Override
public boolean supports(DocumentationType delimiter) {
//支持2.0版本
return delimiter == DocumentationType.SWAGGER_2;
}
}

View File

@@ -0,0 +1,64 @@
package com.orange.demo.common.swagger.plugin;
import com.orange.demo.common.core.annotation.MyRequestBody;
import com.google.common.base.CaseFormat;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spi.service.contexts.ParameterContext;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 构建操作接口参数对象的插件。
*
* @author Jerry
* @date 2020-09-24
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE + 102)
@ConditionalOnProperty(prefix = "swagger", name = "enabled")
public class DynamicBodyParameterBuilder implements OperationBuilderPlugin {
@Override
public void apply(OperationContext context) {
List<ResolvedMethodParameter> methodParameters = context.getParameters();
List<Parameter> parameters = new ArrayList<>();
if (CollectionUtils.isNotEmpty(methodParameters)) {
List<ResolvedMethodParameter> bodyParameter = methodParameters.stream()
.filter(p -> p.hasParameterAnnotation(MyRequestBody.class)).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(bodyParameter)) {
//构造model
String groupName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, context.getGroupName());
String clazzName = groupName + StringUtils.capitalize(context.getName());
ResolvedMethodParameter methodParameter = bodyParameter.get(0);
ParameterContext parameterContext = new ParameterContext(methodParameter,
new ParameterBuilder(),
context.getDocumentationContext(),
context.getGenericsNamingStrategy(),
context);
Parameter parameter = parameterContext.parameterBuilder()
.parameterType("body").modelRef(new ModelRef(clazzName)).name(clazzName).build();
parameters.add(parameter);
}
}
context.operationBuilder().parameters(parameters);
}
@Override
public boolean supports(DocumentationType delimiter) {
return delimiter == DocumentationType.SWAGGER_2;
}
}

View File

@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.orange.demo.common.swagger.config.SwaggerAutoConfiguration

View File

@@ -14,5 +14,6 @@
<modules>
<module>common-core</module>
<module>common-sequence</module>
<module>common-swagger</module>
</modules>
</project>