提交 a6bfca56 编写于 作者: sq3536's avatar sq3536

init

上级 4f6069f5
*volumes
*target
.settings
*node_modules
*bin
*.project
*.classpath
*.factorypath
.history
.vscode
.idea
**.iml
*.jar
*.log
.DS_Store
devsys
\ No newline at end of file
此差异已折叠。
package cn.ibizlab.util.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD})
public @interface Audit
{
}
package cn.ibizlab.util.annotation;
import cn.ibizlab.util.enums.DEFieldDefaultValueType;
import cn.ibizlab.util.enums.DEPredefinedFieldType;
import cn.ibizlab.util.enums.DupCheck;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD})
public @interface DEField
{
/**
* 属性名称
* @return
*/
String name() default "";
/**
* 属性名称
* @return
*/
String value() default "";
/**
* 是否为数据主键
* @return
*/
boolean isKeyField() default false;
/**
* 默认值
* @return
*/
String defaultValue() default "";
/**
* 属性类型
* @return
*/
String fieldType() default"";
/**
* 默认值类型
* @return
*/
DEFieldDefaultValueType defaultValueType() default DEFieldDefaultValueType.NONE;
/**
* 预置属性类型
* @return
*/
DEPredefinedFieldType preType() default DEPredefinedFieldType.NONE;
/**
* 逻辑删除有效值
* @return
*/
String logicval() default "";
/**
* 逻辑删除无效值
* @return
*/
String logicdelval() default "";
/**
* 代码表
* @return
*/
String dict() default "";
/**
* 日期格式化
* @return
*/
String format() default "";
/**
* 重复性检查
* @return
*/
DupCheck dupCheck() default DupCheck.NONE;
/**
* 范围属性
*/
String dupCheckField() default "";
}
package cn.ibizlab.util.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD})
public @interface VersionCheck
{
String entity();
String versionfield();
}
package cn.ibizlab.util.aspect;
import lombok.SneakyThrows;
import cn.ibizlab.util.annotation.Audit;
import cn.ibizlab.util.domain.EntityBase;
import cn.ibizlab.util.helper.DEFieldCacheMap;
import cn.ibizlab.util.service.IBZDataAuditService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* 实体数据审计切面类
*/
@Aspect
@Component
public class AuditAspect
{
private final ExpressionParser parser = new SpelExpressionParser();
@Autowired
IBZDataAuditService dataAuditService;
/**
* 实体数据建立切面,在成功创建数据后将新增数据内容记录审计日志内(审计明细【AuditInfo】中只记录审计属性变化情况,审计属性在平台属性中配置)
* @param point
*/
@AfterReturning(value = "execution(* cn.ibizlab.core.*.service.*.create(..))")
@SneakyThrows
public void create(JoinPoint point) {
HttpServletRequest request = null;
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if(requestAttributes!=null) {
request = ((ServletRequestAttributes)requestAttributes).getRequest();
}
Object [] args = point.getArgs();
if(ObjectUtils.isEmpty(args) || args.length==0) {
return;
}
Object serviceParam = args[0];
if(serviceParam instanceof EntityBase) {
EntityBase entity = (EntityBase)serviceParam;
Map<String, Audit> auditFields = DEFieldCacheMap.getAuditFields(entity.getClass());
//是否有审计属性
if(auditFields.size()==0) {
return;
}
String idField = DEFieldCacheMap.getDEKeyField(entity.getClass());
Object idValue = "";
if(!StringUtils.isEmpty(idField)) {
idValue=entity.get(idField);
}
//记录审计日志
dataAuditService.createAudit(request, entity, idValue, auditFields);
}
}
/**
* 实体数据更新切面,在成功更新数据后将新增数据内容记录审计日志内(审计明细【AuditInfo】中只记录审计属性变化情况,审计属性在平台属性中配置)
* 使用环切【@Around】获取到更新前后的实体数据并进行差异比较,并将差异内容记入审计日志内
* @param point
*/
@Around("execution(* cn.ibizlab.core.*.service.*.update(..))")
public Object update(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = null;
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if(requestAttributes!=null) {
request=((ServletRequestAttributes)requestAttributes).getRequest();
}
Object serviceObj = point.getTarget();
Object args[] = point.getArgs();
if(ObjectUtils.isEmpty(args) || args.length==0) {
return point.proceed();
}
Object arg = args[0];
if(arg instanceof EntityBase) {
EntityBase entity = (EntityBase) arg;
Map<String, Audit> auditFields = DEFieldCacheMap.getAuditFields(entity.getClass());
//是否有审计属性
if(auditFields.size()==0) {
return point.proceed();
}
String idField = DEFieldCacheMap.getDEKeyField(entity.getClass());
Object idValue = "";
if(!StringUtils.isEmpty(idField)){
idValue = entity.get(idField);
}
if(ObjectUtils.isEmpty(idValue)) {
return point.proceed();
}
//获取更新前实体
EntityBase beforeEntity = getEntity(serviceObj, idValue);
//执行更新操作
point.proceed();
//记录审计日志
dataAuditService.updateAudit(request, beforeEntity, serviceObj, idValue, auditFields);
return true;
}
return point.proceed();
}
/**
* 实体数据更新切面,在成功更新数据后将新增数据内容记录审计日志内(审计明细【AuditInfo】中只记录审计属性变化情况,审计属性在平台属性中配置)
* 使用环切【@Around】获取要删除的完整数据,并将审计属性相关信息记录到审计日志中
* @param point
* @return
* @throws Throwable
*/
@Around("execution(* cn.ibizlab.core.*.service.*.remove(..))")
public Object remove(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = null;
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if(requestAttributes!= null) {
request = ((ServletRequestAttributes)requestAttributes).getRequest();
}
Object serviceObj = point.getTarget();
Object args[] = point.getArgs();
if(ObjectUtils.isEmpty(args) || args.length==0) {
return point.proceed();
}
Object idValue = args[0];
EntityBase entity = getEntity(serviceObj, idValue);
Map<String, Audit> auditFields = DEFieldCacheMap.getAuditFields(entity.getClass());
if(auditFields.size()==0) {
return point.proceed();
}
else{
//执行删除操作
point.proceed();
//记录审计日志
dataAuditService.removeAudit(request, entity, idValue, auditFields);
return true;
}
}
/**
* 获取实体
* @param service
* @param id
* @return
*/
@SneakyThrows
private EntityBase getEntity(Object service, Object id) {
EntityBase entity = null;
if(!ObjectUtils.isEmpty(service)) {
EvaluationContext oldContext = new StandardEvaluationContext();
oldContext.setVariable("service", service);
oldContext.setVariable("id", id);
Expression oldExp = parser.parseExpression("#service.get(#id)");
return oldExp.getValue(oldContext, EntityBase.class);
}
return entity;
}
}
\ No newline at end of file
此差异已折叠。
package cn.ibizlab.util.aspect;
import lombok.SneakyThrows;
import cn.ibizlab.util.annotation.VersionCheck;
import cn.ibizlab.util.domain.EntityBase;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.helper.RuleUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* 数据库版本检查
*/
@Aspect
@Order(50)
@Component
public class VersionCheckAspect
{
private final ExpressionParser parser = new SpelExpressionParser();
private final String IgnoreField = "ignoreversioncheck";
@SneakyThrows
@Before("execution(* cn.ibizlab.*.rest.*.update(..)) && @annotation(versionCheck)")
public void BeforeUpdate(JoinPoint point, VersionCheck versionCheck) {
Object[] args = point.getArgs();
Object id = args[0];
Object dto = args[1];
if(ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(dto)) {
return;
}
String versionField = versionCheck.versionfield();
if(StringUtils.isEmpty(versionField)) {
return;
}
versionCheck(versionCheck,point.getTarget(), dto, id);
}
@SneakyThrows
@Before("execution(* cn.ibizlab.*.rest.*.updateBy*(..)) && @annotation(versionCheck)")
public void BeforeUpdateBy(JoinPoint point, VersionCheck versionCheck) {
Object[] args = point.getArgs();
if(args.length>=2) {
Object id = args[args.length-2];
Object dto = args[args.length-1];
if(ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(dto)) {
return;
}
String versionField = versionCheck.versionfield();
if(StringUtils.isEmpty(versionField)) {
return;
}
versionCheck(versionCheck, point.getTarget(), dto, id);
}
}
private void versionCheck(VersionCheck versionCheck, Object resource, Object dto, Object id) {
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("dto", dto);
//忽略版本检查
Expression dtoParamsExp = parser.parseExpression("#dto.extensionparams");
Map dtoParam = dtoParamsExp.getValue(context, Map.class);
if(!ObjectUtils.isEmpty(dtoParam) && !ObjectUtils.isEmpty(dtoParam.get(IgnoreField)) && dtoParam.get(IgnoreField).equals(1)) {
return;
}
Expression newExp = parser.parseExpression(String.format("#dto.%s", versionCheck.versionfield()));
Object newVersion = newExp.getValue(context);
if(ObjectUtils.isEmpty(newVersion)) {
return;
}
//进行版本检查
Object oldVersion = getDBVersion(versionCheck,getService(resource, versionCheck.entity()), id);
if(!ObjectUtils.isEmpty(oldVersion)) {
if(RuleUtils.gt(newVersion, oldVersion)) {
throw new BadRequestAlertException("数据已变更,可能后台数据已被修改,请重新加载数据", "VersionCheckAspect", "versionCheck");
}
}
}
/**
* 获取实体服务对象
* @param resource
* @param entity
* @return
*/
@SneakyThrows
private Object getService(Object resource, String entity) {
Object service = null;
Field[] fields = resource.getClass().getDeclaredFields();
for(Field field : fields) {
if(field.getModifiers()==1 && field.getName().equalsIgnoreCase(String.format("%sService",entity))) {
service = field.get(resource);
break;
}
}
return service;
}
/**
* 获取数据库版本
* @param versionCheck
* @param service
* @param id
* @return
*/
@SneakyThrows
private Object getDBVersion(VersionCheck versionCheck, Object service, Object id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timestamp dbVersion = null;
String versionField = versionCheck.versionfield();
if(!ObjectUtils.isEmpty(service)) {
EvaluationContext oldContext = new StandardEvaluationContext();
oldContext.setVariable("service", service);
oldContext.setVariable("id", id);
Expression oldExp = parser.parseExpression("#service.get(#id)");
EntityBase oldEntity = oldExp.getValue(oldContext, EntityBase.class);
Object oldDate = oldEntity.get(versionField);
if(oldDate!=null && oldDate instanceof Timestamp) {
Timestamp db_time = (Timestamp) oldDate;
Date db_date = sdf.parse(sdf.format(db_time));
dbVersion = new Timestamp(db_date.getTime());
}
}
return dbVersion;
}
}
package cn.ibizlab.util.cache;
import com.github.benmanes.caffeine.cache.CaffeineSpec;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.util.StringUtils;
import cn.ibizlab.util.cache.cacheManager.CaffeineCacheManager;
/**
* Caffeine缓存配置类
*/
@EnableCaching
@Configuration
@EnableConfigurationProperties(CacheProperties.class)
@ConditionalOnExpression("'${ibiz.cacheLevel:None}'.equals('L1')")
public class CaffeineCacheConfig {
/**
* Caffeine配置:设置过期时间
* @return
*/
@Bean
@Primary
public CacheManager cacheManager(CacheProperties cacheProperties) {
CaffeineCacheManager caffeineCacheManager=new CaffeineCacheManager();
String strCacheConfig = cacheProperties.getCaffeine().getSpec();
if (StringUtils.hasText(strCacheConfig)) {
caffeineCacheManager.setCaffeineCacheConfig(CaffeineSpec.parse(strCacheConfig));
}
return caffeineCacheManager;
}
}
\ No newline at end of file
package cn.ibizlab.util.cache;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.benmanes.caffeine.cache.CaffeineSpec;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;
import java.time.Duration;
import cn.ibizlab.util.cache.cacheManager.LayeringCacheManager;
import cn.ibizlab.util.cache.listener.RedisMessageListener;
import cn.ibizlab.util.cache.redis.CustomJacksonSerializer;
import cn.ibizlab.util.enums.RedisChannelTopic;
/**
* 缓存配置类
* 1级缓存为caffeine
* 2级缓存为redis
*/
@EnableCaching
@Configuration
@EnableConfigurationProperties(CacheProperties.class)
@ConditionalOnExpression("'${ibiz.cacheLevel:None}'.equals('L2')")
public class RedisCacheConfig {
@Value("${spring.cache.redis.time-to-live:3600}")
private long timeToLive;
/**
* 分层缓存管理器
* @param redisConnectionFactory
* @param cacheProperties
* @return
*/
@Bean
@Primary
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory ,CacheProperties cacheProperties){
LayeringCacheManager layeringCacheManager=new LayeringCacheManager(redisCacheWriter(redisConnectionFactory),redisCacheConfiguration(),redisTemplate(redisConnectionFactory));
String strCacheConfig = cacheProperties.getCaffeine().getSpec();
if (StringUtils.hasText(strCacheConfig)) {
layeringCacheManager.setCaffeineCacheConfig(CaffeineSpec.parse(strCacheConfig));
}
return layeringCacheManager;
}
/**
* redis配置:设置过期时间及序列化方式
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
CustomJacksonSerializer jackson2JsonRedisSerializer = new CustomJacksonSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(timeToLive))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
return configuration;
}
/**
* 创建redis缓存
* @param connectionFactory
* @return
*/
@Bean
public RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory){
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
return redisCacheWriter;
}
/**
* 发送redis广播
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
CustomJacksonSerializer jacksonSerial = new CustomJacksonSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jacksonSerial.setObjectMapper(om);
template.setValueSerializer(jacksonSerial);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSerial);
template.afterPropertiesSet();
return template;
}
/**
* 监听redis指定频道
* @param redisConnectionFactory
* @param cacheManager
* @param redisTemplate
* @return
*/
@Bean
RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory, CacheManager cacheManager , RedisTemplate redisTemplate) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
MessageListenerAdapter messageListener=new RedisMessageListener(cacheManager,redisTemplate);
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_DELETE_TOPIC.getChannelTopic());
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_CLEAR_TOPIC.getChannelTopic());
container.addMessageListener(messageListener, RedisChannelTopic.REDIS_CACHE_DYNAMICMODEL_TOPIC.getChannelTopic());
return container;
}
}
\ No newline at end of file
package cn.ibizlab.util.cache.cache;
import cn.ibizlab.util.helper.Globs;
import org.springframework.cache.caffeine.CaffeineCache;
import com.github.benmanes.caffeine.cache.Cache;
import javax.validation.constraints.NotNull;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 自定义的Caffeine缓存
*/
public class CusCaffeineCache extends CaffeineCache{
public CusCaffeineCache(String name, Cache<Object, Object> cache) {
super(name,cache);
}
public CusCaffeineCache(String name, Cache<Object, Object> cache, boolean allowNullValues) {
super(name,cache,allowNullValues);
}
@Override
public void evict(@NotNull Object key) {
if (key instanceof String && ((String) key).startsWith("glob:")) {
String globPattern = ((String)key).split("glob:")[1];
// 将Glob匹配转换成正则匹配
String regexPattern = Globs.toUnixRegexPattern(globPattern);
// String regexPattern = Globs.toWindowsRegexPattern(globPattern);
Cache<Object,Object> cache = super.getNativeCache();
Set<Object> keySet = cache.asMap().keySet();
keySet = keySet.stream().filter(o->o.toString().matches(regexPattern)).collect(Collectors.toSet());
cache.invalidateAll(keySet);
}else{
super.evict(key);
}
}
}
package cn.ibizlab.util.cache.cache;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import javax.validation.constraints.NotNull;
/**
* 自定义的redis缓存
*/
public class CusRedisCache extends RedisCache {
public CusRedisCache(String name, RedisCacheWriter redisCacheWriter, RedisCacheConfiguration configuration) {
super(name, redisCacheWriter, configuration);
}
@Override
public void evict(@NotNull Object key) {
if (key instanceof String && ((String) key).startsWith("glob:")) {
String globPattern = ((String)key).split("glob:")[1];
byte[] globPatternBytes = super.getCacheConfiguration().getConversionService().convert(globPattern,byte[].class);
if(globPatternBytes!=null){
super.getNativeCache().clean(super.getName(),globPatternBytes);
}
}else{
super.evict(key);
}
}
}
package cn.ibizlab.util.cache.cache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.AbstractValueAdaptingCache;
import org.springframework.cache.support.NullValue;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.core.RedisOperations;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import cn.ibizlab.util.cache.listener.RedisPublisher;
import cn.ibizlab.util.enums.RedisChannelTopic;
import org.springframework.util.ObjectUtils;
/**
* 缓存分层类
* 1级缓存为caffeine
* 2级缓存为redis
*/
@Slf4j
public class LayeringCache extends AbstractValueAdaptingCache {
/**
* 缓存的名称
*/
private String cacheName;
/**
* Caffeine缓存
*/
private CaffeineCache caffeineCache;
/**
* redis缓存
*/
private RedisCache redisCache;
/**
* redis消息发布
*/
RedisOperations<? extends Object, ? extends Object> redisOperations;
public LayeringCache(String cacheName , CaffeineCache caffeineCache, RedisCache redisCache, RedisOperations redisOperations) {
super(true);
this.cacheName = cacheName;
this.caffeineCache = caffeineCache;
this.redisCache = redisCache;
this.redisOperations=redisOperations;
}
@Override
public String getName() {
return this.cacheName;
}
@Override
public Object getNativeCache() {
return this;
}
@Override
public ValueWrapper get(Object key) {
ValueWrapper wrapper = caffeineCache.get(key);
Object value = ObjectUtils.isEmpty(wrapper) ? null : wrapper.get();
log.debug("查询一级缓存 key:{} ", key, value);
if (ObjectUtils.isEmpty(value)) {
wrapper = redisCache.get(key);
value = ObjectUtils.isEmpty(wrapper) ? null : wrapper.get();
log.debug("查询二级缓存 key:{} ", key);
if (!ObjectUtils.isEmpty(value)) {
caffeineCache.put(key, value);
log.debug("查询二级缓存,并将数据放到一级缓存。 key:{} ", key);
}
}
return wrapper;
}
@Override
public <T> T get(Object key, Class<T> type) {
T value = caffeineCache.get(key, type);
log.debug("查询一级缓存 key:{}", key);
if (value == null) {
value = redisCache.get(key, type);
caffeineCache.put(key, value);
log.debug("查询二级缓存,并将数据放到一级缓存。 key:{}", key);
}
return value;
}
@SuppressWarnings("unchecked")
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
T value = (T) caffeineCache.getNativeCache().get(key, k -> getSecondCacheValue(k, valueLoader));
if(value==null) {
value = (T) getSecondCacheValue(key, valueLoader);
}
if (value instanceof NullValue) {
return null;
}
return value;
}
@Override
public void put(Object key, Object value) {
if(value!=null) {
caffeineCache.put(key, value);
redisCache.put(key, value);
}
}
@Override
public ValueWrapper putIfAbsent(Object key, Object value) {
caffeineCache.putIfAbsent(key, value);
return redisCache.putIfAbsent(key, value);
}
@Override
public void evict(Object key) {
redisCache.evict(key); //清除redis中的二级缓存
caffeineCache.evict(key);//清除本机一级缓存
Map<String, Object> message = new HashMap<>();
message.put("cacheName", cacheName);
message.put("key", key);
RedisPublisher redisPublisher = new RedisPublisher(redisOperations, RedisChannelTopic.REDIS_CACHE_DELETE_TOPIC.getChannelTopic());// 创建redis发布者
redisPublisher.publisher(message);//发布消息,清除其它集群机器中的一级缓存
log.debug(String.format("清除二级缓存数据[%s]", key));
}
@Override
public void clear() {
redisCache.clear(); //清除redis中的二级缓存
caffeineCache.clear();//清除本机一级缓存
Map<String, Object> message = new HashMap<>();
message.put("cacheName", cacheName);
RedisPublisher redisPublisher = new RedisPublisher(redisOperations, RedisChannelTopic.REDIS_CACHE_CLEAR_TOPIC.getChannelTopic());// 创建redis发布者
redisPublisher.publisher(message);//发布消息,清除其它集群机器中的一级缓存
}
@Override
protected Object lookup(Object key) {
Object value = caffeineCache.get(key);
log.debug("查询一级缓存 key:{}", key);
if (value == null) {
value = redisCache.get(key);
log.debug("查询二级缓存 key:{}", key);
}
return value;
}
/**
* 获取caffeine缓存
* @return
*/
public CaffeineCache getFirstCache() {
return this.caffeineCache;
}
/**
* 获取redis缓存
* @return
*/
public RedisCache getSecondCache() {
return this.redisCache;
}
/**
* 查询二级缓存
* @param key
* @param valueLoader
* @return
*/
private <T> Object getSecondCacheValue(Object key, Callable<T> valueLoader) {
T value = redisCache.get(key, valueLoader);
log.debug("查询二级缓存 key:{}", key);
return toStoreValue(value);
}
}
package cn.ibizlab.util.cache.cacheManager;
import lombok.Data;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.CaffeineSpec;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.util.ObjectUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/**
* Caffeine本地缓存
*/
@Data
public class CaffeineCacheManager implements CacheManager {
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16);
private static final int default_expire_after_write = 1;
private static final int default_initial_capacity = 5;
private static final int default_maximum_size = 1_000;
private Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder()
.expireAfterAccess(default_expire_after_write, TimeUnit.HOURS)
.initialCapacity(default_initial_capacity)
.maximumSize(default_maximum_size);
/**
* 获取缓存对象
* @param cacheName
* @return
*/
@Override
public Cache getCache(String cacheName) {
Cache cache = this.cacheMap.get(cacheName);
if (cache == null) {
synchronized (this.cacheMap) {
cache = this.cacheMap.get(cacheName);
if (cache == null) {
cache = createCache(cacheName);
this.cacheMap.put(cacheName, cache);
}
}
}
return cache;
}
/**
* 创建缓存
* @param cacheName
* @return
*/
protected Cache createCache(String cacheName) {
return new CaffeineCache(cacheName, this.cacheBuilder.build(), true);
}
/**
* 获取缓存名
* @return
*/
@Override
public Collection<String> getCacheNames() {
return Collections.unmodifiableSet(this.cacheMap.keySet());
}
/**
* 缓存配置[缓存容量大小、时长等]
* @param caffeineCacheConfig
*/
public void setCaffeineCacheConfig(CaffeineSpec caffeineCacheConfig) {
Caffeine<Object, Object> cacheBuilder = Caffeine.from(caffeineCacheConfig);
if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
this.cacheBuilder = cacheBuilder;
}
}
}
package cn.ibizlab.util.cache.cacheManager;
import lombok.Data;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.CaffeineSpec;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.ObjectUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import cn.ibizlab.util.cache.cache.CusCaffeineCache;
import cn.ibizlab.util.cache.cache.CusRedisCache;
import cn.ibizlab.util.cache.cache.LayeringCache;
/**
* 缓存分层
* 1级缓存为caffeine
* 2级缓存为redis
*/
@Data
public class LayeringCacheManager implements CacheManager {
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>(16);
private static final int default_expire_after_write = 1;
private static final int default_initial_capacity = 5;
private static final int default_maximum_size = 1_000;
private Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder()
.expireAfterAccess(default_expire_after_write, TimeUnit.HOURS)
.initialCapacity(default_initial_capacity)
.maximumSize(default_maximum_size);
private RedisCacheWriter redisCacheWriter;
private RedisCacheConfiguration redisConfiguration;
private RedisTemplate<String, Object> redisTemplate;
public LayeringCacheManager(RedisCacheWriter redisCacheWriter , RedisCacheConfiguration redisConfiguration , RedisTemplate<String, Object> redisTemplate ){
this.redisCacheWriter=redisCacheWriter;
this.redisConfiguration=redisConfiguration;
this.redisTemplate= redisTemplate;
}
/**
* 获取缓存对象
* @param cacheName
* @return
*/
@Override
public Cache getCache(String cacheName) {
Cache cache = this.cacheMap.get(cacheName);
if (cache == null) {
synchronized (this.cacheMap) {
cache = this.cacheMap.get(cacheName);
if (cache == null) {
cache = createCache(cacheName);
this.cacheMap.put(cacheName, cache);
}
}
}
return cache;
}
/**
* 获取集合中的缓存
* @return
*/
@Override
public Collection<String> getCacheNames() {
return Collections.unmodifiableSet(this.cacheMap.keySet());
}
/**
* 创建缓存
* @param cacheName
* @return
*/
protected Cache createCache(String cacheName) {
return new LayeringCache(cacheName,new CusCaffeineCache(cacheName, this.cacheBuilder.build(), true),new CusRedisCache(cacheName, redisCacheWriter, redisConfiguration),redisTemplate);
}
/**
* 缓存配置[缓存容量大小、时长等]
* @param caffeineCacheConfig
*/
public void setCaffeineCacheConfig(CaffeineSpec caffeineCacheConfig) {
Caffeine<Object, Object> cacheBuilder = Caffeine.from(caffeineCacheConfig);
if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
this.cacheBuilder = cacheBuilder;
}
}
}
package cn.ibizlab.util.cache.listener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.StringUtils;
import org.springframework.util.ObjectUtils;
import java.util.Map;
import cn.ibizlab.util.cache.cache.LayeringCache;
import cn.ibizlab.util.enums.RedisChannelTopic;
/**
* redis消息的订阅者
*/
@Slf4j
public class RedisMessageListener extends MessageListenerAdapter {
private CacheManager cacheManager;
private RedisTemplate redisTemplate;
public RedisMessageListener(CacheManager cacheManager, RedisTemplate redisTemplate){
this.cacheManager=cacheManager;
this.redisTemplate=redisTemplate;
}
@Override
public void onMessage(Message message, byte[] pattern) {
RedisChannelTopic channelTopic = RedisChannelTopic.getChannelTopicEnum(new String(message.getChannel()));
Map<String, Object> map = null;
RedisSerializer serializer=redisTemplate.getValueSerializer();
Object result=serializer.deserialize(message.getBody());
if(result instanceof Map){
map= (Map<String, Object>) result;
}
if(StringUtils.isEmpty(map)|| (!map.containsKey("cacheName"))){
log.debug("解析缓存数据失败,无法获取指定值!");
return ;
}
log.debug("redis消息订阅者接收到频道【{}】发布的消息。消息内容:{}", channelTopic.getChannelTopicStr(), result.toString());
String cacheName = (String) map.get("cacheName");
Cache cache = cacheManager.getCache(cacheName);// 根据缓存名称获取多级缓存
if (cache != null && cache instanceof LayeringCache) { // 判断缓存是否是多级缓存
switch (channelTopic) {
case REDIS_CACHE_DELETE_TOPIC: // 获取一级缓存,并删除一级缓存数据
Object cacheKey = map.get("key");
if(!ObjectUtils.isEmpty(cacheKey)){
((LayeringCache) cache).getFirstCache().evict(cacheKey);
((LayeringCache) cache).getSecondCache().evict(cacheKey);
log.debug("同步删除缓存{}数据,key:{},", cacheName, cacheKey.toString());
}
else{
log.debug("同步删除缓存失败,{}缓存键值为空!",cacheName);
}
break;
case REDIS_CACHE_CLEAR_TOPIC:// 获取一级缓存,并删除一级缓存数据
((LayeringCache) cache).getFirstCache().clear();
((LayeringCache) cache).getSecondCache().clear();
log.debug("同步清除缓存{}数据", cacheName);
break;
default:
log.debug("接收到没有定义的订阅消息频道数据");
break;
}
}
}
}
package cn.ibizlab.util.cache.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.listener.ChannelTopic;
/**
* redis消息的发布者
*/
public class RedisPublisher {
private static final Logger logger = LoggerFactory.getLogger(RedisPublisher.class);
RedisOperations<? extends Object, ? extends Object> redisOperations;
/**
* 频道名称
*/
ChannelTopic channelTopic;
/**
* @param redisOperations Redis客户端
* @param channelTopic 频道名称
*/
public RedisPublisher(RedisOperations<? extends Object, ? extends Object> redisOperations, ChannelTopic channelTopic) {
this.channelTopic = channelTopic;
this.redisOperations = redisOperations;
}
/**
* 发布消息到频道(Channel)
*
* @param message 消息内容
*/
public void publisher(Object message) {
redisOperations.convertAndSend(channelTopic.toString(), message);
logger.debug("redis消息发布者向频道【{}】发布了【{}】消息", channelTopic.toString(), message.toString());
}
}
package cn.ibizlab.util.cache.redis;
import cn.ibizlab.util.security.AuthenticationUser;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomJacksonSerializer<T> extends Jackson2JsonRedisSerializer<T> {
public static final String DEFAULT_PACKAGE ="[\\w+\\.]+\\.AuthenticationUser";
public static final String CLASSNAME_EX="_$$_";
public static final String CLASSNAME_EX_PATTEN="(_\\$\\$_)(\\w+)";
public static final String USER_PACKAGE= AuthenticationUser.class.getName();
public CustomJacksonSerializer(Class type) {
super(type);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
String serializerContent = new String(bytes, DEFAULT_CHARSET);
Matcher matcher = Pattern.compile(DEFAULT_PACKAGE).matcher(serializerContent);
if(matcher.find()){
serializerContent=serializerContent.replaceAll(DEFAULT_PACKAGE,USER_PACKAGE);
}
if(serializerContent.contains(CLASSNAME_EX)){
serializerContent=serializerContent.replaceAll(CLASSNAME_EX_PATTEN,"");
}
return super.deserialize(serializerContent.getBytes());
}
}
package cn.ibizlab.util.client;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public class IBZLiteFallback implements IBZLiteFeignClient {
@Override
public Boolean syncSysModel(JSONObject system) {
return null;
}
}
package cn.ibizlab.util.client;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@FeignClient(value = "${ibiz.ref.service.lite:ibzlite-api}",contextId = "lite",fallback = IBZLiteFallback.class)
public interface IBZLiteFeignClient
{
/**
* 同步系统资模型到lite
* @param system 系统模型信息
* @return
*/
@PostMapping("/lite/syncsysmodel")
Boolean syncSysModel(@RequestBody JSONObject system);
}
package cn.ibizlab.util.client;
import cn.ibizlab.util.domain.MsgBody;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
@Component
public class IBZNotifyFallback implements IBZNotifyFeignClient {
@Override
public Boolean sendMsg(MsgBody msg) {
return null;
}
@Override
public Boolean createMsgTemplate(JSONObject template) {
return null;
}
@Override
public Boolean sendDingTalkLinkMsg(MsgBody msg) {
return null;
}
@Override
public String createDingTalkWorkRecord(MsgBody msg) {
return null;
}
@Override
public Boolean finishDingTalkWorkRecord(String msgId) {
return null;
}
}
package cn.ibizlab.util.client;
import cn.ibizlab.util.domain.MsgBody;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(value = "${ibiz.ref.service.notify:ibznotify-api}",contextId = "notify",fallback = IBZNotifyFallback.class)
public interface IBZNotifyFeignClient
{
@RequestMapping(method = RequestMethod.POST,value = "/notify/sendmsg")
Boolean sendMsg(@RequestBody MsgBody msg);
@RequestMapping(method = RequestMethod.POST,value = "/notify/createmsgtempl")
Boolean createMsgTemplate(@RequestBody JSONObject template);
@RequestMapping(method = RequestMethod.POST,value = "/notify/dingtalk/sendlinkmsg")
Boolean sendDingTalkLinkMsg(@RequestBody MsgBody msg);
@RequestMapping(method = RequestMethod.POST,value = "/notify/dingtalk/createworkrecord")
String createDingTalkWorkRecord(@RequestBody MsgBody msg);
@RequestMapping(method = RequestMethod.POST,value = "/notify/dingtalk/finishworkrecord/{msgid}")
Boolean finishDingTalkWorkRecord(@PathVariable("msgid") String msgId);
}
package cn.ibizlab.util.client;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.Set;
@Component
public class IBZOUFallback implements IBZOUFeignClient {
@Override
public Map<String, Set<String>> getOUMapsByUserId(String userId) {
return null;
}
}
package cn.ibizlab.util.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.Map;
import java.util.Set;
@FeignClient(value = "${ibiz.ref.service.ou:ibzou-api}",contextId = "ou",fallback = IBZOUFallback.class)
public interface IBZOUFeignClient
{
/**
* 从ou中获取当前上下级组织、部门信息
* @param userId
* @return
*/
@GetMapping("/sysemployees/{userId}/oumaps")
Map<String, Set<String>> getOUMapsByUserId(@PathVariable("userId") String userId);
}
package cn.ibizlab.util.client;
import cn.ibizlab.util.domain.PayTrade;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
@Component
public class IBZPayFallback implements IBZPayFeignClient {
@Override
public JSONObject preCreate(PayTrade trade) {
return null;
}
@Override
public JSONObject query(PayTrade trade) {
return null;
}
@Override
public JSONObject cancel(PayTrade trade) {
return null;
}
@Override
public String pagePay(PayTrade trade) {
return null;
}
}
package cn.ibizlab.util.client;
import cn.ibizlab.util.domain.PayTrade;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(value = "${ibiz.ref.service.pay:ibzpay-api}",contextId = "pay",fallback = IBZPayFallback.class)
public interface IBZPayFeignClient
{
@RequestMapping(method = RequestMethod.POST,value = "/pay/trade/precreate")
JSONObject preCreate(@RequestBody PayTrade trade);
@RequestMapping(method = RequestMethod.POST,value = "/pay/trade/query")
JSONObject query(@RequestBody PayTrade trade);
@RequestMapping(method = RequestMethod.POST,value = "/pay/trade/cancel")
JSONObject cancel(@RequestBody PayTrade trade);
@RequestMapping(method = RequestMethod.POST,value = "/pay/trade/pagepay")
String pagePay(@RequestBody PayTrade trade);
}
package cn.ibizlab.util.client;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.security.AuthorizationLogin;
import org.springframework.util.MultiValueMap;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
@Component
public class IBZUAAFallback implements IBZUAAFeignClient {
@Override
public Boolean syncSysAuthority(JSONObject system) {
return null;
}
@Override
public AuthenticationUser login(AuthorizationLogin authorizationLogin) {
return null;
}
@Override
public AuthenticationUser loginByUsername(String username) {
return null;
}
@Override
public String getPublicKey() {
return null;
}
}
package cn.ibizlab.util.client;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.security.AuthorizationLogin;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.MultiValueMap;
import com.alibaba.fastjson.JSONObject;
@FeignClient(value = "${ibiz.ref.service.uaa:ibzuaa-api}",contextId = "uaa",fallback = IBZUAAFallback.class)
public interface IBZUAAFeignClient
{
/**
* 同步系统资源到uaa
* @param system 系统资源信息
* @return
*/
@PostMapping("/syspssystems/save")
Boolean syncSysAuthority(@RequestBody JSONObject system);
/**
* 用户登录
* @param authorizationLogin 登录信息
* @return
*/
@PostMapping(value = "/uaa/login")
AuthenticationUser login(@RequestBody AuthorizationLogin authorizationLogin);
@PostMapping(value = "/uaa/loginbyusername")
AuthenticationUser loginByUsername(@RequestBody String username);
@Cacheable(value="ibzuaa_publickey")
@GetMapping(value = "/uaa/publickey")
String getPublicKey();
}
package cn.ibizlab.util.client;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import java.util.*;
import java.io.Serializable;
@Component
public class IBZWFFallback implements IBZWFFeignClient {
@Override
public List<String> getbusinesskeys(String system, String appname, String entity, String processDefinitionKey, String taskDefinitionKey) {
return null;
}
@Override
public List<String> getbusinesskeysByUserId(String system, String userId, String entity, String processDefinitionKey, String taskDefinitionKey) {
return null;
}
@Override
public Boolean deployBpmnFile(List<Map<String, Object>> bpmnfiles) {
return null;
}
@Override
public JSONObject wfstart(String system, String appname, String entity, String businessKey, JSONObject instance) {
return null;
}
@Override
public Map<String, Map<String, Object>> getTask(String system, String userId, String entity, String instTag, String instTag2 ,String taskType) {
return null;
}
@Override
public Map<String, Map<String, Object>> getTaskByStep(String system, String userId, String entity, String instTag, String instTag2 , String taskType, String srfwfstep) {
return null;
}
@Override
public Integer getDataAccessMode(String system, String entity, Serializable businessKey) {
return null;
}
@Override
public Map<String, Map<String, Object>> getMyTask(String system, String appName, String entity) {
return null;
}
}
package cn.ibizlab.util.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import com.alibaba.fastjson.JSONObject;
import java.util.*;
import java.io.Serializable;
@FeignClient(value = "${ibiz.ref.service.wf:ibzwf-api}",contextId = "wf",fallback = IBZWFFallback.class)
public interface IBZWFFeignClient
{
@RequestMapping(method = RequestMethod.GET, value = "/{system}-app-{appname}/{entity}/process-definitions/{processDefinitionKey}/usertasks/{taskDefinitionKey}/tasks")
List<String> getbusinesskeys(@PathVariable("system") String system, @PathVariable("appname") String appname,
@PathVariable("entity") String entity, @PathVariable("processDefinitionKey") String processDefinitionKey, @PathVariable("taskDefinitionKey") String taskDefinitionKey);
@RequestMapping(method = RequestMethod.POST, value = "/{system}-user-{userId}/{entity}/process-definitions/{processDefinitionKey}/usertasks/{taskDefinitionKey}/tasks")
List<String> getbusinesskeysByUserId(@PathVariable("system") String system,@PathVariable("userId") String userId,
@PathVariable("entity") String entity,@PathVariable("processDefinitionKey") String processDefinitionKey,@PathVariable("taskDefinitionKey") String taskDefinitionKey);
@RequestMapping(method = RequestMethod.POST, value = "/deploybpmn")
Boolean deployBpmnFile(@RequestBody List<Map<String,Object>> bpmnfiles);
@RequestMapping(method = RequestMethod.POST, value = "/{system}-app-{appname}/{entity}/{businessKey}/process-instances")
JSONObject wfstart(@PathVariable("system") String system, @PathVariable("appname") String appname,
@PathVariable("entity") String entity,
@PathVariable("businessKey") String businessKey, @RequestBody JSONObject instance);
@RequestMapping(method = RequestMethod.POST, value = "/{system}-user-{userId}/{insttag}/{insttag2}/{entity}/tasks")
Map<String, Map<String, Object>> getTask(@PathVariable("system") String system, @PathVariable("userId") String userId,
@PathVariable("entity") String entity, @PathVariable("insttag") String instTag, @PathVariable("insttag2") String instTag2, @RequestParam("srfwf") String taskType);
@RequestMapping(method = RequestMethod.POST, value = "/{system}-user-{userId}/{insttag}/{insttag2}/{entity}/tasks")
Map<String, Map<String, Object>> getTaskByStep(@PathVariable("system") String system, @PathVariable("userId") String userId,
@PathVariable("entity") String entity, @PathVariable("insttag") String instTag, @PathVariable("insttag2") String instTag2 , @RequestParam("srfwf") String taskType, @RequestParam("n_taskdefinitionkey_eq") String srfwfstep);
@RequestMapping(method = RequestMethod.GET, value = "/{system}/{entity}/{businessKey}/dataaccessmode")
Integer getDataAccessMode(@PathVariable("system") String system, @PathVariable("entity") String entity, @PathVariable("businessKey") Serializable businessKey);
@RequestMapping(method = RequestMethod.GET, value = "/{system}-app-{appname}/{entity}/mytasks")
Map<String,Map<String,Object>> getMyTask(@PathVariable("system") String system,@PathVariable("appname") String appName,
@PathVariable("entity") String entity);
}
此差异已折叠。
package cn.ibizlab.util.domain;
import lombok.Data;
import org.flowable.bpmn.model.Process;
import org.springframework.core.io.Resource;
import org.kie.api.runtime.KieContainer;
import java.io.File;
import java.io.Serializable;
import java.util.List;
@Data
public class DELogic implements Serializable {
String id;
String name;
Process process;
KieContainer container;
List<DELogic> refLogic;
List<Resource> refRuleFiles;
String md5;
int logicMode;
long loadedTime;
}
package cn.ibizlab.util.domain;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import cn.ibizlab.util.helper.DEFieldCacheMap;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.data.annotation.Transient;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Data
public class DTOBase implements Serializable {
@JsonIgnore
@JSONField(serialize = false)
private Set<String> focusNull;
public void modify(String field,Object val) {
if(val==null) {
this.getFocusNull(true).add(field.toLowerCase());
}
else {
this.getFocusNull(true).remove(field.toLowerCase());
}
}
public Set<String> getFocusNull() {
if(focusNull==null) {
focusNull=new HashSet<>();
}
if(focusNull.size()>0 && extensionparams.containsKey("dirtyflagenable"))
{
Set<String> nocheck=new HashSet<>();
for(String key:focusNull)
{
if(!extensionparams.containsKey(key+"dirtyflag")) {
nocheck.add(key);
}
}
for(String key:nocheck) {
focusNull.remove(key);
}
}
return focusNull;
}
private Set<String> getFocusNull(boolean newflag) {
if(focusNull==null) {
focusNull=new HashSet<>();
}
return focusNull;
}
@JsonIgnore
private Map<String,Object> extensionparams=new HashMap<String,Object>();
public Map<String, Object> getExtensionparams() {
return extensionparams;
}
public void setExtensionparams(Map<String, Object> extensionparams) {
this.extensionparams = extensionparams;
}
@JsonAnyGetter
public Map<String , Object> any() {
return extensionparams;
}
@JsonIgnore
@JSONField(serialize = false)
@Transient
private BeanMap map;
private BeanMap getMap()
{
if(map==null) {
map=BeanMap.create(this);
}
return map;
}
public Object get(String field) {
String fieldRealName= DEFieldCacheMap.getFieldRealName(this.getClass(),field);
if(!StringUtils.isEmpty(fieldRealName)) {
return getMap().get(fieldRealName);
}
else {
return this.extensionparams.get(field.toLowerCase());
}
}
@JsonAnySetter
public void set(String field, Object value) {
field=field.toLowerCase();
String fieldRealName=DEFieldCacheMap.getFieldRealName(this.getClass(),field);
if(!StringUtils.isEmpty(fieldRealName)) {
if (value == null) {
getMap().put(fieldRealName, null);
}
else {
getMap().put(fieldRealName, DEFieldCacheMap.fieldValueOf(this.getClass(), fieldRealName, value));
}
}
else {
this.extensionparams.put(field.toLowerCase(),value);
}
}
}
package cn.ibizlab.util.domain;
public class DTOClient extends DTOBase {
@Override
public void modify(String field,Object val) {
getExtensionparams().put("dirtyflagenable",true);
if(val==null){
this.getFocusNull().add(field.toLowerCase());
getExtensionparams().put(field.toLowerCase()+"dirtyflag",true);
}
else{
this.getFocusNull().remove(field.toLowerCase());
getExtensionparams().remove(field.toLowerCase()+"dirtyflag");
}
}
}
package cn.ibizlab.util.domain;
import cn.ibizlab.util.helper.DEFieldCacheMap;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.data.annotation.Transient;
import org.springframework.util.AlternativeJdkIdGenerator;
import org.springframework.util.ObjectUtils;
import java.io.Serializable;
import java.lang.reflect.Field;
import org.springframework.util.StringUtils;
import java.util.*;
public class EntityBase implements Serializable {
@JsonIgnore
@JSONField(serialize = false)
@TableField(exist = false)
@Transient
private Set<String> focusNull;
public Set<String> getFocusNull() {
if(focusNull==null) {
focusNull=new HashSet<>();
}
return focusNull;
}
public void setFocusNull(Set<String> focusNull) {
this.focusNull = focusNull;
}
public void modify(String field,Object val) {
}
public Serializable getDefaultKey(boolean gen) {
String Id=(new AlternativeJdkIdGenerator()).generateId().toString();
return gen?Id.replace("-", ""):Id;
}
@JsonIgnore
@JSONField(serialize = false)
@TableField(exist = false)
@Transient
private BeanMap map;
private BeanMap getMap()
{
if(map==null) {
map=BeanMap.create(this);
}
return map;
}
@JsonIgnore
@TableField(exist = false)
@Transient
private Map<String,Object> extensionparams=new HashMap<String,Object>();
public Map<String, Object> getExtensionparams() {
return extensionparams;
}
public void setExtensionparams(Map<String, Object> extensionparams) {
this.extensionparams = extensionparams;
}
public Object get(String field) {
String fieldRealName=DEFieldCacheMap.getFieldRealName(this.getClass(),field);
if(!StringUtils.isEmpty(fieldRealName)) {
return getMap().get(fieldRealName);
}
else {
return this.extensionparams.get(field.toLowerCase());
}
}
@JsonAnyGetter
public Map<String , Object> any() {
return extensionparams;
}
@JsonAnySetter
public void set(String field, Object value) {
field=field.toLowerCase();
String fieldRealName=DEFieldCacheMap.getFieldRealName(this.getClass(),field);
if(!StringUtils.isEmpty(fieldRealName)) {
if (value == null) {
getMap().put(fieldRealName, null);
}
else {
getMap().put(fieldRealName, DEFieldCacheMap.fieldValueOf(this.getClass(), fieldRealName, value));
}
}
else {
this.extensionparams.put(field.toLowerCase(),value);
}
}
/**
* 复制当前对象数据到目标对象
* @param targetEntity 目标数据对象
* @param bIncEmpty 是否包括空值
* @param <T>
* @return
*/
public <T> T copyTo(T targetEntity, boolean bIncEmpty){
if(targetEntity instanceof EntityBase){
EntityBase target= (EntityBase) targetEntity;
Hashtable<String, Field> sourceFields=DEFieldCacheMap.getFieldMap(this.getClass());
for(String field : sourceFields.keySet()){
Object value=this.get(field);
if( !ObjectUtils.isEmpty(value) || ObjectUtils.isEmpty(value) && getFocusNull().contains(field) && bIncEmpty ){
target.set(field,value);
}
}
}
return targetEntity;
}
/**
* 重置当前数据对象属性值
* @param field
*/
public void reset(String field){
}
}
\ No newline at end of file
package cn.ibizlab.util.domain;
import org.springframework.util.StringUtils;
public class EntityClient extends EntityBase {
@Override
public void modify(String field,Object val) {
getExtensionparams().put("dirtyflagenable",true);
if(val==null){
this.getFocusNull().add(field.toLowerCase());
getExtensionparams().put(field.toLowerCase()+"dirtyflag",true);
}
else{
this.getFocusNull().remove(field.toLowerCase());
getExtensionparams().remove(field.toLowerCase()+"dirtyflag");
}
}
@Override
public void reset(String field) {
if(!StringUtils.isEmpty(field)){
String resetField=field.toLowerCase();
this.set(resetField,null);
this.getFocusNull().remove(resetField);
getExtensionparams().remove(resetField+"dirtyflag");
}
}
}
package cn.ibizlab.util.domain;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.util.StringUtils;
public class EntityMP extends EntityBase {
public UpdateWrapper getUpdateWrapper(boolean clean) {
UpdateWrapper wrapper=new UpdateWrapper();
for(String nullField:getFocusNull()) {
wrapper.set(nullField,null);
}
if(clean) {
getFocusNull().clear();
}
return wrapper;
}
@Override
public void modify(String field,Object val) {
if(val==null) {
this.getFocusNull().add(field.toLowerCase());
}
else {
this.getFocusNull().remove(field.toLowerCase());
}
}
@Override
public void reset(String field){
if(!StringUtils.isEmpty(field)){
String resetField=field.toLowerCase();
this.set(resetField,null);
getFocusNull().remove(resetField);
}
}
}
package cn.ibizlab.util.domain;
public class EntityMongo extends EntityBase {
}
package cn.ibizlab.util.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor
public class FileItem
{
private String id;
private String name;
private String fileid;
private String filename;
private long size;
private String ext;
}
package cn.ibizlab.util.domain;
import cn.ibizlab.util.helper.DataObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.sql.Timestamp;
@TableName(value = "IBZCFG")
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class IBZConfig {
/**
* 配置标识
* 系统+配置类型+引用对象+用户标识联合主键
*/
@TableId
private String cfgId;
/**
* 系统标识
*/
private String systemId;
/**
* 配置类型
* 门户配置/表格自定义配置/自定义查询...消费方自定义
*/
private String cfgType;
/**
* 引用对象
* 门户页标识/具体表格视图标识...消费方具体使用位置的标识
*/
private String targetType;
/**
* 用户标识
* 默认当前登录者
*/
private String userId;
/**
* 配置
* JSONObject
*/
private String cfg;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", locale = "zh" , timezone="GMT+8")
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Timestamp updateDate;
public String getCfgId()
{
if(StringUtils.isEmpty(cfgId)&&
(!(StringUtils.isEmpty(systemId)))&&
(!(StringUtils.isEmpty(cfgType)))&&
(!(StringUtils.isEmpty(targetType)))&&
(!(StringUtils.isEmpty(userId))))
{
cfgId= DigestUtils.md5DigestAsHex((systemId+"||"+cfgType+"||"+targetType+"||"+userId).getBytes());
}
return cfgId;
}
}
package cn.ibizlab.util.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Objects;
/**
* 实体[DataAudit] 数据对象
*/
@TableName(value = "IBZDATAAUDIT")
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class IBZDataAudit implements Serializable{
@TableId(value= "dataauditid",type=IdType.UUID)//指定主键生成策略
private String dataauditid;
private String dataauditname;
private String oppersonid;
private String oppersonname;
private String audittype;
private Timestamp optime;
private String ipaddress;
private String auditinfo;
private Object auditobjectdata;
private String auditobject;
private int isdatachanged;
}
\ No newline at end of file
package cn.ibizlab.util.domain;
import java.sql.Timestamp;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import javax.validation.constraints.Size;
import java.io.Serializable;
/**
* 实体[IBZUSER] 数据对象
*/
@TableName(value = "IBZUSER")
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class IBZUSER implements Serializable{
@Size(min = 0, max = 100, message = "[用户标识]长度必须在[100]以内!")
@TableId(value= "userid",type=IdType.INPUT)//指定主键生成策略
private String userid;
@Size(min = 0, max = 200, message = "[用户全局名]长度必须在[200]以内!")
private String username;
@Size(min = 0, max = 100, message = "[用户姓名]长度必须在[100]以内!")
private String personname;
@Size(min = 0, max = 100, message = "[用户代码]长度必须在[100]以内!")
private String usercode;
@Size(min = 0, max = 100, message = "[登录别名]长度必须在[100]以内!")
private String loginname;
@Size(min = 0, max = 100, message = "[登录密码]长度必须在[100]以内!")
private String password;
@Size(min = 0, max = 100, message = "[区属]长度必须在[100]以内!")
private String domains;
@Size(min = 0, max = 100, message = "[主部门id]长度必须在[100]以内!")
private String mdeptid;
@Size(min = 0, max = 100, message = "[主部门代码]长度必须在[100]以内!")
private String mdeptcode;
@Size(min = 0, max = 200, message = "[主部门名称]长度必须在[200]以内!")
private String mdeptname;
@Size(min = 0, max = 100, message = "[业务编码]长度必须在[100]以内!")
private String bcode;
@Size(min = 0, max = 100, message = "[岗位id]长度必须在[100]以内!")
private String postid;
@Size(min = 0, max = 100, message = "[岗位代码]长度必须在[100]以内!")
private String postcode;
@Size(min = 0, max = 200, message = "[岗位名称]长度必须在[200]以内!")
private String postname;
@Size(min = 0, max = 100, message = "[单位id]长度必须在[100]以内!")
private String orgid;
@Size(min = 0, max = 100, message = "[单位代码]长度必须在[100]以内!")
private String orgcode;
@Size(min = 0, max = 200, message = "[单位名称]长度必须在[200]以内!")
private String orgname;
@Size(min = 0, max = 36, message = "[昵称]长度必须在[36]以内!")
private String nickname;
@Size(min = 0, max = 100, message = "[邮箱]长度必须在[100]以内!")
private String email;
@Size(min = 0, max = 100, message = "[通信账号]长度必须在[100]以内!")
private String avatar;
@Size(min = 0, max = 100, message = "[联系电话]长度必须在[100]以内!")
private String phone;
@Size(min = 0, max = 100, message = "[保留字段]长度必须在[100]以内!")
private String reserver;
@Size(min = 0, max = 100, message = "[头像]长度必须在[100]以内!")
private String usericon;
@Size(min = 0, max = 10, message = "[性别]长度必须在[10]以内!")
private String sex;
private Timestamp birthday;
@Size(min = 0, max = 36, message = "[证件号码]长度必须在[36]以内!")
private String certcode;
@Size(min = 0, max = 200, message = "[地址]长度必须在[200]以内!")
private String addr;
@Size(min = 0, max = 100, message = "[主题]长度必须在[100]以内!")
private String theme;
@Size(min = 0, max = 100, message = "[语言]长度必须在[100]以内!")
private String lang;
@Size(min = 0, max = 10, message = "[字号]长度必须在[10]以内!")
private String fontsize;
@Size(min = 0, max = 500, message = "[备注]长度必须在[500]以内!")
private String memo;
private int superuser;
}
\ No newline at end of file
package cn.ibizlab.util.domain;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.master")
public class LiquibaseProp{
private String url;
private String username;
private String password;
private String isSyncDBSchema;
private String defaultSchema;
private String conf;
}
\ No newline at end of file
package cn.ibizlab.util.domain;
import java.util.List;
/**
* 实体转换器基类
* @param <D> domainDTO
* @param <E> domain
*/
public interface MappingBase<D, E> {
/**
* dto转domain
* @param dto
* @return
*/
E toDomain(D dto);
/**
* domain转dto
* @param entity
* @return
*/
D toDto(E entity);
/**
* dto集合转domain集合
* @param dtoList
* @return
*/
List <E> toDomain(List<D> dtoList);
/**
* domain集合转dto集合
* @param entityList
* @return
*/
List <D> toDto(List<E> entityList);
}
package cn.ibizlab.util.domain;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 消息对象
*/
@Data
public class MsgBody{
/**
* 接收用户
*/
@JSONField(name = "to_users")
@JsonProperty("to_users")
private String toUsers;
/**
* 标题
*/
@JSONField(name = "subject")
@JsonProperty("subject")
private String subject;
/**
* 内容
*/
@JSONField(name = "content")
@JsonProperty("content")
private String content;
/**
* 类型
*/
@JSONField(name = "msg_type")
@JsonProperty("msg_type")
private Integer msgType;
/**
* 模板标识
*/
@JSONField(name = "template_id")
@JsonProperty("template_id")
private String templateId;
/**
* 模板参数
*/
@JSONField(name = "template_params")
@JsonProperty("template_params")
private String templateParams;
/**
* 消息链接
*/
@JSONField(name = "msg_link")
@JsonProperty("msg_link")
private String msgLink;
/**
* 消息链接(pc)
*/
@JSONField(name = "msg_link_pc")
@JsonProperty("msg_link_pc")
private String msgLinkPc;
}
package cn.ibizlab.util.domain;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 实体[支付交易]
*/
@Data
public class PayTrade{
/**
* 订单标题
*/
@TableField(value = "subject")
@JSONField(name = "subject")
@JsonProperty("subject")
private String subject;
/**
* 订单金额
*/
@JSONField(name = "total_amount")
@JsonProperty("total_amount")
private String totalAmount;
/**
* 订单号
*/
@JSONField(name = "out_trade_no")
@JsonProperty("out_trade_no")
private String outTradeNo;
/**
* rt开放平台配置标识(OpenAccessId或AppId)
*/
@JSONField(name = "access_id")
@JsonProperty("access_id")
private String accessId;
}
package cn.ibizlab.util.enums;
/**
* 实体属性默认值类型
*/
public enum DEFieldDefaultValueType {
/**
* 用户全局对象
*/
SESSION,
/**
* 系统全局对象
*/
APPLICATION,
/**
* 唯一编码
*/
UNIQUEID,
/**
* 网页请求
*/
CONTEXT,
/**
* 数据对象属性
*/
PARAM,
/**
* 当前时间
*/
CURTIME,
/**
* 当前操作用户(编号)
*/
OPERATOR,
/**
* 当前操作用户(名称)
*/
OPERATORNAME,
/**
* 当前应用数据
*/
APPDATA,
/**
* 默认值
*/
NONE,
/**
* 用户自定义
*/
USER,
/**
* 用户自定义2
*/
USER2,
/**
* 用户自定义3
*/
USER3,
/**
* 用户自定义4
*/
USER4
}
package cn.ibizlab.util.enums;
/**
* 实体属性预定义类型
*/
public enum DEPredefinedFieldType {
/**
* 创建人标识
*/
CREATEMAN,
/**
* 创建人名称
*/
CREATEMANNAME,
/**
* 更新人标识
*/
UPDATEMAN,
/**
* 更新人名称
*/
UPDATEMANNAME,
/**
* 创建时间
*/
CREATEDATE,
/**
* 更新时间
*/
UPDATEDATE,
/**
* 组织机构标识
*/
ORGID,
/**
* 组织机构名称
*/
ORGNAME,
/**
* 部门标识
*/
ORGSECTORID,
/**
* 部门名称
*/
ORGSECTORNAME,
/**
* 逻辑有效
*/
LOGICVALID,
/**
* 排序
*/
ORDERVALUE,
/**
* 不处理
*/
NONE,
/**
* 动态父类型
*/
PARENTTYPE,
/**
* 动态父标识
*/
PARENTID,
/**
* 动态父名称
*/
PARENTNAME
}
package cn.ibizlab.util.enums;
/**
* 属性重复值检查
*/
public enum DupCheck {
/**
* 不检查
*/
NONE,
/**
* 全部检查
*/
ALL,
/**
* 非空检查
*/
NOTNULL,
/**
* 指定范围检查
*/
RANGE,
}
package cn.ibizlab.util.enums;
import org.springframework.data.redis.listener.ChannelTopic;
/**
* redis频道
*/
public enum RedisChannelTopic {
REDIS_CACHE_DELETE_TOPIC("redis:cache:delete:topic1", "删除redis缓存消息频道"),
REDIS_CACHE_CLEAR_TOPIC("redis:cache:clear:topic2", "清空redis缓存消息频道"),
REDIS_CACHE_DYNAMICMODEL_TOPIC("redis:cache:dynamicmodel:topic3", "动态模型频道");
String channelTopic;
String label;
RedisChannelTopic(String channelTopic, String label) {
this.channelTopic = channelTopic;
this.label = label;
}
public ChannelTopic getChannelTopic() {
return new ChannelTopic(channelTopic);
}
public static RedisChannelTopic getChannelTopicEnum(String channelTopic) {
for (RedisChannelTopic awardTypeEnum : RedisChannelTopic.values()) {
if (awardTypeEnum.getChannelTopicStr().equals(channelTopic)) {
return awardTypeEnum;
}
}
return null;
}
public String getChannelTopicStr() {
return channelTopic;
}
}
package cn.ibizlab.util.errors;
import org.zalando.problem.AbstractThrowableProblem;
import org.zalando.problem.Status;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
public class BadRequestAlertException extends AbstractThrowableProblem {
private final String entityName;
private final String errorKey;
public BadRequestAlertException(String defaultMessage, String entityName, String errorKey) {
this(ErrorConstants.DEFAULT_TYPE, defaultMessage, entityName, errorKey);
}
public BadRequestAlertException(URI type, String defaultMessage, String entityName, String errorKey) {
super(type, defaultMessage, Status.BAD_REQUEST, null, null, null, getAlertParameters(entityName, errorKey));
this.entityName = entityName;
this.errorKey = errorKey;
}
public String getEntityName() {
return entityName;
}
public String getErrorKey() {
return errorKey;
}
private static Map<String, Object> getAlertParameters(String entityName, String errorKey) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("message", "error." + errorKey);
parameters.put("params", entityName);
return parameters;
}
}
package cn.ibizlab.util.errors;
import org.zalando.problem.AbstractThrowableProblem;
import java.util.HashMap;
import java.util.Map;
import static org.zalando.problem.Status.BAD_REQUEST;
public class CustomParameterizedException extends AbstractThrowableProblem {
private static final long serialVersionUID = 1L;
private static final String PARAM = "param";
public CustomParameterizedException(String message, String... params) {
this(message, toParamMap(params));
}
public CustomParameterizedException(String message, Map<String, Object> paramMap) {
super(ErrorConstants.PARAMETERIZED_TYPE, "处理发生异常", BAD_REQUEST, null, null, null, toProblemParameters(message, paramMap));
}
public static Map<String, Object> toParamMap(String... params) {
Map<String, Object> paramMap = new HashMap<>();
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
paramMap.put(PARAM + i, params[i]);
}
}
return paramMap;
}
public static Map<String, Object> toProblemParameters(String message, Map<String, Object> paramMap) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("message", message);
parameters.put("params", paramMap);
return parameters;
}
}
package cn.ibizlab.util.errors;
import java.net.URI;
public final class ErrorConstants {
public static final String ERR_CONCURRENCY_FAILURE = "处理请求发生错误";
public static final String ERR_VALIDATION = "数据校验发生错误";
public static final String PROBLEM_BASE_URL = "";
public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message");
public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation");
public static final URI PARAMETERIZED_TYPE = URI.create(PROBLEM_BASE_URL + "/parameterized");
private ErrorConstants() {
}
}
package cn.ibizlab.util.errors;
import org.springframework.dao.*;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.zalando.problem.DefaultProblem;
import org.zalando.problem.Problem;
import org.zalando.problem.ProblemBuilder;
import org.zalando.problem.Status;
import org.zalando.problem.spring.web.advice.ProblemHandling;
import org.zalando.problem.spring.web.advice.validation.ConstraintViolationProblem;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;
@ControllerAdvice
public class ExceptionTranslator implements ProblemHandling {
@Override
public ResponseEntity<Problem> process(@Nullable ResponseEntity<Problem> entity, NativeWebRequest request) {
if (entity == null || entity.getBody() == null) {
return entity;
}
Problem problem = entity.getBody();
if (!(problem instanceof ConstraintViolationProblem || problem instanceof DefaultProblem)) {
return entity;
}
ProblemBuilder builder = Problem.builder()
.withType(Problem.DEFAULT_TYPE.equals(problem.getType()) ? ErrorConstants.DEFAULT_TYPE : problem.getType())
.withStatus(problem.getStatus())
.withTitle(problem.getTitle())
.with("path", request.getNativeRequest(HttpServletRequest.class).getRequestURI());
if (problem instanceof ConstraintViolationProblem) {
builder
.with("violations", ((ConstraintViolationProblem) problem).getViolations())
.with("message", ErrorConstants.ERR_VALIDATION);
return new ResponseEntity<>(builder.build(), entity.getHeaders(), entity.getStatusCode());
} else {
builder
.withCause(((DefaultProblem) problem).getCause())
.withDetail(problem.getDetail())
.withInstance(problem.getInstance());
problem.getParameters().forEach(builder::with);
if (!problem.getParameters().containsKey("message") && problem.getStatus() != null) {
builder.with("message", "error.http." + problem.getStatus().getStatusCode());
}
return new ResponseEntity<>(builder.build(), entity.getHeaders(), entity.getStatusCode());
}
}
@Override
public ResponseEntity<Problem> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, @Nonnull NativeWebRequest request) {
BindingResult result = ex.getBindingResult();
List<FieldErrorVM> fieldErrors = result.getFieldErrors().stream()
.map(f -> new FieldErrorVM(f.getObjectName(), f.getField(), f.getDefaultMessage()))
.collect(Collectors.toList());
Problem problem = Problem.builder()
.withType(ErrorConstants.CONSTRAINT_VIOLATION_TYPE)
.withTitle(ErrorConstants.ERR_VALIDATION)
.withStatus(defaultConstraintViolationStatus())
.with("message", ErrorConstants.ERR_VALIDATION )
.with("fieldErrors", fieldErrors)
.build();
return create(ex, problem, request);
}
@ExceptionHandler(BadRequestAlertException.class)
public ResponseEntity<Problem> handleBadRequestAlertException(BadRequestAlertException ex, NativeWebRequest request) {
return create(ex, request, createFailureAlert(ex.getEntityName(), ex.getErrorKey(), ex.getMessage()));
}
@ExceptionHandler(ConcurrencyFailureException.class)
public ResponseEntity<Problem> handleConcurrencyFailure(ConcurrencyFailureException ex, NativeWebRequest request) {
Problem problem = Problem.builder()
.withStatus(Status.CONFLICT)
.with("message", ErrorConstants.ERR_CONCURRENCY_FAILURE)
.build();
return create(ex, problem, request);
}
@ExceptionHandler(DataAccessException.class)
public ResponseEntity<Problem> handlerDataAccessFailure(DataAccessException ex, NativeWebRequest request){
Problem problem = Problem.builder()
.withStatus(Status.INTERNAL_SERVER_ERROR)
.with("message", ex.getMessage())
.build();
return create(ex, problem, request,createFailureAlert(ex.getClass().getSimpleName(), ex.getClass().getSimpleName(), ex.getMessage()));
}
public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) {
HttpHeaders headers = new HttpHeaders();
headers.add("X-ibz-error", errorKey);
headers.add("X-ibz-params", entityName);
return headers;
}
/**
* 上传文件大小超出限制异常
*/
@Value("${spring.servlet.multipart.max-file-size}")
private String maxFileSize;
@ExceptionHandler(MaxUploadSizeExceededException.class)
public ResponseEntity<Problem> handlerMaxUploadFile(MaxUploadSizeExceededException ex,NativeWebRequest request){
Problem problem = Problem.builder()
.withStatus(Status.BAD_REQUEST)
.withDetail("上传文件不能大于"+maxFileSize)
.with("message", "上传文件不能大于"+maxFileSize)
.with("exmessage",""+ex.getMessage())
.build();
return create(ex, problem, request);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Problem> handlerTest(Exception ex,NativeWebRequest request){
Problem problem = Problem.builder()
.withStatus(Status.INTERNAL_SERVER_ERROR)
.withDetail("内部服务器异常")
.with("message", "内部服务器异常")
.with("exmessage",""+ex.getMessage())
.build();
return create(ex, problem, request);
}
}
package cn.ibizlab.util.errors;
import java.io.Serializable;
public class FieldErrorVM implements Serializable {
private static final long serialVersionUID = 1L;
private final String objectName;
private final String field;
private final String message;
public FieldErrorVM(String dto, String field, String message) {
this.objectName = dto;
this.field = field;
this.message = message;
}
public String getObjectName() {
return objectName;
}
public String getField() {
return field;
}
public String getMessage() {
return message;
}
}
package cn.ibizlab.util.errors;
import org.zalando.problem.AbstractThrowableProblem;
import org.zalando.problem.Status;
public class InternalServerErrorException extends AbstractThrowableProblem {
public InternalServerErrorException(String message) {
super(ErrorConstants.DEFAULT_TYPE, message, Status.INTERNAL_SERVER_ERROR);
}
}
package cn.ibizlab.util.filter;
public interface ISearchContext {
}
package cn.ibizlab.util.filter;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.mongodb.QueryBuilder;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@Slf4j
@Data
public class QueryBuildContext extends SearchContextBase implements ISearchContext{
@JsonIgnore
@JSONField(serialize = false)
private QueryBuilder selectCond=new QueryBuilder();
public QueryBuilder getSearchCond(){
return this.selectCond;
}
/**
* 填充自定义查询条件
* @return
*/
public QueryBuilder getSelectCond() {
if(!ObjectUtils.isEmpty(filter)){
QueryBuilder queryBuilder=parseQueryFilter(filter);
if(!ObjectUtils.isEmpty(queryBuilder)){
selectCond.and(queryBuilder.get());
}
}
return selectCond;
}
/**
* 解析自定义查询条件
* @param queryFilter
* @return
*/
private QueryBuilder parseQueryFilter(QueryFilter queryFilter){
if(ObjectUtils.isEmpty(queryFilter.get$and()) && ObjectUtils.isEmpty(queryFilter.get$or()) && ObjectUtils.isEmpty(queryFilter.any())) {
return null;
}
QueryBuilder rsBuilder=QueryBuilder.start();
QueryBuilder fieldBuilder=parseFieldMap(queryFilter.any());
QueryBuilder orBuilder=parseOrQueryFilter(queryFilter.get$or());
QueryBuilder andBuilder=parseAndQueryFilter(queryFilter.get$and());
if(!ObjectUtils.isEmpty(fieldBuilder)){
rsBuilder.and(fieldBuilder.get());
}
if(!ObjectUtils.isEmpty(orBuilder)){
rsBuilder.and(orBuilder.get());
}
if(!ObjectUtils.isEmpty(andBuilder)){
rsBuilder.and(andBuilder.get());
}
return rsBuilder;
}
/**
* 解析自定义条件[or]
* @param queryFilters
* @return
*/
private QueryBuilder parseOrQueryFilter(List<QueryFilter> queryFilters) {
QueryBuilder orBuilder =new QueryBuilder();
if(queryFilters==null || queryFilters.size()==0){
return null;
}
for(QueryFilter queryFilter: queryFilters){
QueryBuilder queryBuilder=parseQueryFilter(queryFilter);
if(!ObjectUtils.isEmpty(queryBuilder)){
orBuilder.or(queryBuilder.get());
}
}
return orBuilder;
}
/**
* 解析自定义条件[and]
* @param queryFilters
* @return
*/
private QueryBuilder parseAndQueryFilter(List<QueryFilter> queryFilters) {
QueryBuilder orBuilder =new QueryBuilder();
if(queryFilters==null || queryFilters.size()==0){
return null;
}
for(QueryFilter queryFilter: queryFilters){
QueryBuilder queryBuilder=parseQueryFilter(queryFilter);
if(!ObjectUtils.isEmpty(queryBuilder)){
orBuilder.and(queryBuilder.get());
}
}
return orBuilder;
}
/**
* 解析自定义条件[字段条件]
* @param fieldMap
* @return
*/
private QueryBuilder parseFieldMap(Map<String , QueryFilter.SegmentCond> fieldMap) {
if(fieldMap.size()==0) {
return null;
}
QueryBuilder fieldBuilders=QueryBuilder.start();
for(Map.Entry<String, QueryFilter.SegmentCond> entry: fieldMap.entrySet()){
getSegmentCondSql(entry.getKey(),entry.getValue(),fieldBuilders);
}
return fieldBuilders;
}
/**
* 解析自定义条件[字段条件]
* @param fieldName
* @param segmentCond
* @param fieldBuilder
*/
private void getSegmentCondSql(String fieldName, QueryFilter.SegmentCond segmentCond,QueryBuilder fieldBuilder) {
Map<String , Object> segmentCondMap = segmentCond.any();
for(Map.Entry<String , Object> entry: segmentCondMap.entrySet()){
Object value=entry.getValue();
switch (entry.getKey()){
case "$eq":
fieldBuilder.and(QueryBuilder.start().and(fieldName).is(value).get());
break;
case "$ne":
fieldBuilder.and(QueryBuilder.start().not().and(fieldName).is(value).get());
break;
case "$gt":
fieldBuilder.and(QueryBuilder.start().and(fieldName).greaterThan(value).get());
break;
case "$gte":
fieldBuilder.and(QueryBuilder.start().and(fieldName).greaterThanEquals(value).get());
break;
case "$lt":
fieldBuilder.and(QueryBuilder.start().and(fieldName).lessThan(value).get());
break;
case "$lte":
fieldBuilder.and(QueryBuilder.start().and(fieldName).lessThanEquals(value).get());
break;
case "$null":
fieldBuilder.and(QueryBuilder.start().and(fieldName).exists(null).get());
break;
case "$notNull":
fieldBuilder.and(QueryBuilder.start().and(fieldName).exists(true).and(fieldName).notEquals("").and(fieldName).notEquals(null).get());
break;
case "$in":
fieldBuilder.and(QueryBuilder.start().and(fieldName).in(value).get());
break;
case "$notIn":
fieldBuilder.and(QueryBuilder.start().and(fieldName).not().in(value).get());
break;
case "$like":
Pattern likePattern = Pattern.compile("^.*" + value + ".*$", Pattern.CASE_INSENSITIVE);
fieldBuilder.and(QueryBuilder.start().and(fieldName).regex(likePattern).get());
break;
case "$startsWith":
Pattern startsWithPattern = Pattern.compile(value + ".*$", Pattern.CASE_INSENSITIVE);
fieldBuilder.and(QueryBuilder.start().and(fieldName).regex(startsWithPattern).get());
break;
case "$endsWith":
Pattern endsWithPattern = Pattern.compile("^.*" + value + "$", Pattern.CASE_INSENSITIVE);
fieldBuilder.and(QueryBuilder.start().and(fieldName).regex(endsWithPattern).get());
break;
case "$exists":
break;
case "$notExists":
break;
}
}
}
}
package cn.ibizlab.util.filter;
import com.fasterxml.jackson.annotation.*;
import org.springframework.data.annotation.Transient;
import java.util.*;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class QueryFilter {
public static QueryFilter createQuery()
{
QueryFilter queryFilter=new QueryFilter();
return queryFilter;
}
public QueryFilter eq(String column,Object value) {
return op(column,SegmentCond.eq(value));
}
public QueryFilter ne(String column,Object value) {
return op(column,SegmentCond.ne(value));
}
public QueryFilter gt(String column,Object value) {
return op(column,SegmentCond.gt(value));
}
public QueryFilter ge(String column,Object value) {
return op(column,SegmentCond.ge(value));
}
public QueryFilter lt(String column,Object value) {
return op(column,SegmentCond.lt(value));
}
public QueryFilter le(String column,Object value) {
return op(column,SegmentCond.le(value));
}
public QueryFilter isnull(String column) {
return op(column,SegmentCond.isnull());
}
public QueryFilter isnotnull(String column) {
return op(column,SegmentCond.isnotnull());
}
public QueryFilter in(String column,Collection value) {
return op(column,SegmentCond.in(value));
}
public QueryFilter notin(String column,Collection value) {
return op(column,SegmentCond.notin(value));
}
public QueryFilter like(String column,String value) {
return op(column,SegmentCond.like(value));
}
public QueryFilter startsWith(String column,String value) {
return op(column,SegmentCond.startsWith(value));
}
public QueryFilter endsWith(String column,String value) {
return op(column,SegmentCond.endsWith(value));
}
public QueryFilter between(String column,Object from,Object to) {
return op(column,SegmentCond.between(from,to));
}
@JsonIgnore
@Transient
private Map<String,SegmentCond> map;
private Map<String,SegmentCond> getMap()
{
if(map==null) {
map=new LinkedHashMap<>();
}
return map;
}
@JsonAnyGetter
public Map<String , SegmentCond> any() {
return getMap();
}
@JsonAnySetter
public void set(String column, SegmentCond value) {
getMap().put(column,value);
}
@JsonProperty(index = 999)
private List<QueryFilter> $or;
public List<QueryFilter> get$or() {
return $or;
}
public void set$or(List<QueryFilter> $or) {
this.$or = $or;
}
public QueryFilter or(QueryFilter... ors)
{
if ($or == null) {
$or = new ArrayList();
}
Collections.addAll($or, ors);
return this;
}
@JsonProperty(index = 999)
private List<QueryFilter> $and;
public List<QueryFilter> get$and() {
return $and;
}
public void set$and(List<QueryFilter> $and) {
this.$and = $and;
}
public QueryFilter and(QueryFilter... ands)
{
if ($and == null) {
$and = new ArrayList();
}
Collections.addAll($and, ands);
return this;
}
@Override
public String toString() {
return "QueryFilter{" +
"map=" + map +
", $or=" + $or +
'}';
}
private QueryFilter op(String column, SegmentCond segmentCond) {
if(this.getMap().containsKey(column)) {
((SegmentCond)this.getMap().get(column)).getMap().putAll(segmentCond.getMap());
}
else {
this.getMap().put(column,segmentCond);
}
return this;
}
public static class SegmentCond {
@JsonIgnore
@Transient
private Map<String,Object> map;
@Override
public String toString() {
return "SegmentCond{" +
"map=" + map +
'}';
}
private Map<String,Object> getMap()
{
if(map==null) {
map=new LinkedHashMap<>();
}
return map;
}
@JsonAnyGetter
public Map<String , Object> any() {
return getMap();
}
@JsonAnySetter
public void set(String column, Object value) {
getMap().put(column,value);
}
public static SegmentCond eq(Object value) {
return op(Segment.EQ,value);
}
public static SegmentCond ne(Object value) {
return op(Segment.NE,value);
}
public static SegmentCond gt(Object value) {
return op(Segment.GT,value);
}
public static SegmentCond ge(Object value) {
return op(Segment.GE,value);
}
public static SegmentCond lt(Object value) {
return op(Segment.LT,value);
}
public static SegmentCond le(Object value) {
return op(Segment.LE,value);
}
public static SegmentCond isnull() {
return op(Segment.IS_NULL,true);
}
public static SegmentCond isnotnull() {
return op(Segment.IS_NOT_NULL,true);
}
public static SegmentCond in(Collection value) {
return op(Segment.IN,value);
}
public static SegmentCond notin(Collection value) {
return op(Segment.NOTIN,value);
}
public static SegmentCond like(String value) {
return op(Segment.LIKE,value);
}
public static SegmentCond startsWith(String value) {
return op(Segment.LEFTLIKE,value);
}
public static SegmentCond endsWith(String value) {
return op(Segment.RIGHTLIKE,value);
}
public static SegmentCond between(Object from,Object to) {
return op(Segment.GE,from).op(Segment.LT,to);
}
private static SegmentCond op(Segment segment,Object value) {
SegmentCond segmentCond=new SegmentCond();
segmentCond.getMap().put(segment.keyword,value);
return segmentCond;
}
}
public enum Segment {
AND("$and"),
OR("$or"),
EQ("$eq"),
NE("$ne"),
GT("$gt"),
GE("$gte"),
LT("$lt"),
LE("$lte"),
IS_NULL("$null"),
IS_NOT_NULL("$notNull"),
IN("$in"),
NOTIN("$notIn"),
LIKE("$like"),
LEFTLIKE("$startsWith"),
RIGHTLIKE("$endsWith"),
EXISTS("$exists"),
NOTEXISTS("$notExists");
private final String keyword;
Segment(final String keyword) {
this.keyword = keyword;
}
}
/*
SQL: (field1>1 and field2='3' and (field3 like "a" or (field4 is not null and field5 in ['11','12']) )
JAVA: QueryFilter filter=QueryFilter.createQuery()
.gt("field1",1)
.eq("field2",'3')
.or(QueryFilter.createQuery().like("field3","a")
,QueryFilter.createQuery().isnotnull("field4").in("field5",Arrays.asList("11","12")));
JSON: {
"$or":[
{
"field3":{"$like":"a"}
},
{
"field4":{ "$notNull":true},
"field5":{"$in":["11","12"]}
}],
"field1":{"$gt":1},
"field2":{"$eq":"3" }
}
*/
}
package cn.ibizlab.util.filter;
import cn.ibizlab.util.helper.DEFieldCacheMap;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.lang.reflect.ParameterizedType;
import java.util.*;
import java.util.function.Consumer;
@Slf4j
@Data
public class QueryWrapperContext<T> extends SearchContextBase implements ISearchContext{
@JsonIgnore
@JSONField(serialize = false)
private QueryWrapper<T> selectCond=new QueryWrapper<T>();
/**
* 解析查询上下文中的参数,构建mybatis-plus分页对象
* @return
*/
@JsonIgnore
@JSONField(serialize = false)
public Page getPages(){
Page page;
List<String> asc_fieldList = new ArrayList<>();
List<String> desc_fieldList = new ArrayList<>();
int currentPage=getPageable().getPageNumber();
int pageSize=getPageable().getPageSize();
//构造mybatis-plus分页
if(StringUtils.isEmpty(currentPage) || StringUtils.isEmpty(pageSize)) {
page=new Page(1,Short.MAX_VALUE);
}
else {
page=new Page(currentPage+1,pageSize);
}
//构造mybatis-plus排序
Sort sort = getPageable().getSort();
Iterator<Sort.Order> it_sort = sort.iterator();
if(ObjectUtils.isEmpty(it_sort)) {
return page;
}
ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
Class<T> type = (Class<T>)parameterizedType.getActualTypeArguments()[0];
while (it_sort.hasNext()) {
Sort.Order sort_order = it_sort.next();
if(sort_order.getDirection()== Sort.Direction.ASC){
asc_fieldList.add(DEFieldCacheMap.getFieldColumnName(type,sort_order.getProperty()));
}
else if(sort_order.getDirection()== Sort.Direction.DESC){
desc_fieldList.add(DEFieldCacheMap.getFieldColumnName(type,sort_order.getProperty()));
}
}
if(asc_fieldList.size()>0){
page.setAscs(asc_fieldList);
}
if(desc_fieldList.size()>0){
page.setDescs(desc_fieldList);
}
return page;
}
public QueryWrapper<T> getSearchCond(){
return this.selectCond;
}
/**
* 填充自定义查询条件
* @return
*/
public QueryWrapper<T> getSelectCond() {
if(!ObjectUtils.isEmpty(filter)){
Consumer queryWrapper = parseQueryFilter(filter);
if(!ObjectUtils.isEmpty(queryWrapper)){
selectCond.and(queryWrapper);
}
}
return selectCond;
}
/**
* 解析自定义查询条件
* @param queryFilter
* @return
*/
private Consumer<QueryWrapper<T>> parseQueryFilter(QueryFilter queryFilter){
if(queryFilter.any().size()==0 && queryFilter.get$or()==null && queryFilter.get$and()==null) {
return null;
}
Consumer<QueryWrapper<T>> consumer = queryWrapper -> {
Consumer fieldConsumer=parseFieldMap(queryFilter.any());
Consumer orConsumer=parseOrQueryFilter(queryFilter.get$or());
Consumer andConsumer=parseAndQueryFilter(queryFilter.get$and());
if(!ObjectUtils.isEmpty(fieldConsumer)){
queryWrapper.and(fieldConsumer);
}
if(!ObjectUtils.isEmpty(orConsumer)){
queryWrapper.and(orConsumer);
}
if(!ObjectUtils.isEmpty(andConsumer)){
queryWrapper.and(andConsumer);
}
};
return consumer;
}
/**
* 解析自定义条件[or]
* @param queryFilters
* @return
*/
private Consumer<QueryWrapper<T>> parseOrQueryFilter(List<QueryFilter> queryFilters) {
if(queryFilters==null || queryFilters.size()==0)
return null;
Consumer<QueryWrapper<T>> consumer = queryWrapper -> {
for(QueryFilter queryFilter: queryFilters){
Consumer tempQueryWrapper=parseQueryFilter(queryFilter);
queryWrapper.or(tempQueryWrapper);
}
};
return consumer;
}
/**
* 解析自定义条件[and]
* @param queryFilters
* @return
*/
private Consumer<QueryWrapper<T>> parseAndQueryFilter(List<QueryFilter> queryFilters) {
if(queryFilters==null || queryFilters.size()==0) {
return null;
}
Consumer<QueryWrapper<T>> consumer = queryWrapper -> {
for(QueryFilter queryFilter: queryFilters){
Consumer tempQueryWrapper=parseQueryFilter(queryFilter);
queryWrapper.and(tempQueryWrapper);
}
};
return consumer;
}
/**
* 解析自定义条件[字段条件]
* @param fieldMap
* @return
*/
private Consumer<QueryWrapper<T>> parseFieldMap(Map<String , QueryFilter.SegmentCond> fieldMap) {
if(fieldMap.size()==0) {
return null;
}
Consumer<QueryWrapper<T>> consumer = queryWrapper -> {
for(Map.Entry<String, QueryFilter.SegmentCond> field: fieldMap.entrySet()){
String fieldName=field.getKey();
QueryFilter.SegmentCond segmentCond=field.getValue();
Map<String , Object> segmentCondMap = segmentCond.any();
for(Map.Entry<String , Object> fieldCond: segmentCondMap.entrySet()){
Object value=fieldCond.getValue();
switch (fieldCond.getKey()){
case "$eq":
queryWrapper.eq(fieldName,value);
break;
case "$ne":
queryWrapper.ne(fieldName,value);
break;
case "$gt":
queryWrapper.gt(fieldName,value);
break;
case "$gte":
queryWrapper.ge(fieldName,value);
break;
case "$lt":
queryWrapper.lt(fieldName,value);
break;
case "$lte":
queryWrapper.le(fieldName,value);
break;
case "$null":
queryWrapper.isNull(fieldName);
break;
case "$notNull":
queryWrapper.isNotNull(fieldName);
break;
case "$in":
queryWrapper.in(fieldName,(Collection)value);
break;
case "$notIn":
queryWrapper.notIn(fieldName,(Collection)value);
break;
case "$like":
queryWrapper.like(fieldName,value);
break;
case "$startsWith":
queryWrapper.likeRight(fieldName,value);
break;
case "$endsWith":
queryWrapper.likeLeft(fieldName,value);
break;
case "$exists":
break;
case "$notExists":
break;
}
}
}
};
return consumer;
}
}
package cn.ibizlab.util.filter;
import cn.ibizlab.util.security.AuthenticationUser;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.util.StringUtils;
import org.springframework.util.ObjectUtils;
import java.util.*;
@Slf4j
@Data
public class SearchContextBase implements ISearchContext{
/**
* 自定义查询条件
*/
@JsonProperty("customcond")
public String customCond;
/**
* 自定义查询参数
*/
@JsonProperty("customparams")
public String customParams;
/**
* 快速搜索
*/
@JsonProperty("query")
public String query;
/**
* 条件表达式
*/
@JsonProperty("filter")
public QueryFilter filter;
/**
* 数据查询
*/
public List dataQueryList;
/**
* 当前页数
*/
public int page=0;
/**
* 每页显示条数
*/
public int size=20;
/**
* 排序
*/
public String sort;
/**
* 排序对象
*/
@JsonIgnore
public Sort pageSort;
/**
* 工作流步骤标识
*/
public String userTaskId;
/**
* 工作流流程标识
*/
public String processDefinitionKey;
/**
* 工作流标识
*/
@JsonProperty("srfwf")
public String srfWF;
/**
* 获取工作流步骤标识
*/
public String getUserTaskId() {
if(StringUtils.isEmpty(userTaskId)){
Object taskId=params.get("usertaskid");
return StringUtils.isEmpty(taskId)?null:String.valueOf(taskId);
}else{
return userTaskId;
}
}
/**
* 获取工作流流程标识
* @return
*/
public String getProcessDefinitionKey() {
if(StringUtils.isEmpty(processDefinitionKey)){
Object processKey=params.get("processdefinitionkey");
return StringUtils.isEmpty(processKey)?null:String.valueOf(processKey);
}
else{
return processDefinitionKey;
}
}
/**
* 获取分页参数
* @return
*/
public Pageable getPageable() {
if(ObjectUtils.isEmpty(pageSort)) {
return PageRequest.of(page,size);
}
else {
return PageRequest.of(page,size,pageSort);
}
}
/**
* 设置排序值
* @param strSort
*/
public void setSort(String strSort) {
this.sort=strSort;
if(!StringUtils.isEmpty(strSort)){
String sortArr[]=strSort.split(",");
String sortField=sortArr[0];
String sortDirection=sortArr[1];
if(sortDirection.equalsIgnoreCase("asc")){
this.pageSort=Sort.by(Sort.Direction.ASC,sortField);
}
else if(sortDirection.equalsIgnoreCase("desc")){
this.pageSort=Sort.by(Sort.Direction.DESC,sortField);
}
}
}
/**
* 上下文参数
*/
Map<String,Object> params = new HashMap<String,Object>() ;
/**
* 获取数据上下文
* @return
*/
public Map<String,Object> getDatacontext() {
return params;
}
/**
* 获取网页请求上下文
* @return
*/
public Map<String,Object> getWebcontext() {
return params;
}
/**
* 获取用户上下文
* @return
*/
@JsonIgnore
public Map<String,Object> getSessioncontext() {
return AuthenticationUser.getAuthenticationUser().getSessionParams();
}
@JsonAnyGetter
public Map<String , Object> any() {
return params;
}
@JsonAnySetter
public void set(String name, Object value) {
params.put(name, value);
}
}
package cn.ibizlab.util.helper;
import org.springframework.cglib.beans.BeanCopier;
import java.util.HashMap;
import java.util.Map;
public class CachedBeanCopier {
//创建过的BeanCopier实例放到缓存中,下次可以直接获取,提升性能
static final Map<String, BeanCopier> BEAN_COPIERS = new HashMap<String, BeanCopier>();
public static void copy(Object srcObj, Object destObj) {
copy(srcObj,destObj,false);
}
public static void copy(Object srcObj, Object destObj,boolean useConverter) {
if(srcObj==null||destObj==null) {
return;
}
getCopier(srcObj,destObj,useConverter).copy(srcObj, destObj, null);
}
public synchronized static BeanCopier getCopier(Object srcObj, Object destObj,boolean useConverter) {
String key = srcObj.getClass().getName()+destObj.getClass().getName()+useConverter;
BeanCopier copier;
if (!BEAN_COPIERS.containsKey(key)) {
copier = BeanCopier.create(srcObj.getClass(), destObj.getClass(), useConverter);
BEAN_COPIERS.put(key, copier);
} else {
copier = BEAN_COPIERS.get(key);
}
return copier;
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
package cn.ibizlab.util.helper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
@Slf4j
public class UniqueNameGenerator extends AnnotationBeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
//全限定类名
String beanName = definition.getBeanClassName();
return beanName;
}
}
package cn.ibizlab.util.mapper;
import cn.ibizlab.util.domain.IBZConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface IBZConfigMapper extends BaseMapper<IBZConfig>{
}
\ No newline at end of file
package cn.ibizlab.util.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.ibizlab.util.domain.IBZDataAudit;
public interface IBZDataAuditMapper extends BaseMapper<IBZDataAudit> {
}
\ No newline at end of file
package cn.ibizlab.util.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.ibizlab.util.domain.IBZUSER;
public interface IBZUSERMapper extends BaseMapper<IBZUSER>{
}
\ No newline at end of file
此差异已折叠。
此差异已折叠。
package cn.ibizlab.util.security;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Date;
public interface AuthTokenUtil {
String generateToken(UserDetails userDetails);
Boolean validateToken(String token, UserDetails userDetails);
String getUsernameFromToken(String token);
Date getExpirationDateFromToken(String token) ;
}
package cn.ibizlab.util.service;
import cn.ibizlab.util.domain.FileItem;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
public interface FileService
{
FileItem saveFile(MultipartFile multipartFile);
File getFile(String fileid);
}
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册