init
This commit is contained in:
22
src/main/java/com/senmesh/SFileApplication.java
Normal file
22
src/main/java/com/senmesh/SFileApplication.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.senmesh;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-16
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = {"com.senmesh"})
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
|
||||
@EnableScheduling
|
||||
public class SFileApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SFileApplication.class, args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.senmesh.codegenerator.config;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.senmesh.codegenerator.service.CodeService;
|
||||
import com.senmesh.codegenerator.service.SnowflakeIdWorker;
|
||||
import com.senmesh.codegenerator.service.generator.SnowFlakeCodeGenerator;
|
||||
import com.senmesh.codegenerator.service.impl.CodeServiceImpl;
|
||||
import com.senmesh.codegenerator.util.CodeUtils;
|
||||
import com.senmesh.common.CommonConfiguration;
|
||||
import com.senmesh.common.constant.CommonConstants;
|
||||
import com.senmesh.common.util.EnvironmentUtils;
|
||||
import com.senmesh.common.util.RequestUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 发号器配置类
|
||||
* @author sr on 2021-03-23
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(CommonConfiguration.class)
|
||||
@Slf4j
|
||||
public class CodeConfiguration {
|
||||
|
||||
public static final String PROP_WORID_PREFIX = "code.snowflake.workid";
|
||||
|
||||
/**
|
||||
* 默认编号生成器
|
||||
* @return
|
||||
* @author sr on 2021-03-23
|
||||
*/
|
||||
@Bean
|
||||
public SnowFlakeCodeGenerator snowFlakeCodeGenerator() {
|
||||
// 机器id
|
||||
String hostIp = RequestUtils.getHostIp();
|
||||
log.info("hostIp:" + hostIp);
|
||||
String workIdStr = EnvironmentUtils.getProperty(
|
||||
String.join(CommonConstants.POINT, PROP_WORID_PREFIX, hostIp));
|
||||
Long workId = 99l;
|
||||
try {
|
||||
if (StringUtils.isNoneBlank(workIdStr)) {
|
||||
workId = Long.valueOf(workIdStr);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(workId, 0);
|
||||
return new SnowFlakeCodeGenerator(idWorker);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编号service(根据类型分发不同的生成器)
|
||||
* @return
|
||||
* @author sr on 2021-03-23
|
||||
*/
|
||||
@Bean
|
||||
public CodeService codeService() {
|
||||
CodeService codeService = new CodeServiceImpl();
|
||||
CodeUtils.setCodeService(codeService);
|
||||
return codeService;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.senmesh.codegenerator.constant;
|
||||
|
||||
/**
|
||||
* 编号常量类
|
||||
* @author sr on 2019-09-15
|
||||
*/
|
||||
public class CodeConstants {
|
||||
|
||||
/** 生成器类型:默认(不可用) **/
|
||||
// public static final String GENERATOR_TYPE_DEFAULT = "DEFAULT";
|
||||
public static final String GENERATOR_TYPE_SNOW_FLAKE = "SnowFlake";
|
||||
|
||||
/** id默认长度 **/
|
||||
public static final int ID_DEFAULT_LENGTH = 5;
|
||||
|
||||
/** id默认补位字符 **/
|
||||
public static final char ID_DEFAULT_PAD = '0';
|
||||
/** id默认日期格式化 **/
|
||||
public static final DateFormatterEnum ID_DEFAULT_FORMATTER = DateFormatterEnum.YEAR;
|
||||
|
||||
/** -----异常信息----- **/
|
||||
public static final String CODE_GENERATE_ERROR = "编号生成失败";
|
||||
/** -----异常信息----- **/
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.senmesh.codegenerator.constant;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 日期formatter枚举
|
||||
* @author sr on 2019-12-03
|
||||
*/
|
||||
public enum DateFormatterEnum {
|
||||
|
||||
/** 年:yyyy **/
|
||||
YEAR(DateTimeFormatter.ofPattern("yyyy")),
|
||||
/** 年月:yyyyMM **/
|
||||
YM(DateTimeFormatter.ofPattern("yyyyMM")),
|
||||
/** 年月:yyMM **/
|
||||
YM2(DateTimeFormatter.ofPattern("yyMM")),
|
||||
/** 年月日:yyyyMMdd **/
|
||||
YMD(DateTimeFormatter.ofPattern("yyyyMMdd")),
|
||||
/** 年月日:yyMMdd **/
|
||||
YMD2(DateTimeFormatter.ofPattern("yyMMdd"));
|
||||
|
||||
private DateTimeFormatter formatter;
|
||||
|
||||
private DateFormatterEnum(DateTimeFormatter formatter){
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
public DateTimeFormatter getDateTimeFormatter() {
|
||||
return this.formatter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.senmesh.codegenerator.exception;
|
||||
|
||||
/**
|
||||
* 编号生成器异常
|
||||
* @author sr on 2019-12-03
|
||||
*/
|
||||
public class CodeGeneratorException extends RuntimeException{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 3558280270933232655L;
|
||||
|
||||
|
||||
public CodeGeneratorException() {}
|
||||
|
||||
public CodeGeneratorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CodeGeneratorException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public CodeGeneratorException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
25
src/main/java/com/senmesh/codegenerator/pojo/CodeParam.java
Normal file
25
src/main/java/com/senmesh/codegenerator/pojo/CodeParam.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.senmesh.codegenerator.pojo;
|
||||
|
||||
import com.senmesh.codegenerator.constant.CodeConstants;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.Builder.Default;
|
||||
|
||||
/**
|
||||
* 编码生成参数对象
|
||||
* @author sr on 2019-12-05
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class CodeParam {
|
||||
|
||||
/** 生成器类型 **/
|
||||
@Default
|
||||
private String generatorType = CodeConstants.GENERATOR_TYPE_SNOW_FLAKE;
|
||||
|
||||
/** 编码类型 **/
|
||||
private String type;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.senmesh.codegenerator.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.senmesh.codegenerator.pojo.CodeParam;
|
||||
|
||||
/**
|
||||
* 编号生成器 默认一套实现,如需重定义中间时间format和id长度,重写规则 重写规则,注意去发号器对应的数据库表(leaf_alloc)中添加对应type+时间(biz_tag)的记录
|
||||
*
|
||||
* @author sr on 2019-09-15
|
||||
*/
|
||||
public interface CodeGenerator<T extends CodeParam> {
|
||||
|
||||
/**
|
||||
* 自定义特定业务类型,即前缀
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2019-09-19
|
||||
*/
|
||||
String getType();
|
||||
|
||||
|
||||
/**
|
||||
* 根据生成规则获取编号
|
||||
*
|
||||
* @param codeParam
|
||||
* @return
|
||||
* @author sr on 2020-07-13
|
||||
*/
|
||||
String getCode(T codeParam);
|
||||
|
||||
/**
|
||||
* 批量根据生成规则获取编号
|
||||
*
|
||||
* @param codeParam
|
||||
* @return
|
||||
* @author sr on 2020-07-13
|
||||
*/
|
||||
List<String> batchCode(T codeParam, Integer batchNum);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.senmesh.codegenerator.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.senmesh.codegenerator.pojo.CodeParam;
|
||||
|
||||
/**
|
||||
* 编号service(根据类型分发不同的生成器)
|
||||
*
|
||||
* @author sr on 2019-09-15
|
||||
*/
|
||||
public interface CodeService {
|
||||
|
||||
/**
|
||||
* 根据生成规则获取编号
|
||||
*
|
||||
* @param codeParam
|
||||
* @return
|
||||
* @author sr on 2020-07-13
|
||||
*/
|
||||
String getCode(CodeParam codeParam);
|
||||
|
||||
/**
|
||||
* 批量根据生成规则获取编号
|
||||
*
|
||||
* @param codeParam
|
||||
* @param batchNum 批次数(1-1000)
|
||||
* @return
|
||||
* @author sr on 2020-07-13
|
||||
*/
|
||||
List<String> batchCode(CodeParam codeParam, Integer batchNum);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.senmesh.codegenerator.service;
|
||||
|
||||
/**
|
||||
* Twitter_Snowflake<br>
|
||||
* SnowFlake的结构如下(每部分用-分开):<br>
|
||||
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
|
||||
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
|
||||
* 41位时间戳(毫秒级),注意,41位时间戳不是存储当前时间的时间戳,而是存储时间戳的差值(当前时间戳 - 开始时间戳) 得到的值),这里的的开始时间戳,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间戳,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
|
||||
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
|
||||
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间戳)产生4096个ID序号<br>
|
||||
* 加起来刚好64位,为一个Long型。<br>
|
||||
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
|
||||
*/
|
||||
public class SnowflakeIdWorker {
|
||||
|
||||
// ==============================Fields===========================================
|
||||
/** 开始时间戳 (2015-01-01) */
|
||||
private final long twepoch = 1420041600000L;
|
||||
|
||||
/** 能容忍的系统时钟回拨时间(2秒) */
|
||||
private final long timeOffset = 2000L;
|
||||
|
||||
/** 机器id所占的位数 */
|
||||
private final long workerIdBits = 5L;
|
||||
|
||||
/** 数据标识id所占的位数 */
|
||||
private final long datacenterIdBits = 5L;
|
||||
|
||||
/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
|
||||
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
||||
|
||||
/** 支持的最大数据标识id,结果是31 */
|
||||
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
|
||||
|
||||
/** 序列在id中占的位数 */
|
||||
private final long sequenceBits = 12L;
|
||||
|
||||
/** 机器ID向左移12位 */
|
||||
private final long workerIdShift = sequenceBits;
|
||||
|
||||
/** 数据标识id向左移17位(12+5) */
|
||||
private final long datacenterIdShift = sequenceBits + workerIdBits;
|
||||
|
||||
/** 时间戳向左移22位(5+5+12) */
|
||||
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
|
||||
|
||||
/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
|
||||
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
|
||||
|
||||
/** 工作机器ID(0~31) */
|
||||
private long workerId;
|
||||
|
||||
/** 数据中心ID(0~31) */
|
||||
private long datacenterId;
|
||||
|
||||
/** 毫秒内序列(0~4095) */
|
||||
private long sequence = 0L;
|
||||
|
||||
/** 上次生成ID的时间戳 */
|
||||
private long lastTimestamp = -1L;
|
||||
|
||||
// ==============================Constructors=====================================
|
||||
/**
|
||||
* 构造函数
|
||||
* @param workerId 工作ID (0~31)
|
||||
* @param datacenterId 数据中心ID (0~31)
|
||||
*/
|
||||
public SnowflakeIdWorker(long workerId, long datacenterId) {
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
|
||||
}
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
|
||||
}
|
||||
this.workerId = workerId;
|
||||
this.datacenterId = datacenterId;
|
||||
}
|
||||
|
||||
// ==============================Methods==========================================
|
||||
/**
|
||||
* 获得下一个ID (该方法是线程安全的)
|
||||
* @return SnowflakeId
|
||||
*/
|
||||
public synchronized long nextId() {
|
||||
long timestamp = timeGen();
|
||||
|
||||
// 当前时间戳小于上一次ID生成的时间戳
|
||||
if (timestamp < lastTimestamp) {
|
||||
long offset = lastTimestamp - timestamp;
|
||||
// 系统时钟回退在容忍范围内,例如出现过闰秒
|
||||
if (offset < timeOffset) {
|
||||
timestamp = lastTimestamp;
|
||||
}
|
||||
// 系统时钟回退超出容忍范围,抛出异常
|
||||
else {
|
||||
throw new RuntimeException(String
|
||||
.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是同一时间生成的,则进行毫秒内序列
|
||||
if (lastTimestamp == timestamp) {
|
||||
sequence = (sequence + 1) & sequenceMask;
|
||||
// 毫秒内序列溢出
|
||||
if (sequence == 0) {
|
||||
// 阻塞到下一个毫秒,获得新的时间戳
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
}
|
||||
// 时间戳改变,毫秒内序列重置
|
||||
else {
|
||||
sequence = 0L;
|
||||
}
|
||||
|
||||
// 上次生成ID的时间戳
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
// 移位并通过或运算拼到一起组成64位的ID
|
||||
return ((timestamp - twepoch) << timestampLeftShift) //
|
||||
| (datacenterId << datacenterIdShift) //
|
||||
| (workerId << workerIdShift) //
|
||||
| sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻塞到下一个毫秒,直到获得新的时间戳
|
||||
* @param lastTimestamp 上次生成ID的时间戳
|
||||
* @return 当前时间戳
|
||||
*/
|
||||
protected long tilNextMillis(long lastTimestamp) {
|
||||
long timestamp = timeGen();
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = timeGen();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回以毫秒为单位的当前时间
|
||||
* @return 当前时间(毫秒)
|
||||
*/
|
||||
protected long timeGen() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// ==============================Test=============================================
|
||||
/** 测试 */
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.out.println("1000011111010000000111110011100110011110000000000000000001100".length());
|
||||
// SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
|
||||
// for (int i = 0; i < 1000; i++) {
|
||||
// long id = idWorker.nextId();
|
||||
// System.out.println(Long.toBinaryString(id));
|
||||
// System.out.println(id);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.senmesh.codegenerator.service.generator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.senmesh.codegenerator.constant.CodeConstants;
|
||||
import com.senmesh.codegenerator.pojo.CodeParam;
|
||||
import com.senmesh.codegenerator.service.CodeGenerator;
|
||||
import com.senmesh.codegenerator.service.SnowflakeIdWorker;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 默认编号生成器
|
||||
*
|
||||
* @author sr on 2019-09-15
|
||||
*/
|
||||
@Slf4j
|
||||
public class SnowFlakeCodeGenerator implements CodeGenerator<CodeParam> {
|
||||
|
||||
private SnowflakeIdWorker snowflakeIdWorker;
|
||||
|
||||
public SnowFlakeCodeGenerator(SnowflakeIdWorker snowflakeIdWorker) {
|
||||
this.snowflakeIdWorker = snowflakeIdWorker;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return CodeConstants.GENERATOR_TYPE_SNOW_FLAKE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode(CodeParam codeParam) {
|
||||
return codeParam.getType() + snowflakeIdWorker.nextId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> batchCode(CodeParam codeParam, Integer batchNum) {
|
||||
List<String> ids = Lists.newArrayListWithCapacity(batchNum);
|
||||
for (int i = 0; i < batchNum; i++) {
|
||||
ids.add(this.getCode(codeParam));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.senmesh.codegenerator.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.senmesh.codegenerator.constant.CodeConstants;
|
||||
import com.senmesh.codegenerator.pojo.CodeParam;
|
||||
import com.senmesh.codegenerator.service.CodeGenerator;
|
||||
import com.senmesh.codegenerator.service.CodeService;
|
||||
|
||||
/**
|
||||
* 编号service实现类
|
||||
*
|
||||
* @author sr on 2019-09-15
|
||||
*/
|
||||
public class CodeServiceImpl implements CodeService {
|
||||
|
||||
private Map<String, CodeGenerator<CodeParam>> codeGenerators = Maps.newHashMap();
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Autowired
|
||||
private void codeGenerateResolver(List<CodeGenerator> resolvers) {
|
||||
resolvers.forEach(resolver -> codeGenerators.put(resolver.getType(), resolver));
|
||||
}
|
||||
|
||||
private CodeGenerator<CodeParam> getResolver(String type) {
|
||||
CodeGenerator<CodeParam> resolver = codeGenerators.get(type);
|
||||
if (resolver == null) {
|
||||
resolver = codeGenerators.get(CodeConstants.GENERATOR_TYPE_SNOW_FLAKE);
|
||||
}
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode(CodeParam codeParam) {
|
||||
return getResolver(codeParam.getGeneratorType()).getCode(codeParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> batchCode(CodeParam codeParam, Integer batchNum) {
|
||||
return getResolver(codeParam.getGeneratorType()).batchCode(codeParam, batchNum);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
48
src/main/java/com/senmesh/codegenerator/util/CodeUtils.java
Normal file
48
src/main/java/com/senmesh/codegenerator/util/CodeUtils.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.senmesh.codegenerator.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.senmesh.codegenerator.pojo.CodeParam;
|
||||
import com.senmesh.codegenerator.service.CodeService;
|
||||
import com.senmesh.component.constants.CodeTypeEnum;
|
||||
|
||||
/**
|
||||
* 发号器工具类
|
||||
* @author sr on 2021-03-23
|
||||
*/
|
||||
public abstract class CodeUtils {
|
||||
|
||||
private static CodeService codeService;
|
||||
|
||||
public static void setCodeService(CodeService codeService) {
|
||||
CodeUtils.codeService = codeService;
|
||||
}
|
||||
|
||||
public static String getCode(CodeTypeEnum codeTypeEnum) {
|
||||
return codeService.getCode(codeTypeEnum.getCodeParam());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据生成规则获取编号
|
||||
*
|
||||
* @param codeParam
|
||||
* @return
|
||||
* @author sr on 2021-03-23
|
||||
*/
|
||||
public static String getCode(CodeParam codeParam) {
|
||||
return codeService.getCode(codeParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量根据生成规则获取编号
|
||||
*
|
||||
* @param codeParam
|
||||
* @param batchNum
|
||||
* @return
|
||||
* @author sr on 2021-03-23
|
||||
*/
|
||||
public static List<String> batchCode(CodeParam codeParam, Integer batchNum) {
|
||||
return codeService.batchCode(codeParam, batchNum);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.senmesh.codesetting.constant;
|
||||
|
||||
public interface CodeSettingConstants {
|
||||
/**
|
||||
* 编码配置数据类型
|
||||
*/
|
||||
public static final String CODE_SETTING_DATA_TYPE = "code_setting_data_type";
|
||||
|
||||
public class CodeSettingDataType {
|
||||
|
||||
public static final String STRING = "1";
|
||||
|
||||
public static final String NUMBER = "2";
|
||||
|
||||
public static final String DATE = "3";
|
||||
|
||||
public static final String BOOL = "4";
|
||||
|
||||
public static final String RADIO = "5";
|
||||
|
||||
public static final String CHECKBOX = "6";
|
||||
|
||||
public static final String FILE = "7";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码配置模块:机构配置
|
||||
**/
|
||||
public static final String CODE_SETTING_TYPE_CONFIG = "1";
|
||||
|
||||
/**
|
||||
* 编码配置默认级别
|
||||
**/
|
||||
public static final String CODE_SETTING_LEVEL_DEFAULT = "1,2,3,4";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.senmesh.codesetting.controller;
|
||||
|
||||
import com.senmesh.codesetting.dto.CodeSettingDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingOperatorDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingPageQueryDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingQueryDTO;
|
||||
import com.senmesh.codesetting.service.CodeSettingService;
|
||||
import com.senmesh.common.AlitaResult;
|
||||
import com.senmesh.tkmybatis.pojo.Page;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@Api(tags = "编码表")
|
||||
@RestController
|
||||
@RequestMapping("code_setting")
|
||||
public class CodeSettingController {
|
||||
|
||||
@Autowired
|
||||
private CodeSettingService codeSettingService;
|
||||
|
||||
@PostMapping
|
||||
@ApiOperation("编码表-创建")
|
||||
public AlitaResult<CodeSettingDTO> create(@RequestBody CodeSettingOperatorDTO operatorDTO) {
|
||||
return AlitaResult.success(codeSettingService.create(operatorDTO));
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@ApiOperation("编码表-修改")
|
||||
public AlitaResult<CodeSettingDTO> modify(@RequestBody CodeSettingOperatorDTO operatorDTO) {
|
||||
return AlitaResult.success(codeSettingService.modify(operatorDTO));
|
||||
}
|
||||
|
||||
@DeleteMapping("{id}")
|
||||
@ApiOperation("编码表-删除")
|
||||
public AlitaResult<CodeSettingDTO> delete(@PathVariable("id") Long id) {
|
||||
return AlitaResult.success(codeSettingService.delete(id));
|
||||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
@ApiOperation("编码表-查询单个")
|
||||
public AlitaResult<CodeSettingDTO> findById(@PathVariable("id") Long id) {
|
||||
return AlitaResult.success(codeSettingService.findById(id));
|
||||
}
|
||||
|
||||
@GetMapping("list")
|
||||
@ApiOperation("编码表-列表查询")
|
||||
public AlitaResult<List<CodeSettingDTO>> list(CodeSettingQueryDTO queryDTO) {
|
||||
return AlitaResult.success(codeSettingService.list(queryDTO));
|
||||
}
|
||||
|
||||
@GetMapping("page")
|
||||
@ApiOperation("编码表-分页查询")
|
||||
public AlitaResult<Page<CodeSettingDTO>> page(CodeSettingPageQueryDTO queryDTO) {
|
||||
codeSettingService.page(queryDTO);
|
||||
return AlitaResult.success(queryDTO.getPageResult());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.senmesh.codesetting.convert;
|
||||
|
||||
import com.senmesh.codesetting.dto.CodeSettingDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingOperatorDTO;
|
||||
import com.senmesh.codesetting.entity.CodeSetting;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@Mapper
|
||||
public interface CodeSettingConvert {
|
||||
CodeSettingConvert INSTANCE = Mappers.getMapper(CodeSettingConvert.class);
|
||||
|
||||
CodeSetting convert(CodeSettingDTO dto);
|
||||
|
||||
CodeSettingDTO convert(CodeSetting entity);
|
||||
|
||||
CodeSetting convert(CodeSettingOperatorDTO dto);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.senmesh.codesetting.dao;
|
||||
|
||||
import com.senmesh.codesetting.dto.CodeSettingDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingPageQueryDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingQueryDTO;
|
||||
import com.senmesh.codesetting.entity.CodeSetting;
|
||||
import com.senmesh.tkmybatis.mybatis.MyMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@Mapper
|
||||
public interface CodeSettingMapper extends MyMapper<CodeSetting> {
|
||||
|
||||
List<CodeSettingDTO> page(@Param("param") CodeSettingPageQueryDTO queryDTO);
|
||||
|
||||
List<CodeSettingDTO> list(@Param("param") CodeSettingQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 根据类型查询
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
@Select("select * from xs_code_setting where type = #{type} and deleted = 0")
|
||||
List<CodeSetting> queryByType(String type);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.senmesh.codesetting.dto;
|
||||
|
||||
import com.senmesh.common.dto.BaseDTO;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@ApiModel("编码表")
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CodeSettingDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("编码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty("类型 模板编码、配置编码")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("数据类型")
|
||||
private String dataType;
|
||||
|
||||
@ApiModelProperty("级别 平台、渠道、定制机构、普通机构")
|
||||
private String level;
|
||||
|
||||
@ApiModelProperty("数据值")
|
||||
private String dataFormat;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.senmesh.codesetting.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@ApiModel("编码表")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CodeSettingOperatorDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8836210011277521607L;
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("编码")
|
||||
@NotEmpty(message = "配置项编码不能为空")
|
||||
@Length(min = 1, max = 64, message = "配置项编码长度超限")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("名称")
|
||||
@NotEmpty(message = "配置项名称不能为空")
|
||||
@Length(min = 1, max = 128, message = "配置项名称长度超限")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
// @NotEmpty(message = "备注不能为空")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty("数据值")
|
||||
private String dataFormat;
|
||||
|
||||
@ApiModelProperty("类型 模板编码、配置编码")
|
||||
@NotEmpty(message = "配置类型不能为空")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("数据类型")
|
||||
@NotEmpty(message = "配置参数类型不能为空")
|
||||
private String dataType;
|
||||
|
||||
@ApiModelProperty("级别 平台、渠道、定制机构、普通机构")
|
||||
@NotEmpty(message = "配置应用级别不能为空")
|
||||
private String level;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.senmesh.codesetting.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.senmesh.common.annotation.trimAndUpper.TrimAndUpper;
|
||||
import com.senmesh.common.dto.PageQueryDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
|
||||
@ApiModel("编码表")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CodeSettingPageQueryDTO extends PageQueryDTO<CodeSettingDTO> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("编码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("编码 (模糊匹配)")
|
||||
@TrimAndUpper(TrimAndUpper.ExecuteType.TRIM)
|
||||
private String codeLike;
|
||||
|
||||
@ApiModelProperty("名称 (模糊匹配)")
|
||||
@TrimAndUpper(TrimAndUpper.ExecuteType.TRIM)
|
||||
private String nameLike;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty("类型 模板编码、配置编码")
|
||||
@TrimAndUpper(TrimAndUpper.ExecuteType.TRIM)
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("数据类型")
|
||||
private String dataType;
|
||||
|
||||
@ApiModelProperty("级别 平台、渠道、定制机构、普通机构")
|
||||
private String level;
|
||||
|
||||
@ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTimeStart;
|
||||
|
||||
@ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTimeEnd;
|
||||
|
||||
@ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTimeStart;
|
||||
|
||||
@ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTimeEnd;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.senmesh.codesetting.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@ApiModel("编码表")
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CodeSettingQueryDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("编码")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("编码 (模糊匹配)")
|
||||
private String codeLike;
|
||||
|
||||
@ApiModelProperty("名称 (模糊匹配)")
|
||||
private String nameLike;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty("类型 模板编码、配置编码")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty("数据类型")
|
||||
private String dataType;
|
||||
|
||||
@ApiModelProperty("级别 平台、渠道、定制机构、普通机构")
|
||||
private String level;
|
||||
|
||||
@ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTimeStart;
|
||||
|
||||
@ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTimeEnd;
|
||||
|
||||
@ApiModelProperty("修改时间起,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTimeStart;
|
||||
|
||||
@ApiModelProperty("修改时间止,格式 (yyyy-MM-dd HH:mm:ss)")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTimeEnd;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.senmesh.codesetting.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.senmesh.common.entity.BaseEntity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@TableName("xs_code_setting")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CodeSetting extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 类型 模板编码、配置编码
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String dataType;
|
||||
/**
|
||||
* 数据格式编号
|
||||
*/
|
||||
private String dataFormat;
|
||||
/**
|
||||
* 级别 平台、渠道、定制机构、普通机构
|
||||
*/
|
||||
private String level;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.senmesh.codesetting.dao.CodeSettingMapper">
|
||||
|
||||
<select id="list" resultType="com.senmesh.codesetting.dto.CodeSettingDTO">
|
||||
SELECT t.*
|
||||
<include refid="queryFromSql"></include>
|
||||
</select>
|
||||
|
||||
<select id="page" resultType="com.senmesh.codesetting.dto.CodeSettingDTO">
|
||||
SELECT t.*
|
||||
<include refid="queryFromSql"></include>
|
||||
</select>
|
||||
|
||||
<sql id="queryFromSql">
|
||||
FROM
|
||||
xs_code_setting t
|
||||
WHERE t.deleted = 0
|
||||
<if test='param.id != null'>
|
||||
AND t.id = #{param.id}
|
||||
</if>
|
||||
<if test='param.code != null and param.code.trim() != ""'>
|
||||
AND t.code = #{param.code}
|
||||
</if>
|
||||
<if test='param.codeLike != null and param.codeLike.trim() != ""'>
|
||||
<bind name="codeLike" value="'%' + param.codeLike + '%'"/>
|
||||
AND t.code like #{codeLike}
|
||||
</if>
|
||||
<if test='param.nameLike != null and param.nameLike.trim() != ""'>
|
||||
<bind name="nameLike" value="'%' + param.nameLike + '%'"/>
|
||||
AND t.name like #{nameLike}
|
||||
</if>
|
||||
<if test='param.remark != null and param.remark.trim() != ""'>
|
||||
AND t.remark = #{param.remark}
|
||||
</if>
|
||||
<if test='param.type != null and param.type.trim() != ""'>
|
||||
AND t.type = #{param.type}
|
||||
</if>
|
||||
<if test='param.dataType != null and param.dataType.trim() != ""'>
|
||||
AND t.data_type = #{param.dataType}
|
||||
</if>
|
||||
<if test='param.level != null and param.level.trim() != ""'>
|
||||
AND FIND_IN_SET(CONCAT(#{param.level},""),t.level)
|
||||
</if>
|
||||
<if test='param.createTimeStart != null'>
|
||||
AND t.create_time >= #{param.createTimeStart}
|
||||
</if>
|
||||
<if test='param.createTimeEnd != null'>
|
||||
AND t.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test='param.updateTimeStart != null'>
|
||||
AND t.update_time >= #{param.updateTimeStart}
|
||||
</if>
|
||||
<if test='param.updateTimeEnd != null'>
|
||||
AND t.update_time <= #{param.updateTimeEnd}
|
||||
</if>
|
||||
ORDER BY t.id DESC
|
||||
</sql>
|
||||
</mapper>
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.senmesh.codesetting.service;
|
||||
|
||||
import com.senmesh.codesetting.dto.CodeSettingDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingOperatorDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingPageQueryDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingQueryDTO;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.groups.Default;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@Validated(Default.class)
|
||||
public interface CodeSettingService {
|
||||
|
||||
/**
|
||||
* 编码表 - 创建
|
||||
*
|
||||
* @param operatorDto 操作dto
|
||||
* @return {@link CodeSettingDTO}
|
||||
*/
|
||||
CodeSettingDTO create(@Valid CodeSettingOperatorDTO operatorDto);
|
||||
|
||||
/**
|
||||
* 校验编码是否存在
|
||||
*
|
||||
* @param code 代码
|
||||
* @param codeSettingId 编码ID
|
||||
* @return boolean true: 存在重复编码
|
||||
*/
|
||||
boolean checkCode(String code, Long codeSettingId);
|
||||
|
||||
/**
|
||||
* 编码表 - 修改
|
||||
*
|
||||
* @param operatorDto 操作dto
|
||||
* @return {@link CodeSettingDTO}
|
||||
*/
|
||||
CodeSettingDTO modify(@Valid CodeSettingOperatorDTO operatorDto);
|
||||
|
||||
/**
|
||||
* 编码表 - 删除
|
||||
*
|
||||
* @param id id
|
||||
* @return {@link CodeSettingDTO}
|
||||
*/
|
||||
CodeSettingDTO delete(Long id);
|
||||
|
||||
/**
|
||||
* 编码表 - 根据ID查询单个
|
||||
*
|
||||
* @param id id
|
||||
* @return {@link CodeSettingDTO}
|
||||
*/
|
||||
CodeSettingDTO findById(Long id);
|
||||
|
||||
/**
|
||||
* 编码表 - 列表查询
|
||||
*
|
||||
* @param queryDTO 列表查询dto
|
||||
* @return {@link List}<{@link CodeSettingDTO}>
|
||||
*/
|
||||
List<CodeSettingDTO> list(CodeSettingQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 编码表 - 分页查询
|
||||
*
|
||||
* @param queryDTO 分页查询dto
|
||||
* @return {@link CodeSettingDTO}
|
||||
*/
|
||||
List<CodeSettingDTO> page(CodeSettingPageQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 根据type和code查询
|
||||
*
|
||||
* @param codeSettingType
|
||||
* @param orgType
|
||||
* @return
|
||||
*/
|
||||
List<com.senmesh.codesetting.dto.CodeSettingDTO> queryCode(String codeSettingType, String orgType);
|
||||
|
||||
/**
|
||||
* 根据code查询
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
CodeSettingDTO getByCode(String code);
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.senmesh.codesetting.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.senmesh.codesetting.convert.CodeSettingConvert;
|
||||
import com.senmesh.codesetting.dao.CodeSettingMapper;
|
||||
import com.senmesh.codesetting.dto.CodeSettingDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingOperatorDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingPageQueryDTO;
|
||||
import com.senmesh.codesetting.dto.CodeSettingQueryDTO;
|
||||
import com.senmesh.codesetting.entity.CodeSetting;
|
||||
import com.senmesh.codesetting.service.CodeSettingService;
|
||||
import com.senmesh.common.constant.CommonConstants;
|
||||
import com.senmesh.common.exception.util.Assert;
|
||||
import com.senmesh.common.util.UserContextHolder;
|
||||
import com.senmesh.config.dao.ConfigMapper;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 编码表
|
||||
*
|
||||
* @author chenyun chenyun.home@outlook.com
|
||||
* @since 1.0.0 2023-01-04
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CodeSettingServiceImpl implements CodeSettingService {
|
||||
|
||||
@Resource
|
||||
private CodeSettingMapper codeSettingMapper;
|
||||
|
||||
@Resource
|
||||
private ConfigMapper configMapper;
|
||||
|
||||
@Override
|
||||
public CodeSettingDTO create(CodeSettingOperatorDTO operatorDto) {
|
||||
Assert.isTrue(!checkCode(operatorDto.getCode(), null), "配置项编码已存在");
|
||||
CodeSetting codeSetting = CodeSettingConvert.INSTANCE.convert(operatorDto);
|
||||
codeSettingMapper.saveEntity(codeSetting);
|
||||
return CodeSettingConvert.INSTANCE.convert(codeSetting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkCode(String code, Long codeSettingId) {
|
||||
return codeSettingMapper.existsEntity(CodeSetting.builder().code(code).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSettingDTO modify(CodeSettingOperatorDTO operatorDto) {
|
||||
CodeSettingDTO codeSettingDto = this.findById(operatorDto.getId());
|
||||
if (Objects.isNull(codeSettingDto)) {
|
||||
return null;
|
||||
}
|
||||
Assert.isTrue(!checkCode(operatorDto.getCode(), operatorDto.getId()), "配置项编码已存在");
|
||||
CodeSetting codeSetting = CodeSettingConvert.INSTANCE.convert(operatorDto);
|
||||
codeSettingMapper.updateEntity(codeSetting);
|
||||
return this.findById(operatorDto.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSettingDTO delete(Long id) {
|
||||
CodeSettingDTO codeSettingDto = this.findById(id);
|
||||
if (Objects.isNull(codeSettingDto)) {
|
||||
return null;
|
||||
}
|
||||
CodeSetting codeSetting = CodeSetting.builder().build();
|
||||
codeSetting.setId(id);
|
||||
codeSettingMapper.deleteEntity(codeSetting, UserContextHolder.getLoginUserId());
|
||||
// 删除配置项的时候,同步删除配置项下的配置
|
||||
configMapper.batchDelete(codeSettingDto.getCode(), UserContextHolder.getExistLoginUserId());
|
||||
return codeSettingDto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSettingDTO findById(Long id) {
|
||||
CodeSetting codeSetting = codeSettingMapper.getById(id);
|
||||
if (Objects.isNull(codeSetting)) {
|
||||
return null;
|
||||
}
|
||||
return CodeSettingConvert.INSTANCE.convert(codeSetting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CodeSettingDTO> list(CodeSettingQueryDTO queryDTO) {
|
||||
return codeSettingMapper.list(queryDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CodeSettingDTO> page(CodeSettingPageQueryDTO queryDTO) {
|
||||
return codeSettingMapper.page(queryDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CodeSettingDTO> queryCode(String codeSettingType, String orgType) {
|
||||
List<CodeSetting> codeSettings = codeSettingMapper.queryByType(codeSettingType);
|
||||
return codeSettings.stream()
|
||||
.filter(codeSetting -> ArrayUtils
|
||||
.contains(codeSetting.getLevel().split(CommonConstants.COMMA), orgType))
|
||||
.map(CodeSettingConvert.INSTANCE::convert).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSettingDTO getByCode(String code) {
|
||||
List<CodeSettingDTO> list = this.list(CodeSettingQueryDTO.builder().code(code).build());
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return null;
|
||||
}
|
||||
return list.get(0);
|
||||
}
|
||||
}
|
||||
253
src/main/java/com/senmesh/common/AlitaResult.java
Normal file
253
src/main/java/com/senmesh/common/AlitaResult.java
Normal file
@@ -0,0 +1,253 @@
|
||||
package com.senmesh.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.senmesh.sdk.common.constant.SdkConstants;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 用于 ajax 请求的响应工具类
|
||||
*
|
||||
* @author guhong
|
||||
* @date 2019/8/19
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AlitaResult<T> implements Serializable {
|
||||
|
||||
/** */
|
||||
private static final long serialVersionUID = 5933105804003541576L;
|
||||
|
||||
/** 未登录 * */
|
||||
public static final String UN_LOGIN_CODE = "401";
|
||||
/** 无权限 * */
|
||||
public static final String NO_AUTHORITY_CODE = "402";
|
||||
/** 无查询信息 * */
|
||||
public static final String NO_RESULT_CODE = "405";
|
||||
/** 登录用户多机构 * */
|
||||
public static final String DUPLICATE_ORG_CODE = "600";
|
||||
/** 登录用户多用户 * */
|
||||
public static final String DUPLICATE_USER_CODE = "601";
|
||||
/** 用户未实名 * */
|
||||
public static final String UN_AUTH_CODE = "602";
|
||||
/** 用户更换token **/
|
||||
public static final String CHANGE_TOKEN_CODE = "603";
|
||||
/** 用户未绑定手机号 **/
|
||||
public static final String UN_BINDING_PHONE = "604";
|
||||
/** 登录用户相关异常 **/
|
||||
public static final String LOGIN_ERROR_CODE = "666";
|
||||
/** 系统异常 * */
|
||||
public static final String SYSTEM_ERROR_CODE = "999";
|
||||
/** 业务异常 **/
|
||||
public static final String BUSINESS_ERROR_CODE = "700";
|
||||
/** 校验异常 * */
|
||||
public static final String VALIDATION_ERROR_CODE = "555";
|
||||
/** 操作成功 * */
|
||||
public static final String SUCCESS_CODE = "200";
|
||||
|
||||
public static final String CHANG_TOKEN_MSG = "token变更";
|
||||
|
||||
/** 链路id **/
|
||||
private String requestId;
|
||||
/** 响应信息 */
|
||||
private String msg;
|
||||
/** 响应code */
|
||||
private String code;
|
||||
/** 是否成功 */
|
||||
private Boolean success;
|
||||
/** 操作成功,响应数据 */
|
||||
private T data;
|
||||
/** 操作失败结果 **/
|
||||
private Object errorData;
|
||||
|
||||
/** 临时json **/
|
||||
@JsonIgnore
|
||||
private String tempJson;
|
||||
|
||||
public AlitaResult(String code, String msg, boolean success, T data) {
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
this.success = success;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public AlitaResult(String code, String msg, Serializable errorData) {
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
this.success = false;
|
||||
this.errorData = errorData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个成功的响应对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> success() {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个成功的响应对象
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> success(T data) {
|
||||
return new AlitaResult<T>(SUCCESS_CODE, "请求成功", true, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个成功的响应对象
|
||||
*
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> success(String msg, T data) {
|
||||
return new AlitaResult<T>(SUCCESS_CODE, msg, true, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个失败的响应对象
|
||||
*
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> error(String msg) {
|
||||
return new AlitaResult<T>(SYSTEM_ERROR_CODE, msg, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个失败的响应对象
|
||||
*
|
||||
* @param code
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> error(String code, String msg) {
|
||||
return new AlitaResult<T>(code, msg, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个失败的响应对象
|
||||
*
|
||||
* @param code
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> error(String code, String msg, T data) {
|
||||
return new AlitaResult<T>(code, msg, false, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个失败的响应对象
|
||||
*
|
||||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> error(String msg, T data) {
|
||||
return new AlitaResult<T>(SYSTEM_ERROR_CODE, msg, false, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建业务异常对象
|
||||
*
|
||||
* @param <T>
|
||||
* @param msg
|
||||
* @return
|
||||
* @author sr on 2020-07-02
|
||||
*/
|
||||
public static <T> AlitaResult<T> bizError(String msg) {
|
||||
return new AlitaResult<T>(BUSINESS_ERROR_CODE, msg, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个未登录响应对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static <T> AlitaResult<T> unLogin() {
|
||||
return new AlitaResult<T>(UN_LOGIN_CODE, "请先登录", false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建未实名响应对象
|
||||
* @param <T>
|
||||
* @return
|
||||
* @author sr on 2021-06-30
|
||||
*/
|
||||
public static <T> AlitaResult<T> unAuth() {
|
||||
return new AlitaResult<T>(UN_AUTH_CODE, "请先实名", false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建未绑定手机号响应对象
|
||||
* @param <T>
|
||||
* @return
|
||||
* @author sr on 2021-06-30
|
||||
*/
|
||||
public static <T> AlitaResult<T> unBinding() {
|
||||
return new AlitaResult<T>(UN_BINDING_PHONE, "请先绑定手机号", false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个未登录响应对象
|
||||
*
|
||||
* @param loginUrl 登录地址
|
||||
* @return
|
||||
* @author sr on 2019-12-29
|
||||
*/
|
||||
public static AlitaResult<String> unLogin(String loginUrl) {
|
||||
return new AlitaResult<String>(UN_LOGIN_CODE, "请先登录", false, loginUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更换token
|
||||
* @param <T>
|
||||
* @param token
|
||||
* @return
|
||||
* @author sr on 2021-08-02
|
||||
*/
|
||||
public static <T> AlitaResult<T> changeToken(Serializable token) {
|
||||
return new AlitaResult<T>(AlitaResult.CHANGE_TOKEN_CODE, CHANG_TOKEN_MSG, token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个未登录响应对象
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2019-12-29
|
||||
*/
|
||||
public static <T> AlitaResult<T> noResult() {
|
||||
return new AlitaResult<T>(NO_RESULT_CODE, "无查询信息", false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接口调用失败,未能拿到返回对象
|
||||
*
|
||||
* @param <T>
|
||||
* @param msg
|
||||
* @return
|
||||
* @author sr on 2020-04-10
|
||||
*/
|
||||
public static <T> AlitaResult<T> sdkInvokeNotReachError(String msg) {
|
||||
return new AlitaResult<T>(SdkConstants.SDK_INVOKE_NOT_REACH_CODE, msg, false, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"hiding", "unchecked"})
|
||||
public <T> AlitaResult<T> setRequestId(String requestId){
|
||||
this.requestId = requestId;
|
||||
return (AlitaResult<T>) this;
|
||||
}
|
||||
|
||||
public <T> AlitaResult<T> setTempJson(String tempJson){
|
||||
this.tempJson = tempJson;
|
||||
return (AlitaResult<T>) this;
|
||||
}
|
||||
|
||||
}
|
||||
110
src/main/java/com/senmesh/common/CommonConfiguration.java
Normal file
110
src/main/java/com/senmesh/common/CommonConfiguration.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package com.senmesh.common;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.senmesh.common.cache.DefaultCacheProvider;
|
||||
import com.senmesh.common.cache.ICacheProvider;
|
||||
import com.senmesh.common.log.ILogProvider;
|
||||
import com.senmesh.common.log.provider.Slf4jLogProvider;
|
||||
import com.senmesh.common.log.util.LogUtils;
|
||||
import com.senmesh.common.service.IMockProvider;
|
||||
import com.senmesh.common.service.IMockProvider.DefaultMockProvider;
|
||||
import com.senmesh.common.util.EnvironmentUtils;
|
||||
import com.senmesh.common.util.MockUtils;
|
||||
import com.senmesh.component.file.service.IFileStorage;
|
||||
import com.senmesh.component.file.service.storage.LocalFileStorage;
|
||||
import com.senmesh.component.file.util.FileStorageUtils;
|
||||
|
||||
import lombok.var;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-07-24
|
||||
*/
|
||||
@Configuration
|
||||
public class CommonConfiguration {
|
||||
|
||||
@Bean
|
||||
EnvironmentUtils environmentUtils(Environment environment) {
|
||||
return new EnvironmentUtils(environment);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ICacheProvider.class)
|
||||
@Order(100)
|
||||
DefaultCacheProvider defauCacheProvider() {
|
||||
return new DefaultCacheProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(100)
|
||||
@ConditionalOnMissingBean(ILogProvider.class)
|
||||
Slf4jLogProvider slf4jLogProvider() {
|
||||
return new Slf4jLogProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(200)
|
||||
LogUtils logUtils(ILogProvider iLogProvider) {
|
||||
LogUtils logUtils = new LogUtils();
|
||||
logUtils.setLogProvider(iLogProvider);
|
||||
return logUtils;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(IFileStorage.class)
|
||||
public LocalFileStorage localFileStorage() {
|
||||
return new LocalFileStorage();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FileStorageUtils fileStorageUtils(IFileStorage fileStorage) {
|
||||
return new FileStorageUtils(fileStorage);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(IMockProvider.class)
|
||||
public IMockProvider defaultMockProvider() {
|
||||
return new DefaultMockProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MockUtils mockUtils(IMockProvider mockProvider) {
|
||||
return new MockUtils(mockProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* requestbody string trim
|
||||
* @return
|
||||
* @author sr on 2024-04-19
|
||||
*/
|
||||
@Bean
|
||||
public SimpleModule stringDeserializerModule() {
|
||||
final var module = new SimpleModule();
|
||||
module.addDeserializer(String.class, new StringDeserializer() {
|
||||
@Override
|
||||
public String deserialize(JsonParser p, DeserializationContext ctx) throws java.io.IOException {
|
||||
final var value = super.deserialize(p, ctx);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final var trimmed = value.trim();
|
||||
if (trimmed.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
});
|
||||
return module;
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/com/senmesh/common/CoreConfiguration.java
Normal file
26
src/main/java/com/senmesh/common/CoreConfiguration.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.senmesh.common;
|
||||
|
||||
import org.jasypt.encryption.StringEncryptor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.senmesh.common.trace.DefaultTracer;
|
||||
import com.senmesh.common.trace.ITracer;
|
||||
import com.senmesh.common.util.JasyptUtils;
|
||||
|
||||
@Configuration
|
||||
public class CoreConfiguration {
|
||||
|
||||
@Bean
|
||||
JasyptUtils jasyptUtils(StringEncryptor stringEncryptor) {
|
||||
return new JasyptUtils(stringEncryptor);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(value = ITracer.class)
|
||||
ITracer defaultTracer() {
|
||||
return new DefaultTracer();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.senmesh.common.actuate.health.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 监控健康信息
|
||||
*
|
||||
* @author sr on 2020-07-08
|
||||
* @param <T>
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class HealthDTO<T> {
|
||||
|
||||
private String status;
|
||||
|
||||
private T details;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.senmesh.common.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface AlitaStopWatch {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.senmesh.common.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.senmesh.common.constant.ProjectProfileEnum;
|
||||
|
||||
/**
|
||||
* 校验并mock
|
||||
*
|
||||
* @author sr on 2020-05-20
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface CheckAndMock {
|
||||
|
||||
/**
|
||||
* 属性前缀
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-20
|
||||
*/
|
||||
String propertyPrefix() default "";
|
||||
|
||||
/**
|
||||
* 属性配置类
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-20
|
||||
*/
|
||||
Class<ICheckAndMockPropertity> checkAndMockPropertity() default ICheckAndMockPropertity.class;
|
||||
|
||||
/**
|
||||
* mock实现类(需注入spring上下文,提供与原方法方法名/参数/返回对象一致的方法)
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-20
|
||||
*/
|
||||
Class<?> mockClass();
|
||||
|
||||
// String mockBeanId();
|
||||
|
||||
/**
|
||||
* 指定环境直接mock
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-21
|
||||
*/
|
||||
ProjectProfileEnum[] mockIfInProfile() default {};
|
||||
|
||||
|
||||
}
|
||||
27
src/main/java/com/senmesh/common/annotation/CheckJob.java
Normal file
27
src/main/java/com/senmesh/common/annotation/CheckJob.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.senmesh.common.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 校验定时任务是否开启
|
||||
*
|
||||
* @author sr on 2020-05-19
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface CheckJob {
|
||||
|
||||
/**
|
||||
* 配置文件是否开启的key,明确指定为false时才关闭
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-19
|
||||
*/
|
||||
String value();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.senmesh.common.annotation;
|
||||
|
||||
/**
|
||||
* 需要校验后mock的配置
|
||||
*
|
||||
* @author sr on 2020-05-20
|
||||
*/
|
||||
public interface ICheckAndMockPropertity {
|
||||
|
||||
/**
|
||||
* 是否开启
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-21
|
||||
*/
|
||||
Boolean getEnable();
|
||||
|
||||
/**
|
||||
* 次数限制
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-21
|
||||
*/
|
||||
Long getNumLimit();
|
||||
|
||||
/**
|
||||
* 属性前缀
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-05-21
|
||||
*/
|
||||
String getPropertityPrefix();
|
||||
|
||||
}
|
||||
19
src/main/java/com/senmesh/common/annotation/Mask.java
Normal file
19
src/main/java/com/senmesh/common/annotation/Mask.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.senmesh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||
|
||||
/**
|
||||
* 掩码
|
||||
* @author sr on 2021-11-25
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@JacksonAnnotationsInside
|
||||
public @interface Mask {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.senmesh.common.annotation;
|
||||
|
||||
import com.fasterxml.jackson.databind.introspect.Annotated;
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
|
||||
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
|
||||
|
||||
/**
|
||||
* @author sr on 2021-11-25
|
||||
*/
|
||||
public class MaskAnontationIntrospector extends JacksonAnnotationIntrospector {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Object findSerializer(Annotated a) {
|
||||
Mask mask = a.getAnnotation(Mask.class);
|
||||
if (mask != null) {
|
||||
return MaskSerializer.class;
|
||||
}
|
||||
return super.findSerializer(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIgnoreMarker(AnnotatedMember m) {
|
||||
// 直接不打印该字段,则置为true
|
||||
/*if (m.hasAnnotation(Mask.class)) {
|
||||
return true;
|
||||
}*/
|
||||
return super.hasIgnoreMarker(m);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.senmesh.common.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
|
||||
/**
|
||||
* @author sr on 2021-11-25
|
||||
*/
|
||||
public class MaskSerializer extends StdSerializer<Object> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String mask = "***";
|
||||
|
||||
public MaskSerializer() {
|
||||
super(Object.class);
|
||||
}
|
||||
|
||||
public MaskSerializer(String mask, int count) {
|
||||
this();
|
||||
}
|
||||
|
||||
public MaskSerializer(MaskSerializer src) {
|
||||
super(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(Object s, JsonGenerator jsonGenerator,
|
||||
SerializerProvider serializerProvider) throws IOException {
|
||||
jsonGenerator.writeString(mask);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.senmesh.common.annotation.aspect;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
import com.senmesh.common.annotation.AlitaStopWatch;
|
||||
import com.senmesh.common.exception.util.DevopsUtils;
|
||||
import com.senmesh.common.util.EnvironmentUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class AlitaStopWatchAspect {
|
||||
|
||||
public static final String DEVOPS_TIME_KEY = "devops.usetime";
|
||||
/** 默认十分钟 **/
|
||||
public static final Long DEFAULT_DEVOPS_TIME = 10 * 60L;
|
||||
|
||||
|
||||
@Around("@annotation(alitaStopWatch)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, AlitaStopWatch alitaStopWatch) throws Throwable {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
try {
|
||||
return joinPoint.proceed();
|
||||
} finally {
|
||||
stopWatch.stop();
|
||||
String useTimeStr = EnvironmentUtils.getProperty(DEVOPS_TIME_KEY);
|
||||
Long maxUseTime = DEFAULT_DEVOPS_TIME;
|
||||
try {
|
||||
maxUseTime = Long.parseLong(useTimeStr);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
maxUseTime = 1000 * maxUseTime;
|
||||
Long actualTime = stopWatch.getTotalTimeMillis();
|
||||
String logMsg = joinPoint.getSignature().toShortString() + ",use(ms): " + actualTime;
|
||||
if (actualTime > maxUseTime) {
|
||||
DevopsUtils.deal(logMsg);
|
||||
}
|
||||
log.info(logMsg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.senmesh.common.annotation.aspect;
|
||||
|
||||
import com.senmesh.common.annotation.CheckAndMock;
|
||||
import com.senmesh.common.annotation.ICheckAndMockPropertity;
|
||||
import com.senmesh.common.cache.ICacheProvider;
|
||||
import com.senmesh.common.constant.CommonConstants;
|
||||
import com.senmesh.common.constant.ProjectProfileEnum;
|
||||
import com.senmesh.common.util.SpringContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 校验并mock
|
||||
*
|
||||
* @author sr on 2020-05-19
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
@Order(200)
|
||||
public class CheckAndMockAspect {
|
||||
|
||||
/** 是否开启属性 **/
|
||||
public static final String ENABLE_KEY = "enable";
|
||||
/** 次数限制属性 **/
|
||||
public static final String NUM_LIMIT_KEY = "numLimit";
|
||||
/** 默认次数 **/
|
||||
public static final Long DEFALUT_NUM_LIMIT = 3L;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Autowired
|
||||
private ICacheProvider iCacheProvider;
|
||||
|
||||
@Around("@annotation(checkAndMock)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, CheckAndMock checkAndMock) throws Throwable {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
ProjectProfileEnum[] profileEnums = checkAndMock.mockIfInProfile();
|
||||
Class<?> mockClass = checkAndMock.mockClass();
|
||||
String currentProfile = environment.getProperty(CommonConstants.PROFILE_KEY);
|
||||
|
||||
Object[] args = joinPoint.getArgs();
|
||||
// 只要配置环境mock,就不校验开关和次数限制
|
||||
if (profileEnums.length > 0) {
|
||||
for (ProjectProfileEnum profileEnum : profileEnums) {
|
||||
if (profileEnum.getValue().equals(currentProfile)) {
|
||||
return mock(mockClass, method, args);
|
||||
}
|
||||
}
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
|
||||
// 获取属性配置
|
||||
String propertyPrefix = checkAndMock.propertyPrefix();
|
||||
boolean enable = true;
|
||||
Long numLimit = null;
|
||||
if (StringUtils.isNotBlank(propertyPrefix)) {
|
||||
enable = BooleanUtils.toBoolean(
|
||||
environment.getProperty(String.join(CommonConstants.POINT, propertyPrefix, ENABLE_KEY)));
|
||||
try {
|
||||
numLimit = enable ? Long.parseLong(environment
|
||||
.getProperty(String.join(CommonConstants.POINT, propertyPrefix, NUM_LIMIT_KEY))) : 0L;
|
||||
} catch (NumberFormatException e) {
|
||||
log.info("{} numLimit not right, use default numLimit", propertyPrefix);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
ICheckAndMockPropertity properties =
|
||||
SpringContextHolder.getBean(checkAndMock.checkAndMockPropertity());
|
||||
enable = properties.getEnable();
|
||||
numLimit = properties.getNumLimit();
|
||||
propertyPrefix = properties.getPropertityPrefix();
|
||||
} catch (Exception e) {
|
||||
log.info("ICheckAndMockPropertity not found...");
|
||||
enable = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 开关关闭,都走mock
|
||||
if (!enable) {
|
||||
return mock(mockClass, method, args);
|
||||
}
|
||||
// 开关开启,生产无次数限制,本地测试根据配置/默认次数控制
|
||||
boolean isProd = ProjectProfileEnum.PROD.getValue().equals(currentProfile);
|
||||
if (isProd) {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
|
||||
numLimit = numLimit == null ? DEFALUT_NUM_LIMIT : numLimit;
|
||||
String key = String.join(CommonConstants.POINT, propertyPrefix, NUM_LIMIT_KEY);
|
||||
if (iCacheProvider.outLimit(key, numLimit)) {
|
||||
// 超限,mock
|
||||
return mock(mockClass, method, args);
|
||||
}
|
||||
// 次数限制
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mock调用
|
||||
*
|
||||
* @param clazz
|
||||
* @param method
|
||||
* @param objects
|
||||
* @return
|
||||
* @throws Throwable
|
||||
* @author sr on 2020-05-21
|
||||
*/
|
||||
private Object mock(Class<?> clazz, Method method, Object[] objects) throws Throwable {
|
||||
Object mockBean = SpringContextHolder.getBean(clazz);
|
||||
Method mockMethod = mockBean.getClass().getMethod(method.getName(), method.getParameterTypes());
|
||||
return mockMethod.invoke(mockBean, objects);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.senmesh.common.annotation.aspect;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.senmesh.common.annotation.CheckJob;
|
||||
import com.senmesh.common.constant.CommonConstants;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 校验定时任务是否开启
|
||||
*
|
||||
* @author sr on 2020-05-19
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class CheckJobAspect {
|
||||
|
||||
/** 配置无效识别符(只有配置false才失效) **/
|
||||
private String falseValue = "false";
|
||||
|
||||
/** 定时任务配置前缀 **/
|
||||
public static final String JOB_PROPERTY_PREFIX = "job";
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Around("@annotation(checkJob)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, CheckJob checkJob) throws Throwable {
|
||||
String propertityKey = checkJob.value();
|
||||
boolean disable = falseValue.equals(environment
|
||||
.getProperty(String.join(CommonConstants.POINT, JOB_PROPERTY_PREFIX, propertityKey)));
|
||||
if (disable) {
|
||||
log.info("job:{} not enable...", propertityKey);
|
||||
return null;
|
||||
}
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.senmesh.common.annotation.trimAndUpper;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 用于字符串去空格以及大写
|
||||
*
|
||||
* @author Carlye
|
||||
* @date 2022/02/16
|
||||
*/
|
||||
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface TrimAndUpper {
|
||||
|
||||
/**
|
||||
* 执行类型
|
||||
* ALL: (所有类型都包含)
|
||||
* TRIM: (去两边的空格)
|
||||
* REPLACE_ALL: (去所有的空格)
|
||||
* UPPER_CASE: (转大写)
|
||||
*
|
||||
* @author Carlye
|
||||
* @date 2022/02/16
|
||||
*/
|
||||
public static enum ExecuteType {
|
||||
ALL, TRIM, REPLACE_ALL, UPPER_CASE;
|
||||
}
|
||||
|
||||
ExecuteType value() default ExecuteType.ALL;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.senmesh.common.annotation.trimAndUpper;
|
||||
|
||||
import com.fasterxml.jackson.databind.AnnotationIntrospector;
|
||||
import com.fasterxml.jackson.databind.introspect.Annotated;
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
|
||||
|
||||
/**
|
||||
* @author sr on 2021-11-25
|
||||
*/
|
||||
public class TrimAndUpperAnontationIntrospector extends AnnotationIntrospectorPair {
|
||||
|
||||
|
||||
private static final long serialVersionUID = -1755768596246088917L;
|
||||
|
||||
public TrimAndUpperAnontationIntrospector(AnnotationIntrospector p,
|
||||
AnnotationIntrospector s) {
|
||||
super(p, s);
|
||||
}
|
||||
@Override
|
||||
public Object findDeserializer(Annotated a) {
|
||||
TrimAndUpper trim = a.getAnnotation(TrimAndUpper.class);
|
||||
if (trim != null) {
|
||||
return TrimAndUpperDeserializer.class;
|
||||
}
|
||||
return super.findDeserializer(a);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.senmesh.common.annotation.trimAndUpper;
|
||||
|
||||
import com.fasterxml.jackson.databind.AnnotationIntrospector;
|
||||
import com.fasterxml.jackson.databind.DeserializationConfig;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.cfg.BaseSettings;
|
||||
import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
|
||||
import java.lang.reflect.Field;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
|
||||
@Configuration
|
||||
public class TrimAndUpperConfig {
|
||||
|
||||
@Autowired
|
||||
public void addFormatters(FormatterRegistry registry) {
|
||||
TrimAndUpperFormatterFactory trimAndUpperCaseFormatterFactory = new TrimAndUpperFormatterFactory();
|
||||
registry.addFormatterForFieldAnnotation(trimAndUpperCaseFormatterFactory);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void init(RequestMappingHandlerAdapter handlerAdapter){
|
||||
for (HttpMessageConverter<?> messageConverter : handlerAdapter.getMessageConverters()) {
|
||||
try {
|
||||
if (messageConverter instanceof MappingJackson2HttpMessageConverter){
|
||||
MappingJackson2HttpMessageConverter converter1 = (MappingJackson2HttpMessageConverter)messageConverter;
|
||||
ObjectMapper objectMapper = converter1.getObjectMapper();
|
||||
DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig();
|
||||
|
||||
Field _base = ReflectionUtils.findField(DeserializationConfig.class, "_base");
|
||||
ReflectionUtils.makeAccessible(_base);
|
||||
BaseSettings baseSettings = (BaseSettings)ReflectionUtils.getField(_base, deserializationConfig);
|
||||
|
||||
AnnotationIntrospector annotationIntrospector = baseSettings.getAnnotationIntrospector();
|
||||
if (annotationIntrospector instanceof AnnotationIntrospectorPair){
|
||||
AnnotationIntrospectorPair annotationIntrospectorOld = (AnnotationIntrospectorPair)baseSettings.getAnnotationIntrospector();
|
||||
|
||||
Field _primary = ReflectionUtils.findField(AnnotationIntrospectorPair.class, "_primary");
|
||||
ReflectionUtils.makeAccessible(_primary);
|
||||
AnnotationIntrospector _primaryObj = (AnnotationIntrospector)ReflectionUtils.getField(_primary, annotationIntrospectorOld);
|
||||
|
||||
Field _secondary = ReflectionUtils.findField(AnnotationIntrospectorPair.class, "_secondary");
|
||||
ReflectionUtils.makeAccessible(_secondary);
|
||||
AnnotationIntrospector _secondaryObj = (AnnotationIntrospector)ReflectionUtils.getField(_secondary, annotationIntrospectorOld);
|
||||
|
||||
converter1.getObjectMapper().setAnnotationIntrospector(new TrimAndUpperAnontationIntrospector(_primaryObj,_secondaryObj));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//doNothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.senmesh.common.annotation.trimAndUpper;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.BeanProperty;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.senmesh.common.annotation.trimAndUpper.TrimAndUpper.ExecuteType;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class TrimAndUpperDeserializer extends StdDeserializer<String> implements ContextualDeserializer {
|
||||
|
||||
private static final Map<ExecuteType, TrimAndUpperDeserializer> INSTANCE_MAP = Maps.newHashMap();
|
||||
private static final long serialVersionUID = 3463447204376923373L;
|
||||
|
||||
static {
|
||||
for (ExecuteType value : ExecuteType.values()) {
|
||||
INSTANCE_MAP.put(value,new TrimAndUpperDeserializer(value));
|
||||
}
|
||||
}
|
||||
|
||||
private ExecuteType executeType;
|
||||
|
||||
public TrimAndUpperDeserializer(){
|
||||
super(String.class);
|
||||
}
|
||||
|
||||
public TrimAndUpperDeserializer(ExecuteType executeType){
|
||||
super(String.class);
|
||||
this.executeType = executeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
|
||||
String s = jsonParser.getText();
|
||||
if (!(StringUtils.isEmpty(s) || Objects.isNull(executeType))) {
|
||||
if (ExecuteType.ALL.equals(executeType) || ExecuteType.TRIM.equals(executeType)) {
|
||||
s = StringUtils.replace(StringUtils.trim(s)," ","");
|
||||
}
|
||||
if (ExecuteType.ALL.equals(executeType) || ExecuteType.TRIM.equals(executeType)) {
|
||||
s = StringUtils.upperCase(s);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonDeserializer<?> createContextual(DeserializationContext prov, BeanProperty property) throws JsonMappingException {
|
||||
ExecuteType executeType = null;
|
||||
TrimAndUpper ann = null;
|
||||
if (property != null) {
|
||||
ann = property.getAnnotation(TrimAndUpper.class);
|
||||
}
|
||||
if (ann != null) {
|
||||
executeType = ann.value();
|
||||
}
|
||||
return INSTANCE_MAP.get(executeType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.senmesh.common.annotation.trimAndUpper;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.senmesh.common.annotation.trimAndUpper.TrimAndUpper.ExecuteType;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.format.AnnotationFormatterFactory;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
public class TrimAndUpperFormatterFactory implements
|
||||
AnnotationFormatterFactory<TrimAndUpper> {
|
||||
|
||||
private static final Map<ExecuteType, TrimAndUpperCaseFormatter> TRIMMER_FORMATTER_MAP;
|
||||
|
||||
static {
|
||||
ExecuteType[] values = ExecuteType.values();
|
||||
Map<ExecuteType, TrimAndUpperCaseFormatter> map = Maps.newHashMap();
|
||||
for (ExecuteType type : values) {
|
||||
map.put(type, new TrimAndUpperCaseFormatter(type));
|
||||
}
|
||||
TRIMMER_FORMATTER_MAP = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> getFieldTypes() {
|
||||
return Sets.newHashSet(String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Printer<?> getPrinter(TrimAndUpper trimAndUpper, Class<?> aClass) {
|
||||
return TRIMMER_FORMATTER_MAP.get(trimAndUpper.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parser<?> getParser(TrimAndUpper trimAndUpper, Class<?> aClass) {
|
||||
return TRIMMER_FORMATTER_MAP.get(trimAndUpper.value());
|
||||
}
|
||||
|
||||
private static class TrimAndUpperCaseFormatter implements Formatter<String> {
|
||||
|
||||
private TrimAndUpper.ExecuteType executeType;
|
||||
|
||||
public TrimAndUpperCaseFormatter(TrimAndUpper.ExecuteType executeType) {
|
||||
this.executeType = executeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parse(String value, Locale locale) throws ParseException {
|
||||
if (StringUtils.isEmpty(value) || Objects.isNull(executeType)) {
|
||||
return value;
|
||||
}
|
||||
// 去所有空格
|
||||
if (ExecuteType.ALL.equals(executeType) || ExecuteType.REPLACE_ALL.equals(executeType)) {
|
||||
value = StringUtils.replace(value, " ", "");
|
||||
}
|
||||
// 转大写
|
||||
if (ExecuteType.ALL.equals(executeType) || ExecuteType.UPPER_CASE.equals(executeType)) {
|
||||
value = StringUtils.upperCase(value);
|
||||
}
|
||||
//去两边空格
|
||||
if (ExecuteType.ALL.equals(executeType) || ExecuteType.TRIM.equals(executeType)) {
|
||||
value = StringUtils.trim(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String print(String value, Locale locale) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/main/java/com/senmesh/common/cache/DefaultCacheProvider.java
vendored
Normal file
31
src/main/java/com/senmesh/common/cache/DefaultCacheProvider.java
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.senmesh.common.cache;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-07-07
|
||||
*/
|
||||
public class DefaultCacheProvider implements ICacheProvider {
|
||||
|
||||
private Map<String, Long> numLimitMap = Maps.newConcurrentMap();
|
||||
|
||||
@Override
|
||||
public boolean outLimit(final String key, Long maxNumLimit) {
|
||||
Long currentNumLimit = null;
|
||||
final Object lockKey = key.intern();
|
||||
synchronized (lockKey) {
|
||||
currentNumLimit = MapUtils.getLong(numLimitMap, key, 0L);
|
||||
if (currentNumLimit >= maxNumLimit) {
|
||||
return true;
|
||||
}
|
||||
currentNumLimit++;
|
||||
numLimitMap.put(key, currentNumLimit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/main/java/com/senmesh/common/cache/ICacheProvider.java
vendored
Normal file
18
src/main/java/com/senmesh/common/cache/ICacheProvider.java
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.senmesh.common.cache;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-07-07
|
||||
*/
|
||||
public interface ICacheProvider {
|
||||
|
||||
/**
|
||||
* 是否超限
|
||||
*
|
||||
* @param key
|
||||
* @param maxNumLimit
|
||||
* @return
|
||||
* @author sr on 2020-07-07
|
||||
*/
|
||||
boolean outLimit(String key, Long maxNumLimit);
|
||||
|
||||
}
|
||||
32
src/main/java/com/senmesh/common/cache/RedisCacheProvier.java
vendored
Normal file
32
src/main/java/com/senmesh/common/cache/RedisCacheProvier.java
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.senmesh.common.cache;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-07-07
|
||||
*/
|
||||
@Service
|
||||
@ConditionalOnClass(RedisTemplate.class)
|
||||
@Order(1)
|
||||
public class RedisCacheProvier implements ICacheProvider{
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Autowired(required = false)
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean outLimit(String key, Long maxNumLimit) {
|
||||
Long currentNumLimit = redisTemplate.opsForValue().increment(key);
|
||||
if (currentNumLimit > maxNumLimit) {
|
||||
redisTemplate.opsForValue().decrement(key);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
/**
|
||||
* 系统枚举
|
||||
*
|
||||
* @author sr on 2020-06-02
|
||||
*/
|
||||
public enum AuthStatusEnum {
|
||||
|
||||
/**
|
||||
* 待认证
|
||||
**/
|
||||
NOT_AUTH(1, "待认证"),
|
||||
/**
|
||||
* 认证中
|
||||
**/
|
||||
AUTHING(2, "认证中"),
|
||||
/**
|
||||
* 认证成功
|
||||
**/
|
||||
AUTH_SUCCESS(3, "认证成功"),
|
||||
/**
|
||||
* 认证失败
|
||||
**/
|
||||
AUTH_FAIL(4, "认证失败");
|
||||
|
||||
/**
|
||||
* 状态类型
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 状态名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
AuthStatusEnum(Integer type, String name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
/**
|
||||
* 缓存常量
|
||||
*
|
||||
* @author sr on 2020-04-03
|
||||
*/
|
||||
public interface CacheConstants {
|
||||
|
||||
String CACHE_NAME_DICT = "dict";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
/**
|
||||
* 公共常量
|
||||
* @author sr on 2019-12-03
|
||||
*/
|
||||
public interface CommonConstants {
|
||||
|
||||
/** _(下划线) **/
|
||||
String UNDERLINE = "_";
|
||||
/** # **/
|
||||
String POUND = "#";
|
||||
/** & **/
|
||||
String AND = "&";
|
||||
/** ,(逗号) **/
|
||||
String COMMA = ",";
|
||||
/** :(冒号) **/
|
||||
String COLON = ":";
|
||||
/** ;(分号) **/
|
||||
String SEMICOLON = ";";
|
||||
/** . **/
|
||||
String POINT = ".";
|
||||
/** = **/
|
||||
String EQUAL = "=";
|
||||
/** ? **/
|
||||
String QUESTION = "?";
|
||||
/** -(连字号) **/
|
||||
String HYPHEN = "-";
|
||||
/** ...(省略号) **/
|
||||
String ELLIPSIS = "...";
|
||||
|
||||
/** 金额精度:两位 **/
|
||||
int AMOUNT_SCALE = 2;
|
||||
|
||||
/** 金额小数位 **/
|
||||
int AMOUNT_FRACTION = 2;
|
||||
/** 金额整数位 **/
|
||||
int AMOUNT_INTEGER = 14;
|
||||
|
||||
|
||||
/** 项目环境配置key **/
|
||||
String PROFILE_KEY = "spring.profiles.active";
|
||||
/** 项目名称 **/
|
||||
String APPLICATION_NAME_KEY = "spring.application.name";
|
||||
String SYSTEM_CODE_KEY = "system.code";
|
||||
/** security是否使用本地方法 **/
|
||||
String USELOCAL_KEY = "security.useLocal";
|
||||
|
||||
/**
|
||||
* 表字段去空格
|
||||
*/
|
||||
String TRIM_TABLE_FIELDS_ENBALE_KEY = "trim.table.fields";
|
||||
|
||||
/** 开关键 **/
|
||||
String ENABLE_KEY = "enable";
|
||||
|
||||
String FALSE_STR = "false";
|
||||
|
||||
/** 配置值:是 **/
|
||||
String CONFIG_TRUE = "1";
|
||||
/** 配置值:否 **/
|
||||
String CONFIG_FALSE = "0";
|
||||
|
||||
/** 平台机构id **/
|
||||
Long PLATFORM_ORG_ID = 1L;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
public interface CommonMqConstants {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
/**
|
||||
* @author Jerry.li
|
||||
* @description Cookie相关常量
|
||||
* @date 2020/5/11
|
||||
*/
|
||||
public class CookieConstants {
|
||||
|
||||
/**
|
||||
* 登录Cookie名称前缀
|
||||
*/
|
||||
public static final String LOGIN_COOKIE_NAME_PREFIX = "xs_ck_";
|
||||
|
||||
/** 属性配置键:cookie域名 **/
|
||||
public static final String PROP_KEY_COOKIE_DOMAIN = "cookie.domain";
|
||||
|
||||
}
|
||||
21
src/main/java/com/senmesh/common/constant/ExceptionMsgs.java
Normal file
21
src/main/java/com/senmesh/common/constant/ExceptionMsgs.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
/**
|
||||
* 异常错误信息
|
||||
*
|
||||
* @author on 2019-11-05
|
||||
*/
|
||||
public interface ExceptionMsgs {
|
||||
|
||||
String ENTITY_HAS_EXISTS = "数据已存在";
|
||||
|
||||
String ENTITY_NONE_EXISTS = "数据不存在";
|
||||
|
||||
String ENTITY_MULTIPLE_EXISTS = "数据存在多条";
|
||||
|
||||
String UPDATE_DATA_NOT_EXIST = "操作失败,请检查数据";
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
public interface ExceptionRecordConstants {
|
||||
|
||||
/**
|
||||
* 接口记录系统类型
|
||||
*/
|
||||
String SOURCE_HYG = "1";
|
||||
String SOURCE_XINPAI = "2";
|
||||
}
|
||||
48
src/main/java/com/senmesh/common/constant/GenderEnum.java
Normal file
48
src/main/java/com/senmesh/common/constant/GenderEnum.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
/**
|
||||
* 性别枚举
|
||||
*
|
||||
*/
|
||||
public enum GenderEnum {
|
||||
|
||||
MALE(1, "男"),
|
||||
FEMALE(2, "女"),
|
||||
OTHER(3, "其它");
|
||||
|
||||
private final Integer type;
|
||||
|
||||
private final String desc;
|
||||
|
||||
GenderEnum(Integer type, String desc) {
|
||||
this.type = type;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static Integer formatFemale(Integer value){
|
||||
// 通过sql 身份证号处理性别条件:0女,1男
|
||||
if(GenderEnum.FEMALE.getType().equals(value)){
|
||||
return 0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String getVal(Integer val){
|
||||
if(GenderEnum.MALE.getType().equals(val)){
|
||||
return GenderEnum.MALE.desc;
|
||||
} else if(GenderEnum.FEMALE.getType().equals(val)){
|
||||
return GenderEnum.FEMALE.desc;
|
||||
}
|
||||
return GenderEnum.OTHER.desc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
/**
|
||||
* 项目环境枚举
|
||||
* @author sr on 2020-05-20
|
||||
*/
|
||||
public enum ProjectProfileEnum {
|
||||
|
||||
/** 开发 **/
|
||||
DEV("dev"),
|
||||
/** 测试 **/
|
||||
TEST("test"),
|
||||
/** 测试 * */
|
||||
UAT("uat"),
|
||||
/** 生产 **/
|
||||
PROD("prod"),
|
||||
/** 福安 **/
|
||||
FUAN("fuan");
|
||||
|
||||
private String value;
|
||||
|
||||
ProjectProfileEnum(String value){
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.senmesh.common.constant;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 交易账户类型常量
|
||||
* @author sr on 2020-08-19
|
||||
*/
|
||||
public interface TradeAccountTypeConstants {
|
||||
|
||||
/** 交易账号类型:银行卡 **/
|
||||
String TRADE_ACCOUNT_TYPE_BANK = TradeAccountTypeEnum.BANK.getType().toString();
|
||||
/** 交易账号类型:子账号 **/
|
||||
String TRADE_ACCOUNT_TYPE_SUB_ACCOUNT = TradeAccountTypeEnum.SUB_ACCOUNT.getType().toString();
|
||||
/** 交易账号类型:支付宝账号 **/
|
||||
String TRADE_ACCOUNT_TYPE_ALIPAY_ACCOUNT = TradeAccountTypeEnum.ALIPAY_ACCOUNT.getType().toString();
|
||||
/** 交易账号类型:支付宝用户ID **/
|
||||
String TRADE_ACCOUNT_TYPE_ALIPAY_USERID = TradeAccountTypeEnum.ALIPAY_USERID.getType().toString();
|
||||
/** 交易账号类型:微信OPENID **/
|
||||
String TRADE_ACCOUNT_TYPE_WECHAT_OPENID = TradeAccountTypeEnum.WECHAT_OPENID.getType().toString();
|
||||
/** 交易账号类型:平台机构 **/
|
||||
String TRADE_ACCOUNT_TYPE_PLATFORM_ORG = TradeAccountTypeEnum.PLATFORM_ORG.getType().toString();
|
||||
|
||||
/**
|
||||
* 交易账号类型:其他
|
||||
*/
|
||||
String TRADE_ACCOUNT_TYPE_OTHER = TradeAccountTypeEnum.OTHER.getType().toString();
|
||||
|
||||
/**
|
||||
* 帐户类型枚举
|
||||
*
|
||||
* @author Carlye
|
||||
* @date 2021/08/17
|
||||
*/
|
||||
public enum TradeAccountTypeEnum{
|
||||
BANK(1,"银行卡"),
|
||||
SUB_ACCOUNT(2,"内部子账户"),
|
||||
ALIPAY_ACCOUNT(3,"支付宝账号"),
|
||||
ALIPAY_USERID(4,"支付宝用户ID"),
|
||||
WECHAT_OPENID(5,"微信支付"),
|
||||
PLATFORM_ORG(6,"平台机构"),
|
||||
OTHER(99,"其他");
|
||||
|
||||
private final Integer type;
|
||||
|
||||
private final String desc;
|
||||
|
||||
TradeAccountTypeEnum(Integer type,String desc){
|
||||
this.type = type;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static TradeAccountTypeEnum find(Integer type){
|
||||
if (Objects.isNull(type)){
|
||||
return null;
|
||||
}
|
||||
return Arrays.stream(TradeAccountTypeEnum.values()).filter(e->e.getType().equals(type)).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.senmesh.common.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.senmesh.common.AlitaResult;
|
||||
import com.senmesh.common.util.JsonUtils;
|
||||
import com.senmesh.common.util.RequestUtils;
|
||||
import com.senmesh.commonexport.service.ExportService;
|
||||
import com.senmesh.usercenter.user.dto.UserDTO;
|
||||
|
||||
@RestController
|
||||
public class TestController {
|
||||
|
||||
@Autowired
|
||||
private ExportService exportService;
|
||||
|
||||
@GetMapping("anon/hostIp")
|
||||
public AlitaResult<String> hostIp() {
|
||||
return AlitaResult.success(RequestUtils.getHostIp());
|
||||
}
|
||||
|
||||
@GetMapping("anon/trim")
|
||||
public AlitaResult<String> gettrim(UserDTO userDTO) {
|
||||
return AlitaResult.success(JsonUtils.toJsonString(userDTO));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("anon/trim")
|
||||
public AlitaResult<String> posttrim(@RequestBody UserDTO userDTO) {
|
||||
return AlitaResult.success(JsonUtils.toJsonString(userDTO));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
56
src/main/java/com/senmesh/common/dto/BaseDTO.java
Normal file
56
src/main/java/com/senmesh/common/dto/BaseDTO.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
|
||||
import com.senmesh.common.validation.Update;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
|
||||
/**
|
||||
* 基础dto
|
||||
*
|
||||
* @author sr on 2019-12-07
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
public class BaseDTO implements Serializable,IBaseDTO {
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 3305990673475531178L;
|
||||
|
||||
@ApiModelProperty("id")
|
||||
@NotNull(message = "id不能为空", groups = {Update.class})
|
||||
private Long id;
|
||||
@ApiModelProperty("是否逻辑删除(0否1是)")
|
||||
private Boolean deleted;
|
||||
@ApiModelProperty("创建人")
|
||||
private Long createBy;
|
||||
@ApiModelProperty("创建时间")
|
||||
// requestparam
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
// requestbody+serial
|
||||
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
@ApiModelProperty("修改人")
|
||||
private Long updateBy;
|
||||
@ApiModelProperty("修改时间")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
private Long proxyBy;
|
||||
|
||||
}
|
||||
41
src/main/java/com/senmesh/common/dto/BaseOperateDTO.java
Normal file
41
src/main/java/com/senmesh/common/dto/BaseOperateDTO.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.senmesh.common.util.UserContextHolder;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 基础操作对象
|
||||
*
|
||||
* @author sr on 2020-08-26
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BaseOperateDTO implements Serializable, IOperateDTO{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = -3075506470200622050L;
|
||||
|
||||
/** 操作机构ID **/
|
||||
@JsonIgnore
|
||||
private Long operateOrgId;
|
||||
|
||||
/** 操作用户ID **/
|
||||
@JsonIgnore
|
||||
private Long operateUserId;
|
||||
|
||||
public Long getOperateOrgId() {
|
||||
return operateOrgId == null ? UserContextHolder.getLoginOrgId() : operateOrgId;
|
||||
}
|
||||
|
||||
public Long getOperateUserId() {
|
||||
return operateUserId == null ? UserContextHolder.getLoginUserId() : operateUserId;
|
||||
}
|
||||
|
||||
}
|
||||
13
src/main/java/com/senmesh/common/dto/ButtonDTO.java
Normal file
13
src/main/java/com/senmesh/common/dto/ButtonDTO.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-22
|
||||
*/
|
||||
public class ButtonDTO implements Serializable{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = -8606784819452806185L;
|
||||
|
||||
}
|
||||
27
src/main/java/com/senmesh/common/dto/CasTokenDTO.java
Normal file
27
src/main/java/com/senmesh/common/dto/CasTokenDTO.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class CasTokenDTO implements Serializable{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = -6818144396647084889L;
|
||||
|
||||
private String token;
|
||||
|
||||
/** 当前token用户id **/
|
||||
private Long userId;
|
||||
|
||||
/** 是否新注册 **/
|
||||
private Boolean register;
|
||||
|
||||
}
|
||||
37
src/main/java/com/senmesh/common/dto/ColumnDTO.java
Normal file
37
src/main/java/com/senmesh/common/dto/ColumnDTO.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Builder.Default;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-22
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ColumnDTO implements Serializable{
|
||||
/** **/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final int DEFAULT_WIDTH = 160;
|
||||
|
||||
/** 标题,如:总条数 **/
|
||||
private String title;
|
||||
/** 下标(同key),如:totalCount **/
|
||||
private String dataIndex;
|
||||
/** 属性,如:totalCount **/
|
||||
private String key;
|
||||
/** 宽度 **/
|
||||
@Default
|
||||
private int width = DEFAULT_WIDTH;
|
||||
/** 对齐方式 **/
|
||||
@Default
|
||||
private String align = "center";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 展示定制的组件
|
||||
*
|
||||
* @author sr on 2020-04-22
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DisplayedComponentDTO<T> implements Serializable{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 消息 **/
|
||||
private MessageDTO message;
|
||||
/** 列配置 **/
|
||||
private List<ColumnDTO> columns;
|
||||
/** 展示数据 **/
|
||||
private List<T> data;
|
||||
/** 按钮 **/
|
||||
private List<ButtonDTO> buttons;
|
||||
|
||||
}
|
||||
31
src/main/java/com/senmesh/common/dto/ExceptionRecordDTO.java
Normal file
31
src/main/java/com/senmesh/common/dto/ExceptionRecordDTO.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ExceptionRecordDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 入参json
|
||||
*/
|
||||
private String paramJson;
|
||||
/**
|
||||
* 响应json
|
||||
*/
|
||||
private String resultJson;
|
||||
/**
|
||||
* 调用接口地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 系统 1 慧用工、2、3、4待定
|
||||
*/
|
||||
private String sys;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
@Builder
|
||||
public class ExportHeadDetailInfoDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2399902503017038944L;
|
||||
/**
|
||||
* 表头
|
||||
*/
|
||||
private String head;
|
||||
|
||||
/**
|
||||
* 下拉列表
|
||||
*/
|
||||
private List<String> explicitList;
|
||||
}
|
||||
59
src/main/java/com/senmesh/common/dto/ExportHeadInfoDTO.java
Normal file
59
src/main/java/com/senmesh/common/dto/ExportHeadInfoDTO.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
@Builder
|
||||
public class ExportHeadInfoDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3123297330700623056L;
|
||||
|
||||
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 表头
|
||||
*/
|
||||
private List<ExportHeadDetailInfoDTO> heads;
|
||||
|
||||
/**
|
||||
* 数据列
|
||||
*/
|
||||
private List<List> datas;
|
||||
|
||||
public String getFileName() {
|
||||
if (Objects.isNull(fileName)){
|
||||
fileName = DateUtil.today() + "_动态模板";
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public List<ExportHeadDetailInfoDTO> getHeads() {
|
||||
if (Objects.isNull(heads)){
|
||||
heads = Lists.newArrayList();
|
||||
}
|
||||
return heads;
|
||||
}
|
||||
|
||||
public List<List> getDatas() {
|
||||
if (Objects.isNull(datas)){
|
||||
datas = Lists.newArrayList();
|
||||
}
|
||||
return datas;
|
||||
}
|
||||
}
|
||||
12
src/main/java/com/senmesh/common/dto/IBaseDTO.java
Normal file
12
src/main/java/com/senmesh/common/dto/IBaseDTO.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
/**
|
||||
* 基础对象
|
||||
* @author sr on 2024-04-18
|
||||
*/
|
||||
public interface IBaseDTO {
|
||||
|
||||
Long getId();
|
||||
|
||||
|
||||
}
|
||||
23
src/main/java/com/senmesh/common/dto/IDisplayed.java
Normal file
23
src/main/java/com/senmesh/common/dto/IDisplayed.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
/**
|
||||
* 展示信息
|
||||
*
|
||||
* @author sr on 2020-07-14
|
||||
*/
|
||||
public interface IDisplayed{
|
||||
/**
|
||||
* 是否展示
|
||||
* @return
|
||||
* @author sr on 2020-07-14
|
||||
*/
|
||||
Boolean getDisplayed();
|
||||
|
||||
/**
|
||||
* 展示组件
|
||||
* @return
|
||||
* @author sr on 2020-07-14
|
||||
*/
|
||||
DisplayedComponentDTO<?> getDisplayedComponentDto();
|
||||
|
||||
}
|
||||
26
src/main/java/com/senmesh/common/dto/IOperateDTO.java
Normal file
26
src/main/java/com/senmesh/common/dto/IOperateDTO.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
/**
|
||||
* 操作对象
|
||||
*
|
||||
* @author sr on 2020-08-26
|
||||
*/
|
||||
public interface IOperateDTO {
|
||||
|
||||
/**
|
||||
* 设置操作机构id
|
||||
*
|
||||
* @param orgId
|
||||
* @author sr on 2020-08-31
|
||||
*/
|
||||
void setOperateOrgId(Long orgId);
|
||||
|
||||
/**
|
||||
* 设置操作用户id
|
||||
*
|
||||
* @param userId
|
||||
* @author sr on 2020-08-31
|
||||
*/
|
||||
void setOperateUserId(Long userId);
|
||||
|
||||
}
|
||||
43
src/main/java/com/senmesh/common/dto/IPage.java
Normal file
43
src/main/java/com/senmesh/common/dto/IPage.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页对象
|
||||
*
|
||||
* @author sr on 2020-08-26
|
||||
*/
|
||||
public interface IPage<T> {
|
||||
|
||||
/**
|
||||
* 第几页
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-08-26
|
||||
*/
|
||||
Integer getPageNo();
|
||||
|
||||
/**
|
||||
* 页宽
|
||||
*
|
||||
* @return
|
||||
* @author sr on 2020-08-26
|
||||
*/
|
||||
Integer getPageSize();
|
||||
|
||||
|
||||
/**
|
||||
* 获取是否需要分页属性
|
||||
*
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
Boolean getNeedPage();
|
||||
|
||||
/**
|
||||
* 设置分页结果
|
||||
*
|
||||
* @author sr on 2020-08-26
|
||||
*/
|
||||
void setPageResult(int totalCount, List<T> results);
|
||||
|
||||
}
|
||||
28
src/main/java/com/senmesh/common/dto/MessageDTO.java
Normal file
28
src/main/java/com/senmesh/common/dto/MessageDTO.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Builder.Default;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-22
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class MessageDTO implements Serializable{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 3623225038987713421L;
|
||||
/** 类型:success/info/warning/error **/
|
||||
@Default
|
||||
private String type = "info";
|
||||
/** 内容 **/
|
||||
private String content;
|
||||
|
||||
}
|
||||
24
src/main/java/com/senmesh/common/dto/OrgBaseDTO.java
Normal file
24
src/main/java/com/senmesh/common/dto/OrgBaseDTO.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* 机构基础
|
||||
*
|
||||
* @author sr on 2019-12-22
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@SuperBuilder
|
||||
public class OrgBaseDTO extends BaseDTO {
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = -2595043832455614748L;
|
||||
|
||||
private Long orgId;
|
||||
|
||||
}
|
||||
98
src/main/java/com/senmesh/common/dto/PageQueryDTO.java
Normal file
98
src/main/java/com/senmesh/common/dto/PageQueryDTO.java
Normal file
@@ -0,0 +1,98 @@
|
||||
package com.senmesh.common.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.senmesh.tkmybatis.pojo.Page;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 分页查询对象
|
||||
*
|
||||
* @author sr on 2020-08-03
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PageQueryDTO<T> extends BaseOperateDTO implements Serializable, IPage<T> {
|
||||
|
||||
/**
|
||||
*
|
||||
**/
|
||||
private static final long serialVersionUID = -6370476082571087349L;
|
||||
|
||||
/**
|
||||
* 第几页
|
||||
**/
|
||||
private Integer pageNo = 1;
|
||||
/**
|
||||
* 页宽
|
||||
**/
|
||||
private Integer pageSize = 20;
|
||||
/**
|
||||
* 是否需要分页
|
||||
**/
|
||||
private Boolean needPage = Boolean.TRUE;
|
||||
/**
|
||||
* 分页结果
|
||||
**/
|
||||
@JsonIgnore
|
||||
private Page<T> pageResult;
|
||||
|
||||
@Override
|
||||
public Integer getPageNo() {
|
||||
return Optional.ofNullable(pageNo).orElse(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPageSize() {
|
||||
return Optional.ofNullable(pageSize).orElse(20);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getNeedPage() {
|
||||
return Optional.ofNullable(this.needPage).orElse(Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPageResult(int totalCount, List<T> results) {
|
||||
pageResult = new Page<T>(getPageNo(), getPageSize());
|
||||
pageResult.setPageResult(totalCount, results);
|
||||
}
|
||||
|
||||
public void setPageNo(Integer pageNo) {
|
||||
this.pageNo = pageNo;
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize) {
|
||||
if (pageSize != null && pageSize >1000) {
|
||||
this.pageSize = 1000;
|
||||
} else {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNeedPage(Boolean needPage) {
|
||||
this.needPage = needPage;
|
||||
}
|
||||
|
||||
public Page<T> getPageResult() {
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
public void setPageResult(Page<T> pageResult) {
|
||||
this.pageResult = pageResult;
|
||||
}
|
||||
|
||||
public PageQueryDTO<T> disablePage() {
|
||||
this.setNeedPage(Boolean.FALSE);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getStartPage() {
|
||||
return (getPageNo() - 1) * getPageSize();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.senmesh.common.easyexcel;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
|
||||
import com.alibaba.excel.metadata.Head;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.write.handler.AbstractCellWriteHandler;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
import com.senmesh.common.dto.ExportHeadDetailInfoDTO;
|
||||
import com.senmesh.common.dto.ExportHeadInfoDTO;
|
||||
|
||||
import org.apache.poi.hssf.util.HSSFColor;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.DataValidation;
|
||||
import org.apache.poi.ss.usermodel.DataValidationConstraint;
|
||||
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Name;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFColor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
|
||||
|
||||
import java.awt.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
||||
public class DynamicExportTemplateCellWriteHandler extends AbstractCellWriteHandler {
|
||||
|
||||
private Map<Integer, ExportHeadDetailInfoDTO> exportHeadIndexMap = null;
|
||||
|
||||
private Integer hiddenSheetIndex = 1;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
|
||||
super.afterCellDispose(writeSheetHolder, writeTableHolder, cellDataList, cell, head, relativeRowIndex, isHead);
|
||||
int rowIndex = cell.getRowIndex();
|
||||
int columnIndex = cell.getColumnIndex();
|
||||
Workbook workbook = writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook();
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
if (rowIndex == 0) {
|
||||
Row row = cell.getRow();
|
||||
row.setHeight((short) (33 * 20));
|
||||
ExportHeadInfoDTO exportInfo = (ExportHeadInfoDTO) ImportDataContext.get("exportInfo");
|
||||
|
||||
XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle();
|
||||
cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
|
||||
cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
|
||||
cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
|
||||
cellStyle.setLeftBorderColor(IndexedColors.BLACK.index);
|
||||
cellStyle.setBorderTop(BorderStyle.THIN);//上边框
|
||||
cellStyle.setTopBorderColor(IndexedColors.BLACK.index);
|
||||
cellStyle.setBorderRight(BorderStyle.THIN);//右边框
|
||||
cellStyle.setRightBorderColor(IndexedColors.BLACK.index);
|
||||
|
||||
cellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
|
||||
Color color = new Color(91, 155, 213);
|
||||
cellStyle.setFillForegroundColor(new XSSFColor(color,null));
|
||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
Font font = workbook.createFont();
|
||||
cellStyle.setFont(font);
|
||||
|
||||
font.setFontName("Calibri");
|
||||
font.setColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
|
||||
cell.setCellStyle(cellStyle);
|
||||
if (Objects.isNull(exportHeadIndexMap)) {
|
||||
List<ExportHeadDetailInfoDTO> heads = exportInfo.getHeads();
|
||||
exportHeadIndexMap = Maps.newHashMap();
|
||||
for (int i = 0; i < heads.size(); i++) {
|
||||
ExportHeadDetailInfoDTO exportHead = heads.get(i);
|
||||
exportHeadIndexMap.put(i, exportHead);
|
||||
}
|
||||
}
|
||||
|
||||
ExportHeadDetailInfoDTO exportHeadDetailInfoDTO = exportHeadIndexMap.get(columnIndex);
|
||||
String name;
|
||||
if (Objects.isNull(exportHeadDetailInfoDTO)) {
|
||||
name = cell.getStringCellValue();
|
||||
} else {
|
||||
name = exportHeadDetailInfoDTO.getHead();
|
||||
}
|
||||
int length = ((name.getBytes(StandardCharsets.UTF_8).length + cell.toString().length()) * 3) / 5 + 5;
|
||||
sheet.setColumnWidth(columnIndex, length * 290);
|
||||
|
||||
List<String> explicitList = Objects.isNull(exportHeadDetailInfoDTO) ? null : exportHeadDetailInfoDTO.getExplicitList();
|
||||
// 设置下拉属性
|
||||
// if (CollUtil.isNotEmpty(explicitList)) {
|
||||
// DataValidationHelper helper = sheet.getDataValidationHelper();
|
||||
// DataValidationConstraint constraint = helper.createExplicitListConstraint(explicitList.toArray(new String[]{}));
|
||||
// //设置生效的起始行、终止行、起始列、终止列
|
||||
// CellRangeAddressList cellAddressList = new CellRangeAddressList(1,
|
||||
// 65535, columnIndex, columnIndex);
|
||||
// DataValidation validation = helper.createValidation(constraint, cellAddressList);
|
||||
// //适配xls和xlsx
|
||||
// if (validation instanceof HSSFDataValidation) {
|
||||
// validation.setSuppressDropDownArrow(false);
|
||||
// } else {
|
||||
// validation.setSuppressDropDownArrow(true);
|
||||
// validation.setShowErrorBox(true);
|
||||
// }
|
||||
// sheet.addValidationData(validation);
|
||||
// }
|
||||
|
||||
if (CollUtil.isNotEmpty(explicitList)){
|
||||
String hiddenName = "hidden" + hiddenSheetIndex;
|
||||
//1.创建隐藏的sheet页。 起个名字吧!叫"hidden"!
|
||||
Sheet hiddenSheet = workbook.createSheet(hiddenName);
|
||||
//2.循环赋值(为了防止下拉框的行数与隐藏域的行数相对应,将隐藏域加到结束行之后)
|
||||
for (int i = 0; i < explicitList.size(); i++) {
|
||||
hiddenSheet.createRow(65535 + i).createCell(columnIndex).setCellValue(explicitList.get(i));
|
||||
}
|
||||
Name category1Name = workbook.createName();
|
||||
category1Name.setNameName(hiddenName);
|
||||
//3 A1:A代表隐藏域创建第N列createCell(N)时。以A1列开始A行数据获取下拉数组
|
||||
category1Name.setRefersToFormula(hiddenName + "!A1:A" + (explicitList.size() + 65535));
|
||||
//
|
||||
DataValidationHelper helper = sheet.getDataValidationHelper();
|
||||
DataValidationConstraint constraint = helper.createFormulaListConstraint(hiddenName);
|
||||
CellRangeAddressList addressList = new CellRangeAddressList(1, 65535, columnIndex, columnIndex);
|
||||
DataValidation dataValidation = helper.createValidation(constraint, addressList);
|
||||
if (dataValidation instanceof XSSFDataValidation) {
|
||||
// 数据校验
|
||||
dataValidation.setSuppressDropDownArrow(true);
|
||||
dataValidation.setShowErrorBox(true);
|
||||
} else {
|
||||
dataValidation.setSuppressDropDownArrow(false);
|
||||
}
|
||||
// 作用在目标sheet上
|
||||
sheet.addValidationData(dataValidation);
|
||||
// 设置hiddenSheet隐藏
|
||||
workbook.setSheetHidden(hiddenSheetIndex, true);
|
||||
hiddenSheetIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
77
src/main/java/com/senmesh/common/easyexcel/ExcelUtil.java
Normal file
77
src/main/java/com/senmesh/common/easyexcel/ExcelUtil.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package com.senmesh.common.easyexcel;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.senmesh.common.dto.ExportHeadDetailInfoDTO;
|
||||
import com.senmesh.common.dto.ExportHeadInfoDTO;
|
||||
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
public class ExcelUtil {
|
||||
|
||||
|
||||
private ExcelUtil() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 动态导出excel模板
|
||||
*
|
||||
* @param reqDto 点播dto
|
||||
*/
|
||||
public static void dynamicExportTemplate(ExportHeadInfoDTO reqDto) {
|
||||
if (CollUtil.isEmpty(reqDto.getHeads())) {
|
||||
return;
|
||||
}
|
||||
ImportDataContext.set("exportInfo", reqDto);
|
||||
|
||||
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletResponse response = attr.getResponse();
|
||||
if (Objects.isNull(response)) {
|
||||
return;
|
||||
}
|
||||
String fileName = reqDto.getFileName() + ".xlsx";
|
||||
|
||||
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
String fileNamePrefix = StrUtil.subBefore(fileName, ".", true);
|
||||
String fileNameSuffix = StrUtil.subAfter(fileName, ".", true);
|
||||
try {
|
||||
String fileNamePrefix2 = URLEncoder.encode(fileNamePrefix, "UTF-8").replaceAll("\\+", "%20");
|
||||
response.setHeader("Content-Disposition", "attachment;" + fileNamePrefix2 + "." + fileNameSuffix);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalArgumentException("下载文件异常");
|
||||
}
|
||||
response.addHeader("Param", "no-cache");
|
||||
response.addHeader("Cache-Control", "no-cache");
|
||||
|
||||
try (OutputStream out = response.getOutputStream();) {
|
||||
ExcelWriter writer = EasyExcel.write(out).registerWriteHandler(new DynamicExportTemplateCellWriteHandler()).build();
|
||||
List<List> objects = Lists.newArrayList();
|
||||
objects.add(reqDto.getHeads().stream().map(ExportHeadDetailInfoDTO::getHead).collect(Collectors.toList()));
|
||||
objects.addAll(reqDto.getDatas());
|
||||
writer.write(objects, EasyExcel.writerSheet("sheet").build());
|
||||
writer.finish();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.senmesh.common.easyexcel;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ImportDataContext {
|
||||
public static final ThreadLocal<Map<String, Object>> THREAD_LOCAL_MAP = new ThreadLocal<>();
|
||||
|
||||
public static Object get(String key) {
|
||||
Map<String, Object> stringObjectMap = THREAD_LOCAL_MAP.get();
|
||||
if (Objects.isNull(stringObjectMap)) {
|
||||
THREAD_LOCAL_MAP.set(Maps.newHashMap());
|
||||
return null;
|
||||
}
|
||||
return stringObjectMap.get(key);
|
||||
}
|
||||
|
||||
public static void set(String key,Object value) {
|
||||
Map<String, Object> stringObjectMap = THREAD_LOCAL_MAP.get();
|
||||
if (Objects.isNull(stringObjectMap)) {
|
||||
THREAD_LOCAL_MAP.set(Maps.newHashMap());
|
||||
}
|
||||
THREAD_LOCAL_MAP.get().put(key,value);
|
||||
}
|
||||
|
||||
public static void putAll(Map<String, Object> extraInfoMap){
|
||||
Map<String, Object> stringObjectMap = THREAD_LOCAL_MAP.get();
|
||||
if (Objects.isNull(stringObjectMap)) {
|
||||
THREAD_LOCAL_MAP.set(Maps.newHashMap());
|
||||
}
|
||||
THREAD_LOCAL_MAP.get().putAll(extraInfoMap);
|
||||
}
|
||||
}
|
||||
67
src/main/java/com/senmesh/common/entity/BaseEntity.java
Normal file
67
src/main/java/com/senmesh/common/entity/BaseEntity.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package com.senmesh.common.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.senmesh.common.dto.IBaseDTO;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* @author Rey(leijiaping @ newyetai.com)
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
public abstract class BaseEntity implements Serializable, Cloneable, IBaseDTO {
|
||||
|
||||
private static final long serialVersionUID = -723338960662087915L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
/**
|
||||
* 是否逻辑删除(0否1是)
|
||||
*/
|
||||
@TableField(value = "deleted", fill = FieldFill.INSERT)
|
||||
@Builder.Default
|
||||
private Boolean deleted = Boolean.FALSE;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField(value = "create_by", fill = FieldFill.INSERT)
|
||||
private Long createBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
@TableField(value = "update_by", fill = FieldFill.UPDATE)
|
||||
private Long updateBy;
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@TableField(value = "update_time", fill = FieldFill.UPDATE)
|
||||
private Date updateTime;
|
||||
/**
|
||||
* 代理人
|
||||
*/
|
||||
private Long proxyBy;
|
||||
}
|
||||
27
src/main/java/com/senmesh/common/entity/OrgBaseEntity.java
Normal file
27
src/main/java/com/senmesh/common/entity/OrgBaseEntity.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.senmesh.common.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* 机构基础实体
|
||||
* @author sr on 2019-10-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder
|
||||
public class OrgBaseEntity extends BaseEntity {
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 2559571969035017003L;
|
||||
|
||||
/** 机构id **/
|
||||
private Long orgId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
|
||||
/**
|
||||
* 项目所有自定义异常父类
|
||||
*
|
||||
* @author guhong
|
||||
*/
|
||||
public class AlitaException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 3121871576733025786L;
|
||||
|
||||
public AlitaException() {}
|
||||
|
||||
public AlitaException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AlitaException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public AlitaException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*
|
||||
* @author guhong
|
||||
* @date 2019/8/19
|
||||
*/
|
||||
public class BusinessException extends AlitaException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -3097174055942519169L;
|
||||
|
||||
public BusinessException() {}
|
||||
|
||||
public BusinessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BusinessException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public BusinessException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
import com.senmesh.common.AlitaResult;
|
||||
import com.senmesh.common.dto.CasTokenDTO;
|
||||
|
||||
/**
|
||||
* 更新token
|
||||
* @author sr on 2021-07-05
|
||||
*/
|
||||
public class ChangeTokenException extends WithResultException{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = -8897274199463229506L;
|
||||
|
||||
|
||||
public ChangeTokenException(CasTokenDTO casTokenDTO) {
|
||||
super(AlitaResult.changeToken(casTokenDTO));
|
||||
}
|
||||
|
||||
public CasTokenDTO getCasTokenDTO(){
|
||||
return (CasTokenDTO) getResult().getErrorData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
import com.senmesh.common.exception.util.DevopsUtils;
|
||||
|
||||
/**
|
||||
* 运维业务异常
|
||||
* @author sr on 2022-03-01
|
||||
*/
|
||||
public class DevopsException extends BusinessException{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DevopsException(String message) {
|
||||
super(message);
|
||||
DevopsUtils.deal(message);
|
||||
}
|
||||
|
||||
public DevopsException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
DevopsUtils.deal(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
/**
|
||||
* 已存在业务异常
|
||||
* @author sr on 2022-03-01
|
||||
*/
|
||||
public class ExistException extends BusinessException{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ExistException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ExistException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ExistException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
public interface IDevopsProvider {
|
||||
|
||||
void deal(String msg);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
/**
|
||||
* 用户未登录异常
|
||||
*
|
||||
* @author guhong
|
||||
* @date 2019/8/19
|
||||
*/
|
||||
public class NoneLoginException extends AlitaException {
|
||||
|
||||
public static final String ERROR_MSG = "用户未登录";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -7013134475760472324L;
|
||||
|
||||
public NoneLoginException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
public NoneLoginException() {
|
||||
super(ERROR_MSG);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.senmesh.common.exception;
|
||||
|
||||
import com.senmesh.common.AlitaResult;
|
||||
|
||||
/**
|
||||
* 更新token
|
||||
* @author sr on 2021-07-05
|
||||
*/
|
||||
public class WithResultException extends AlitaException{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = -8897274199463229506L;
|
||||
|
||||
private AlitaResult<?> result;
|
||||
|
||||
public WithResultException(AlitaResult<?> result) {
|
||||
super(result.getMsg());
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public WithResultException(AlitaResult<?> result, Throwable cause) {
|
||||
super(result.getMsg(), cause);
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public AlitaResult<?> getResult(){
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.senmesh.common.exception.controller;
|
||||
|
||||
import com.senmesh.common.exception.dao.ExceptionLogMapper;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 异常日志查看
|
||||
*
|
||||
* @author on 2019-11-05
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/anon/exception")
|
||||
@Api(tags = "异常日志查看")
|
||||
public class ExceptionLogController {
|
||||
|
||||
@Autowired
|
||||
private ExceptionLogMapper exceptionLogMapper;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public String getExceptionMsg(@PathVariable Long id) {
|
||||
try {
|
||||
return exceptionLogMapper.selectById(id).getMsg();
|
||||
} catch (Exception e) {
|
||||
return "未找到对应id错误";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.senmesh.common.exception.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.senmesh.common.exception.entity.ExceptionLog;
|
||||
|
||||
/**
|
||||
* 异常日志
|
||||
*
|
||||
* @author on 2019-11-05
|
||||
*/
|
||||
public interface ExceptionLogMapper extends BaseMapper<ExceptionLog> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.senmesh.common.exception.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 错误日志
|
||||
* @author sr on 2019-10-28
|
||||
*/
|
||||
@TableName("xs_exception_log")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class ExceptionLog implements Serializable{
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 3730091070919812549L;
|
||||
|
||||
/** 主键 **/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 创建时间 **/
|
||||
private Date createTime;
|
||||
|
||||
/** 错误信息 **/
|
||||
private String msg;
|
||||
|
||||
public ExceptionLog(Date createTime, String msg) {
|
||||
super();
|
||||
this.createTime = createTime;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package com.senmesh.common.exception.handle;
|
||||
|
||||
import com.senmesh.common.util.EnvironmentUtils;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import com.senmesh.common.AlitaResult;
|
||||
import com.senmesh.common.constant.CommonConstants;
|
||||
import com.senmesh.common.exception.BusinessException;
|
||||
import com.senmesh.common.exception.NoneLoginException;
|
||||
import com.senmesh.common.exception.WithResultException;
|
||||
import com.senmesh.common.log.dto.ExceptionLogDTO;
|
||||
import com.senmesh.common.log.util.LogUtils;
|
||||
import com.senmesh.common.util.SpringContextHolder;
|
||||
import com.senmesh.common.util.TracerUtils;
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*
|
||||
* @author guhong
|
||||
* @date 2019/8/19
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalControllerExceptionHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(GlobalControllerExceptionHandler.class);
|
||||
|
||||
@Value("${spring.application.name:}")
|
||||
private String applicationName;
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*
|
||||
* @param ex
|
||||
*/
|
||||
@ExceptionHandler(value = {BusinessException.class})
|
||||
public AlitaResult<String> handleBusinessException(BusinessException ex) {
|
||||
String traceId = TracerUtils.getTraceId();
|
||||
String msg;
|
||||
if (StringUtils.isNotBlank(ex.getMessage()) && ex.getMessage().contains(traceId)) {
|
||||
msg = ex.getMessage();
|
||||
}else {
|
||||
msg = String.format("[%s]操作失败:%s", traceId, ex.getMessage());
|
||||
}
|
||||
|
||||
LOGGER.debug(msg, ex);
|
||||
AlitaResult<String> alitaResult = AlitaResult.error(AlitaResult.BUSINESS_ERROR_CODE, msg);
|
||||
alitaResult.setRequestId(traceId);
|
||||
return alitaResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理未登录异常
|
||||
*
|
||||
* @param ex
|
||||
*/
|
||||
@ExceptionHandler(value = {NoneLoginException.class})
|
||||
public AlitaResult<String> handleNoneLoginException(NoneLoginException ex) {
|
||||
AlitaResult<String> alitaResult = AlitaResult.unLogin();
|
||||
alitaResult.setRequestId(TracerUtils.getTraceId());
|
||||
return alitaResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理更换token
|
||||
*
|
||||
* @param ex
|
||||
*/
|
||||
@ExceptionHandler(value = {WithResultException.class})
|
||||
public AlitaResult<?> handleChangeTokenException(WithResultException ex) {
|
||||
AlitaResult<?> result = ex.getResult();
|
||||
result.setRequestId(TracerUtils.getTraceId());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理校验异常
|
||||
*
|
||||
* @param ex
|
||||
*/
|
||||
@ExceptionHandler(value = {
|
||||
MethodArgumentNotValidException.class,
|
||||
BindException.class})
|
||||
public AlitaResult<String> handleValidationException(Exception ex) {
|
||||
BindingResult result;
|
||||
if (ex instanceof MethodArgumentNotValidException) {
|
||||
result = ((MethodArgumentNotValidException) ex).getBindingResult();
|
||||
} else {
|
||||
result = ((BindException) ex).getBindingResult();
|
||||
}
|
||||
if (!result.hasErrors()) {
|
||||
return AlitaResult.error("操作失败");
|
||||
}
|
||||
|
||||
StringJoiner joiner = new StringJoiner(",");
|
||||
List<ObjectError> errors = result.getAllErrors();
|
||||
|
||||
errors.forEach(error -> {
|
||||
if (error instanceof FieldError) {
|
||||
joiner.add(((FieldError) error).getField() + "-" + error.getDefaultMessage());
|
||||
} else {
|
||||
joiner.add(error.getDefaultMessage());
|
||||
}
|
||||
});
|
||||
|
||||
String msg = String.format("数据异常:%s", joiner.toString());
|
||||
LOGGER.error(msg);
|
||||
AlitaResult<String> alitaResult = AlitaResult.error(AlitaResult.VALIDATION_ERROR_CODE, msg);
|
||||
alitaResult.setRequestId(TracerUtils.getTraceId());
|
||||
return alitaResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理未知的错误
|
||||
*
|
||||
* @param ex
|
||||
*/
|
||||
@ExceptionHandler(value = {ConstraintViolationException.class})
|
||||
@Transactional(rollbackFor = RuntimeException.class)
|
||||
public AlitaResult<String> handleConstraintViolationException(ConstraintViolationException ex) {
|
||||
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
|
||||
StringJoiner joiner = new StringJoiner(CommonConstants.COMMA);
|
||||
constraintViolations.stream().forEach(error -> joiner.add(error.getMessage()));
|
||||
String msg = String.format("数据异常:%s", joiner.toString());
|
||||
LOGGER.error(msg);
|
||||
AlitaResult<String> alitaResult = AlitaResult.error(AlitaResult.VALIDATION_ERROR_CODE, msg);
|
||||
alitaResult.setRequestId(TracerUtils.getTraceId());
|
||||
return alitaResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理未知的错误
|
||||
*
|
||||
* @param ex
|
||||
*/
|
||||
@ExceptionHandler(value = {Exception.class})
|
||||
@Transactional(rollbackFor = RuntimeException.class)
|
||||
public AlitaResult<String> handleUnknownException(Exception ex) {
|
||||
String msg = null;
|
||||
if (ex instanceof HttpRequestMethodNotSupportedException) {
|
||||
msg = "请求错误:" + ((HttpRequestMethodNotSupportedException) ex).getSupportedMethods()[0]
|
||||
+ SpringContextHolder.getRequest().getRequestURI();
|
||||
} else {
|
||||
LOGGER.error("",ex);
|
||||
ExceptionLogDTO exceptionLogDTO = ExceptionLogDTO.builder().traceId(TracerUtils.getTraceId())
|
||||
.msg(ExceptionUtils.getStackTrace(ex)).build();
|
||||
LogUtils.log(exceptionLogDTO);
|
||||
msg = String.format("系统异常[%s#%s],请稍后重试.",
|
||||
EnvironmentUtils.getSystemCode(), exceptionLogDTO.getErrNo()
|
||||
);
|
||||
LOGGER.error("系统异常,错误号:{}", exceptionLogDTO.getErrNo());
|
||||
}
|
||||
|
||||
AlitaResult<String> alitaResult = AlitaResult.error(msg);
|
||||
alitaResult.setRequestId(TracerUtils.getTraceId());
|
||||
return alitaResult;
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void initBinder(WebDataBinder binder) {
|
||||
binder.registerCustomEditor(String.class, new StringTrimmerEditor(" \t\r\n\f", true));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
133
src/main/java/com/senmesh/common/exception/util/Assert.java
Normal file
133
src/main/java/com/senmesh/common/exception/util/Assert.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package com.senmesh.common.exception.util;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.senmesh.common.constant.CommonConstants;
|
||||
import com.senmesh.common.exception.BusinessException;
|
||||
import com.senmesh.common.util.JsonUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* 断言
|
||||
*
|
||||
* @author sr on 2020-09-02
|
||||
*/
|
||||
@Slf4j
|
||||
public class Assert {
|
||||
|
||||
private Assert() {
|
||||
}
|
||||
|
||||
private static void dealLog(String message, Object... logData) {
|
||||
if (logData.length > 0) {
|
||||
log.info(new StringBuilder().append(message).append(CommonConstants.COLON)
|
||||
.append(JsonUtils.toJsonString(logData)).toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* true正常,fasle抛BusinessException
|
||||
*
|
||||
* @param expression
|
||||
* @param message
|
||||
* @author sr on 2020-09-02
|
||||
*/
|
||||
public static void isTrue(boolean expression, String message, Object... logData) {
|
||||
if (!expression) {
|
||||
dealLog(message, logData);
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* true正常,fasle抛BusinessException
|
||||
*
|
||||
* @param expression 表达式
|
||||
* @param message 消息
|
||||
*/
|
||||
public static void isTrue(boolean expression, Supplier<String> message) {
|
||||
if (!expression) {
|
||||
throw new BusinessException(message.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* true正常,fasle抛指定异常
|
||||
* @param expression
|
||||
* @param e
|
||||
* @author sr on 2021-06-18
|
||||
*/
|
||||
public static void isTrue(boolean expression, RuntimeException e) {
|
||||
if (!expression) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* null正常,notNull抛BusinessException
|
||||
*
|
||||
* @param object
|
||||
* @param message
|
||||
* @author sr on 2020-09-02
|
||||
*/
|
||||
public static void isNull(@Nullable Object object, String message, Object... logData) {
|
||||
if (object != null) {
|
||||
dealLog(message, logData);
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* notNull正常,null抛BusinessException
|
||||
*
|
||||
* @param object
|
||||
* @param message
|
||||
* @author sr on 2020-09-02
|
||||
*/
|
||||
public static void notNull(@Nullable Object object, String message, Object... logData) {
|
||||
if (object == null) {
|
||||
dealLog(message, logData);
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* notNull正常,null抛BusinessException
|
||||
*
|
||||
* @param object 对象
|
||||
* @param message 消息
|
||||
*/
|
||||
public static void notNull(@Nullable Object object, Supplier<String> message) {
|
||||
if (object == null) {
|
||||
throw new BusinessException(message.get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* notBlank正常,blank抛BusinessException
|
||||
*
|
||||
* @param str
|
||||
* @param message
|
||||
* @author sr on 2021-01-06
|
||||
*/
|
||||
public static void notBlank(String str, String message, Object... logData) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
dealLog(message, logData);
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void notEmpty(@Nullable Collection<?> collection, String message) {
|
||||
if (CollectionUtils.isEmpty(collection)) {
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.senmesh.common.exception.util;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.senmesh.common.exception.IDevopsProvider;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 运维工具类
|
||||
* @author sr on 2022-03-01
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DevopsUtils {
|
||||
|
||||
private static IDevopsProvider devopsProvider;
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setDevopsProvider(IDevopsProvider devopsProvider) {
|
||||
DevopsUtils.devopsProvider = devopsProvider;
|
||||
}
|
||||
|
||||
public static void deal(String msg) {
|
||||
if (devopsProvider == null) {
|
||||
log.error("no devops provider, error:{}", msg);
|
||||
return ;
|
||||
}
|
||||
devopsProvider.deal(msg);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.senmesh.common.exception.util;
|
||||
|
||||
import com.senmesh.common.exception.BusinessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 异常工具类
|
||||
* @author sr on 2019-10-14
|
||||
*/
|
||||
@Slf4j
|
||||
public class ExceptionUtils {
|
||||
|
||||
/**
|
||||
* @Description 抛异常
|
||||
* @Author chenyun.huang
|
||||
* @Date 2020/3/27 15:06
|
||||
**/
|
||||
public static void throwBusinessException(String msg) {
|
||||
ExceptionUtils.throwBusinessException(true,msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据判断抛异常
|
||||
* @param isThrow
|
||||
* @param msg 异常信息
|
||||
* @author sr on 2019-10-14
|
||||
*/
|
||||
public static void throwBusinessException(boolean isThrow, String msg) {
|
||||
if (isThrow) {
|
||||
throw new BusinessException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据判断抛异常
|
||||
* @param isThrow
|
||||
* @param errorMsg 异常信息
|
||||
* @param logMsg 日志信息(info级)
|
||||
* @author sr on 2019-12-18
|
||||
*/
|
||||
public static void throwBusinessException(boolean isThrow, String errorMsg, String logMsg) {
|
||||
if (isThrow) {
|
||||
log.info(logMsg);
|
||||
throw new BusinessException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.senmesh.common.exception.util;
|
||||
|
||||
import com.senmesh.common.util.RandomUtils;
|
||||
|
||||
/**
|
||||
* uuid工具类
|
||||
* {@link RandomUtils}
|
||||
* @author sr on 2019-12-10
|
||||
*/
|
||||
@Deprecated
|
||||
public class UUIDUtils {
|
||||
|
||||
/**
|
||||
* 生成uuid,去掉-
|
||||
* @return
|
||||
* @author sr on 2019-12-10
|
||||
*/
|
||||
public static String generateUUID() {
|
||||
return RandomUtils.generateUUID();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.senmesh.common.freemarker.constant;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-13
|
||||
*/
|
||||
public enum BusinessModelFileEnum {
|
||||
|
||||
/** 常量 **/
|
||||
CONSTANT("Constants.java", "constant", "Constant.ftl"),
|
||||
/** 控制层 **/
|
||||
CONTROLLER_FILE_SUFFIX("Controller.java", "controller", "Controller.ftl"),
|
||||
/** dao **/
|
||||
DAO_FILE_SUFFIX("Mapper.java", "dao", "Dao.ftl"),
|
||||
/** dto **/
|
||||
DTO_FILE_SUFFIX("DTO.java", "dto", "DTO.ftl"),
|
||||
/** operateDto **/
|
||||
OPERATE_DTO_FILE_SUFFIX("OperateDTO.java", "dto", "OperateDTO.ftl"),
|
||||
/** queryDto **/
|
||||
QUERY_DTO_FILE_SUFFIX("QueryDTO.java", "dto", "QueryDTO.ftl"),
|
||||
/** entity **/
|
||||
ENTITY_FILE_SUFFIX(".java", "entity", "entity.ftl"),
|
||||
/** mapper **/
|
||||
MAPPER_FILE_SUFFIX("Mapper.xml", "mapper", "Mapper.ftl"),
|
||||
/** mapstruct **/
|
||||
MAPSTRUCT_FILE_SUFFIX("MapMapper.java", "mapstruct", "MapMapper.ftl"),
|
||||
/** service **/
|
||||
SERVICE_FILE_SUFFIX("Service.java", "service", "Service.ftl"),
|
||||
/** serviceImpl **/
|
||||
SERVICE_IMPL_FILE_SUFFIX("ServiceImpl.java", "service.impl", "ServiceImpl.ftl"),
|
||||
/** util **/
|
||||
UTIL_FILE_SUFFIX("Utils.java", "util", "Util.ftl");
|
||||
|
||||
|
||||
|
||||
/** 生成文件后缀 **/
|
||||
private String generatefileSuffix;
|
||||
/** 包名 **/
|
||||
private String packageName;
|
||||
/** 模版文件后缀 **/
|
||||
private String ftlFile;
|
||||
|
||||
private BusinessModelFileEnum(String fileSuffix, String packageName, String ftlFile) {
|
||||
this.generatefileSuffix = fileSuffix;
|
||||
this.packageName = packageName;
|
||||
this.ftlFile = ftlFile;
|
||||
}
|
||||
|
||||
public String getGeneratefileSuffix() {
|
||||
return generatefileSuffix;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public String getFtlFile() {
|
||||
return ftlFile;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.senmesh.common.freemarker.constant;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-10
|
||||
*/
|
||||
public interface FreemarkerConstants {
|
||||
|
||||
/** 数据库表名前缀 **/
|
||||
String TABLE_PREFIX = "xs_";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.senmesh.common.freemarker.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-10
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class BusinessModelCreateDTO implements Serializable {
|
||||
|
||||
/** **/
|
||||
private static final long serialVersionUID = 3962743989033667188L;
|
||||
|
||||
/**
|
||||
* 文件输出路径-绝对路径,如/work/eclipse/workspace/alita-base/common/src/main/java/com/newyetai/common/freemarker/
|
||||
**/
|
||||
private String exportDir;
|
||||
/** 包路径,如com.newyetai.dict **/
|
||||
private String packageName;
|
||||
/** 是否创建业务路径,默认创建 **/
|
||||
private Boolean createBusinessPath;
|
||||
/** 数据库表名:为空,则默认xs_entityName(snake小写) **/
|
||||
private String tableName;
|
||||
/** 作者名 **/
|
||||
private String author;
|
||||
/** 实体名,如Dict **/
|
||||
private String entityName;
|
||||
/** 实体名描述,如数据字典 **/
|
||||
private String entityNameDescription;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.senmesh.common.freemarker.util;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.senmesh.common.constant.CommonConstants;
|
||||
import com.senmesh.common.freemarker.constant.BusinessModelFileEnum;
|
||||
import com.senmesh.common.freemarker.constant.FreemarkerConstants;
|
||||
import com.senmesh.common.freemarker.dto.BusinessModelCreateDTO;
|
||||
import com.senmesh.common.util.StrUtils;
|
||||
|
||||
import freemarker.template.Template;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-13
|
||||
*/
|
||||
@Slf4j
|
||||
public class CodeGenerateUtils {
|
||||
|
||||
public static void generateModelFile(BusinessModelCreateDTO businessModelCreateDto) {
|
||||
for (BusinessModelFileEnum businessModelFileEnum : BusinessModelFileEnum.values()) {
|
||||
generateModelFile(businessModelCreateDto, businessModelFileEnum);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean generateModelFile(BusinessModelCreateDTO businessModelCreateDto,
|
||||
BusinessModelFileEnum businessModelFileEnum) {
|
||||
// 文件输出路径/包名路径/实体名+文件后缀
|
||||
String entityName = businessModelCreateDto.getEntityName();
|
||||
String entityNameLowerCase = StrUtils.toLowerCamel(entityName);
|
||||
String entityNameSnake = StrUtils.toSnake(entityNameLowerCase);
|
||||
String packageName = businessModelCreateDto.getPackageName();
|
||||
String tableName = businessModelCreateDto.getTableName();
|
||||
String path = String.join(StringUtils.EMPTY,
|
||||
packageNameToPath(businessModelFileEnum.getPackageName()), File.separator,
|
||||
entityName, businessModelFileEnum.getGeneratefileSuffix());
|
||||
if (!Boolean.FALSE.equals(businessModelCreateDto.getCreateBusinessPath())) {
|
||||
path = String.join(StringUtils.EMPTY, entityName.toLowerCase(), File.separator, path);
|
||||
packageName = String.join(CommonConstants.POINT, packageName, entityName.toLowerCase());
|
||||
}
|
||||
final String templateName = businessModelFileEnum.getFtlFile();
|
||||
File file = new File(businessModelCreateDto.getExportDir(), path);
|
||||
if (!file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
Map<String, Object> dataMap = new HashMap<>();
|
||||
try {
|
||||
dataMap.put("packageName", packageName);
|
||||
dataMap.put("author", businessModelCreateDto.getAuthor());
|
||||
dataMap.put("entityName", entityName);
|
||||
dataMap.put("entityNameLowerCamel", entityNameLowerCase);
|
||||
dataMap.put("entityNameSnake", entityNameSnake);
|
||||
dataMap.put("entityNameDescription", businessModelCreateDto.getEntityNameDescription());
|
||||
dataMap.put("tableName",
|
||||
StringUtils.isBlank(tableName) ? FreemarkerConstants.TABLE_PREFIX + entityNameSnake
|
||||
: tableName);
|
||||
|
||||
generateFileByTemplate(templateName, file, dataMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.info("generateFile fail:{}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
log.info("generateFile suc:{}", file.getPath());
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void generateFileByTemplate(final String templateName, File file,
|
||||
Map<String, Object> dataMap) throws Exception {
|
||||
Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
|
||||
template.process(dataMap, out);
|
||||
}
|
||||
|
||||
public static String packageNameToPath(String packageName) {
|
||||
return packageName.replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.senmesh.common.freemarker.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Map;
|
||||
|
||||
import freemarker.cache.ClassTemplateLoader;
|
||||
import freemarker.cache.NullCacheStorage;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author sr on 2020-04-13
|
||||
*/
|
||||
@Slf4j
|
||||
public class FreeMarkerTemplateUtils {
|
||||
|
||||
private FreeMarkerTemplateUtils() {}
|
||||
|
||||
private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22);
|
||||
|
||||
static {
|
||||
//这里比较重要,用来指定加载模板所在的路径
|
||||
CONFIGURATION
|
||||
.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class, "/ftls"));
|
||||
CONFIGURATION.setDefaultEncoding("UTF-8");
|
||||
CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
|
||||
CONFIGURATION.setClassicCompatible(true);
|
||||
}
|
||||
|
||||
public static Template getTemplate(String templateName) throws IOException {
|
||||
try {
|
||||
return CONFIGURATION.getTemplate(templateName);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串模版占位符替换
|
||||
* @param templateStr
|
||||
* @param params
|
||||
* @return
|
||||
* @author sr on 2020-12-21
|
||||
*/
|
||||
public static String formatString(String templateStr, Map<String, Object> params) {
|
||||
try {
|
||||
Template template = new Template("formatString", templateStr, FreeMarkerTemplateUtils.CONFIGURATION);
|
||||
StringWriter result = new StringWriter();
|
||||
template.process(params, result);
|
||||
return result.toString();
|
||||
} catch (IOException | TemplateException e) {
|
||||
log.error("内容占位符替换失败:{}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static void clearCache() {
|
||||
CONFIGURATION.clearTemplateCache();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.senmesh.common.function;
|
||||
|
||||
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TransactionAfterCommit {
|
||||
|
||||
void afterCommit();
|
||||
|
||||
/**
|
||||
* 事务提交后的回调操作
|
||||
*
|
||||
* @param transactionAfterCommit 事务提交后
|
||||
*/
|
||||
static void doSomeThingAfterCommit(TransactionAfterCommit transactionAfterCommit) {
|
||||
TransactionSynchronizationManager
|
||||
.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
transactionAfterCommit.afterCommit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void doSomeThingAfterCompletion(TransactionAfterCommit transactionAfterCommit) {
|
||||
TransactionSynchronizationManager
|
||||
.registerSynchronization(new TransactionSynchronizationAdapter() {
|
||||
@Override
|
||||
public void afterCompletion(int status) {
|
||||
transactionAfterCommit.afterCommit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user