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

init

上级 cd9d3e56
......@@ -7,7 +7,7 @@
<artifactId>ibizlab-util</artifactId>
<name>ibizlab-util</name>
<description>ibizlab-util</description>
<version>0.0.2</version>
<version>1.0.2</version>
<!-- Spring Boot -->
<parent>
......@@ -17,10 +17,8 @@
</parent>
<properties>
<!-- Spring Cloud Alibaba(2.2.x.RELEASE) & Spring Cloud(Spring Cloud Greenwich) & Spring Boot(2.2.x.RELEASE) compatibility -->
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
<spring-cloud-openfeign.version>2.2.1.RELEASE</spring-cloud-openfeign.version>
<ibizlab-common.version>1.0.2</ibizlab-common.version>
<!-- Alibaba Druid -->
<alibaba-druid.version>1.1.21</alibaba-druid.version>
......@@ -35,54 +33,18 @@
<!-- JBPM+Drools -->
<drools-version>7.23.0.Final</drools-version>
<!-- Error -->
<zalando-problem-spring-web.version>0.23.0</zalando-problem-spring-web.version>
<!-- Security -->
<spring-cloud-security.version>2.1.1.RELEASE</spring-cloud-security.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<!--logstash-logback-encoder-->
<logstash.version>5.2</logstash.version>
<!--Zuul网关-->
<spring-cloud-starter-netflix-zuul.version>2.2.1.RELEASE</spring-cloud-starter-netflix-zuul.version>
<!--MapStruct高性能属性映射工具-->
<mapstruct.version>1.3.0.Final</mapstruct.version>
<!--Java Web Token-->
<jsonwebtoken-jjwt.version>0.9.1</jsonwebtoken-jjwt.version>
<!--Liquibase数据库版本更新工具-->
<liquibase.version>3.9.0</liquibase.version>
<!--H2内存数据库-->
<h2.version>1.4.200</h2.version>
<!--caffeine缓存-->
<caffeine-cache.version>2.6.0</caffeine-cache.version>
<!--反序列化工具-->
<kryo.version>4.0.2</kryo.version>
<!--httpClient -->
<openfeign-httpclient.version>11.0</openfeign-httpclient.version>
<!--baomidou-jobs定时服务 -->
<baomidou-jobs.version>1.0.3</baomidou-jobs.version>
<!-- eureka微服务注册中心 -->
<eureka-client.version>2.2.1.RELEASE</eureka-client.version>
<!-- 阿里sentinel熔断器 -->
<alibaba-sentinel.version>2.1.1.RELEASE</alibaba-sentinel.version>
<!-- 阿里seata分布式事务 -->
<alibaba-seata.version>1.3.0</alibaba-seata.version>
<log4j2.version>2.16.0</log4j2.version>
<oracle.version>19.8.0.0</oracle.version>
<postgresql.version>42.2.6</postgresql.version>
<flowable-modeler.version>6.4.2</flowable-modeler.version>
......@@ -90,22 +52,11 @@
<dependencyManagement>
<dependencies>
<!-- Alibaba Cloud -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-dependencies</artifactId>
<version>${spring-cloud-openfeign.version}</version>
<type>pom</type>
<scope>import</scope>
<groupId>cn.ibizlab</groupId>
<artifactId>ibizlab-common</artifactId>
<version>${ibizlab-common.version}</version>
</dependency>
<!-- Alibaba Druid -->
......@@ -126,6 +77,7 @@
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
......@@ -192,20 +144,6 @@
<version>${drools-version}</version>
</dependency>
<!-- Error -->
<!-- Security -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>${logstash.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>${spring-cloud-starter-netflix-zuul.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
......@@ -218,43 +156,6 @@
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<version>${spring-cloud-security.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jsonwebtoken-jjwt.version}</version>
</dependency>
<dependency>
<groupId>org.zalando</groupId>
<artifactId>problem-spring-web</artifactId>
<version>${zalando-problem-spring-web.version}</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>${caffeine-cache.version}</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo-shaded</artifactId>
<version>${kryo.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>${openfeign-httpclient.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>jobs-spring-boot-starter</artifactId>
......@@ -272,66 +173,6 @@
<artifactId>flowable-ui-modeler-conf</artifactId>
<version>${flowable-modeler.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>${alibaba-sentinel.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- 阿里Druid数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- H2内存库 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- eureka服务注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>${eureka-client.version}</version>
</dependency>
<!-- Oracle驱动包 -->
<dependency>
......@@ -355,72 +196,50 @@
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mp动态数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<groupId>cn.ibizlab</groupId>
<artifactId>ibizlab-common</artifactId>
</dependency>
<!-- 阿里Druid数据源 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- H2内存库 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>org.zalando</groupId>
<artifactId>problem-spring-web</artifactId>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo-shaded</artifactId>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- Swagger2 -->
......@@ -433,11 +252,6 @@
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<!-- drools -->
<dependency>
<groupId>org.drools</groupId>
......@@ -487,9 +301,9 @@
<repositories>
<repository>
<id>ibizmvnrepository</id>
<name>ibizmvnrepository</name>
<url>http://172.16.240.220:8081/nexus/content/groups/public/</url>
<id>aliyunmaven</id>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
......@@ -500,9 +314,9 @@
</snapshots>
</repository>
<repository>
<id>aliyunmaven</id>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public/</url>
<id>ibizmvnrepository</id>
<name>ibizmvnrepository</name>
<url>http://172.16.240.220:8081/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
......@@ -512,5 +326,6 @@
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
</project>
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 cn.ibizlab.util.dict.Catalog;
import cn.ibizlab.util.dict.CodeList;
import com.alibaba.fastjson.JSONArray;
import org.springframework.stereotype.Component;
@Component
public class IBZDictFallback implements IBZDictFeignClient {
@Override
public Boolean syncRuntimeDict(JSONArray catalogs) {
return null;
}
@Override
public CodeList getCodeList(String code) {
return null;
}
@Override
public Catalog getCatalog(String code) {
return null;
}
}
\ No newline at end of file
package cn.ibizlab.util.client;
import cn.ibizlab.util.dict.Catalog;
import cn.ibizlab.util.dict.CodeList;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
import java.util.Map;
@FeignClient(value = "${r'${ibiz.ref.service.dict:ibzdict-api}'}",contextId = "dict",fallback = IBZDictFallback.class)
public interface IBZDictFeignClient
{
@RequestMapping(method = RequestMethod.POST, value = "/dictionarys/catalogs/sync")
Boolean syncRuntimeDict(@RequestBody JSONArray catalogs);
@Cacheable( value="dictcatalog",key = "'codelist:'+#p0")
@RequestMapping(method = RequestMethod.GET, value = "/dictionarys/codelist/{code}")
CodeList getCodeList(@PathVariable("code") String code);
@Cacheable( value="dictcatalog",key = "'dict:'+#p0")
@RequestMapping(method = RequestMethod.GET, value = "/dictionarys/catalogs/{code}")
Catalog getCatalog(@PathVariable("code") String code);
}
\ No newline at end of file
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.dict;
import cn.ibizlab.util.helper.DataObject;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Catalog
{
private String code;
private String name;
@JSONField(name = "items")
@JsonProperty("items")
private List<Option> options = new ArrayList<>();
public Option findCodeItem(Object value)
{
return findCodeItem(value,this.options);
}
public Option findCodeItem(Object value, List<Option> options){
for(Option codeItem : options){
if(value != null && codeItem.getValue() != null && value.equals(codeItem.getValue()))
return codeItem;
else if (!ObjectUtils.isEmpty(codeItem.getChildren()))
{
Option rt=findCodeItem(value,codeItem.getChildren());
if(rt!=null)
return rt;
}
}
return null;
}
private Map<String, Object> advancedSettings;
public Catalog putAdvancedSettings(String settings)
{
try
{
if(!StringUtils.isEmpty(settings))
advancedSettings= JSON.parseObject(settings, Map.class);
}catch (Exception ex){}
return this;
}
@JsonIgnore
@JSONField(serialize = false)
public String getUrl() {
return advancedSettings!=null&&advancedSettings.get("url")!=null?advancedSettings.get("url").toString():null;
}
@JsonIgnore
@JSONField(serialize = false)
public String getRequestMethod() {
return advancedSettings!=null&&advancedSettings.get("requestMethod")!=null?advancedSettings.get("requestMethod").toString():"GET";
}
@JsonIgnore
@JSONField(serialize = false)
public String getRequestBody() {
return advancedSettings!=null&&advancedSettings.get("requestBody")!=null?advancedSettings.get("requestBody").toString():"{}";
}
@JsonIgnore
@JSONField(serialize = false)
public String getNodeProp() {
return advancedSettings!=null&&advancedSettings.get("nodeProp")!=null?advancedSettings.get("nodeProp").toString():"";
}
@JsonIgnore
@JSONField(serialize = false)
public String getValueProp() {
return advancedSettings!=null&&advancedSettings.get("valueProp")!=null?advancedSettings.get("valueProp").toString():"value";
}
@JsonIgnore
@JSONField(serialize = false)
public String getLabelProp() {
return advancedSettings!=null&&advancedSettings.get("labelProp")!=null?advancedSettings.get("labelProp").toString():"label";
}
@JsonIgnore
@JSONField(serialize = false)
public String getParentProp() {
return advancedSettings!=null&&advancedSettings.get("parentProp")!=null?advancedSettings.get("parentProp").toString():"parent";
}
@JsonIgnore
@JSONField(serialize = false)
public String getChildrenProp() {
return advancedSettings!=null&&advancedSettings.get("childrenProp")!=null?advancedSettings.get("childrenProp").toString():"children";
}
@JsonIgnore
@JSONField(serialize = false)
public String getDisabledProp() {
return advancedSettings!=null&&advancedSettings.get("disabledProp")!=null?advancedSettings.get("disabledProp").toString():"disabled";
}
@JsonIgnore
@JSONField(serialize = false)
public String getFilterProp() {
return advancedSettings!=null&&advancedSettings.get("filterProp")!=null?advancedSettings.get("filterProp").toString():"filter";
}
@JsonIgnore
@JSONField(serialize = false)
public String getExpiredProp() {
return advancedSettings!=null&&advancedSettings.get("expiredProp")!=null?advancedSettings.get("expiredProp").toString():"expired";
}
@JsonIgnore
@JSONField(serialize = false)
public String getIconClassProp() {
return advancedSettings!=null&&advancedSettings.get("iconClassProp")!=null?advancedSettings.get("iconClassProp").toString():"iconClass";
}
public Catalog setNodes(List<Map> nodes)
{
return setNodes(nodes,null,null);
}
public Catalog setNodes(List<Map> nodes, String filter, String subCode)
{
Map<String, List<Option>> map = new LinkedHashMap<>();
Option subOption=null;
for(Map item:unfoldList(nodes,null))
{
Map<String, Object> extension = new HashMap<>();
if(!StringUtils.isEmpty(item.get("extension")))
extension = JSONObject.parseObject(item.get("extension").toString(), Map.class);
String pid= DataObject.getStringValue(item.get(this.getParentProp()), DataObject.getStringValue(item.get("pvalue"),"_root"));
if(StringUtils.isEmpty(pid))pid="_root";
List<Option> list=null;
if(!map.containsKey(pid))
{
list=new ArrayList<>();
map.put(pid,list);
}
else
list=map.get(pid);
Option option=new Option().setValue(DataObject.getStringValue(item.get(this.getValueProp()), DataObject.getStringValue(item.get("id"),null)))
.setId(DataObject.getStringValue(item.get(this.getValueProp()), DataObject.getStringValue(item.get("id"),null)))
.setDisabled(DataObject.getBooleanValue(item.get(this.getDisabledProp()),false)|| DataObject.getBooleanValue(item.get(this.getExpiredProp()),false))
.setFilter(DataObject.getStringValue(item.get(this.getFilterProp()),null)).setIconClass(DataObject.getStringValue(item.get(this.getIconClassProp()),null))
.setLabel(DataObject.getStringValue(item.get(this.getLabelProp()), DataObject.getStringValue(item.get("text"),"")))
.setParent(DataObject.getStringValue(item.get(this.getParentProp()), DataObject.getStringValue(item.get("pvalue"),""))).setExtension(extension);
if(option.getValue().equals(subCode))
subOption=option;
if(StringUtils.isEmpty(filter)||option.getFilterSet().contains(filter))
list.add(option);
}
List<Option> codeItemTreeList = loop(map, (StringUtils.isEmpty(subCode))?"_root":subCode);
if(subOption!=null)
{
subOption.setChildren(codeItemTreeList).setParent("");
this.getOptions().add(subOption.setParent(null));
}
else
this.setOptions(codeItemTreeList);
return this;
}
public List<Map> unfoldList(List<Map> nodes, String parent)
{
List<Map> unfoldList = new ArrayList<>();
for(Map item:nodes)
{
if((!StringUtils.isEmpty(parent))&&StringUtils.isEmpty(DataObject.getStringValue(item.get(this.getParentProp()), DataObject.getStringValue(item.get("pvalue"),null))))
item.put(this.getParentProp(),parent);
String value = DataObject.getStringValue(item.get(this.getValueProp()), DataObject.getStringValue(item.get("id"),null));
unfoldList.add(item);
Object child=item.get(this.getChildrenProp());
if(!ObjectUtils.isEmpty(child))
{
if(child instanceof List && ((List) child).get(0) instanceof Map)
unfoldList.addAll(unfoldList((List)child,value));
item.remove(this.getChildrenProp());
}
}
return unfoldList;
}
public List<Option> loop(Map<String, List<Option>> listCodeItem, Object parentValue) {
List<Option> trees = new ArrayList<Option>();
if(listCodeItem.containsKey(parentValue)) {
for (Option codeItem : listCodeItem.get(parentValue)) {
List<Option> childCodeItem = loop(listCodeItem, codeItem.getValue());
if (childCodeItem.size() > 0)
codeItem.setChildren(childCodeItem);
trees.add(codeItem);
}
}
return trees;
}
}
package cn.ibizlab.util.dict;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import liquibase.util.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class CodeItem
{
private String id;
private Object value;
private String label;
@JsonIgnore
@JSONField(serialize = false)
private List<CodeItem> children;
private String iconClass;
private String filter;
private Boolean disabled;
@JSONField(name = "pvalue")
@JsonProperty("pvalue")
private String parent;
private Map<String, Object> extension;
@JSONField(name = "text")
@JsonProperty("text")
public String getText()
{
return label;
}
@JsonIgnore
@JSONField(serialize = false)
public Set<String> getFilterSet()
{
Set<String> set=new HashSet<>();
if(!StringUtils.isEmpty(filter))
for(String str:filter.split(";|,"))
set.add(str);
return set;
}
}
package cn.ibizlab.util.dict;
import cn.ibizlab.util.helper.DataObject;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class CodeList
{
@JSONField(name = "srfkey")
@JsonProperty("srfkey")
private String code;
private String name;
@JSONField(name = "emptytext")
@JsonProperty("emptytext")
public String getEmptytext()
{
return "";
}
@JSONField(name = "items")
@JsonProperty("items")
private List<CodeItem> options = new ArrayList<>();
public CodeItem findCodeItem(Object value){
for(CodeItem codeItem : options){
if(value != null && codeItem.getValue() != null && value.equals(codeItem.getValue()))
return codeItem;
}
return null;
}
public CodeItem findChildren(Object value){
CodeItem resultCodeItem = this.findCodeItem(value);
List<CodeItem> children = new ArrayList<>();
for(CodeItem codeItem : options){
if(value != null && resultCodeItem.getValue() != null && codeItem.getParent() != null && codeItem.getParent().equals(resultCodeItem.getValue()))
children.add(codeItem);
}
resultCodeItem.setChildren(children);
return resultCodeItem;
}
private Map<String, Object> advancedSettings;
public CodeList putAdvancedSettings(String settings)
{
try
{
if(!StringUtils.isEmpty(settings))
advancedSettings= JSON.parseObject(settings, Map.class);
}catch (Exception ex){}
return this;
}
@JsonIgnore
@JSONField(serialize = false)
public String getUrl() {
return advancedSettings!=null&&advancedSettings.get("url")!=null?advancedSettings.get("url").toString():null;
}
@JsonIgnore
@JSONField(serialize = false)
public String getRequestMethod() {
return advancedSettings!=null&&advancedSettings.get("requestMethod")!=null?advancedSettings.get("requestMethod").toString():"GET";
}
@JsonIgnore
@JSONField(serialize = false)
public String getRequestBody() {
return advancedSettings!=null&&advancedSettings.get("requestBody")!=null?advancedSettings.get("requestBody").toString():"{}";
}
@JsonIgnore
@JSONField(serialize = false)
public String getNodeProp() {
return advancedSettings!=null&&advancedSettings.get("nodeProp")!=null?advancedSettings.get("nodeProp").toString():"";
}
@JsonIgnore
@JSONField(serialize = false)
public String getValueProp() {
return advancedSettings!=null&&advancedSettings.get("valueProp")!=null?advancedSettings.get("valueProp").toString():"value";
}
@JsonIgnore
@JSONField(serialize = false)
public String getLabelProp() {
return advancedSettings!=null&&advancedSettings.get("labelProp")!=null?advancedSettings.get("labelProp").toString():"label";
}
@JsonIgnore
@JSONField(serialize = false)
public String getParentProp() {
return advancedSettings!=null&&advancedSettings.get("parentProp")!=null?advancedSettings.get("parentProp").toString():"parent";
}
@JsonIgnore
@JSONField(serialize = false)
public String getChildrenProp() {
return advancedSettings!=null&&advancedSettings.get("childrenProp")!=null?advancedSettings.get("childrenProp").toString():"children";
}
@JsonIgnore
@JSONField(serialize = false)
public String getDisabledProp() {
return advancedSettings!=null&&advancedSettings.get("disabledProp")!=null?advancedSettings.get("disabledProp").toString():"disabled";
}
@JsonIgnore
@JSONField(serialize = false)
public String getFilterProp() {
return advancedSettings!=null&&advancedSettings.get("filterProp")!=null?advancedSettings.get("filterProp").toString():"filter";
}
@JsonIgnore
@JSONField(serialize = false)
public String getExpiredProp() {
return advancedSettings!=null&&advancedSettings.get("expiredProp")!=null?advancedSettings.get("expiredProp").toString():"expired";
}
@JsonIgnore
@JSONField(serialize = false)
public String getIconClassProp() {
return advancedSettings!=null&&advancedSettings.get("iconClassProp")!=null?advancedSettings.get("iconClassProp").toString():"iconClass";
}
public CodeList setNodes(List<Map> nodes, String filter, String subCode)
{
Map<String, List<CodeItem>> map = new LinkedHashMap<>();
List<CodeItem> alllist = new ArrayList<>();
CodeItem subOption=null;
for(Map item:unfoldList(nodes,null))
{
Map<String, Object> extension = new HashMap<>();
if(!StringUtils.isEmpty(item.get("extension")))
extension = JSONObject.parseObject(item.get("extension").toString(), Map.class);
String pid= DataObject.getStringValue(item.get(this.getParentProp()), DataObject.getStringValue(item.get("pvalue"),"_root"));
if(StringUtils.isEmpty(pid))pid="_root";
List<CodeItem> list=null;
if(!map.containsKey(pid))
{
list=new ArrayList<>();
map.put(pid,list);
}
else
list=map.get(pid);
CodeItem option=new CodeItem().setValue(DataObject.getStringValue(item.get(this.getValueProp()), DataObject.getStringValue(item.get("id"),null)))
.setId(DataObject.getStringValue(item.get(this.getValueProp()), DataObject.getStringValue(item.get("id"),null)))
.setDisabled(DataObject.getBooleanValue(item.get(this.getDisabledProp()),false)|| DataObject.getBooleanValue(item.get(this.getExpiredProp()),false))
.setFilter(DataObject.getStringValue(item.get(this.getFilterProp()),null)).setIconClass(DataObject.getStringValue(item.get(this.getIconClassProp()),null))
.setLabel(DataObject.getStringValue(item.get(this.getLabelProp()), DataObject.getStringValue(item.get("text"),"")))
.setParent(DataObject.getStringValue(item.get(this.getParentProp()), DataObject.getStringValue(item.get("pvalue"),""))).setExtension(extension);
if(option.getValue().equals(subCode))
subOption=option;
if(StringUtils.isEmpty(filter)||option.getFilterSet().contains(filter)) {
alllist.add(option);
list.add(option);
}
}
if(subOption!=null)
{
List<CodeItem> codeItemTreeList = loop(map, (StringUtils.isEmpty(subCode))?"_root":subCode);
codeItemTreeList.add(0,subOption.setParent(null));
this.setOptions(codeItemTreeList);
}
else
this.setOptions(alllist);
return this;
}
public List<Map> unfoldList(List<Map> nodes, String parent)
{
List<Map> unfoldList = new ArrayList<>();
for(Map item:nodes)
{
if((!StringUtils.isEmpty(parent))&&StringUtils.isEmpty(DataObject.getStringValue(item.get(this.getParentProp()), DataObject.getStringValue(item.get("pvalue"),null))))
item.put(this.getParentProp(),parent);
String value = DataObject.getStringValue(item.get(this.getValueProp()), DataObject.getStringValue(item.get("id"),null));
unfoldList.add(item);
Object child=item.get(this.getChildrenProp());
if(!ObjectUtils.isEmpty(child))
{
if(child instanceof List && ((List) child).get(0) instanceof Map)
unfoldList.addAll(unfoldList((List)child,value));
item.remove(this.getChildrenProp());
}
}
return unfoldList;
}
public List<CodeItem> loop(Map<String, List<CodeItem>> listCodeItem, Object parentValue) {
List<CodeItem> trees = new ArrayList<CodeItem>();
if(listCodeItem.containsKey(parentValue)) {
for (CodeItem codeItem : listCodeItem.get(parentValue)) {
trees.add(codeItem);
List<CodeItem> childCodeItem = loop(listCodeItem, codeItem.getValue());
if (childCodeItem.size() > 0)
trees.addAll(childCodeItem);
}
}
return trees;
}
}
package cn.ibizlab.util.dict;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.springframework.util.StringUtils;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Option
{
private String id;
private Object value;
private String label;
private List<Option> children;
private String iconClass;
private String filter;
private Boolean disabled;
@JsonIgnore
@JSONField(serialize = false)
private String parent;
private Map<String, Object> extension;
@JsonIgnore
@JSONField(serialize = false)
public Set<String> getFilterSet()
{
Set<String> set=new HashSet<>();
if(!StringUtils.isEmpty(filter))
for(String str:filter.split(";|,"))
set.add(str);
return set;
}
}
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 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;
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.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 com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class DataObject {
final static public DateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final static public DateFormat datetimeFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
final static public DateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");
final static public String getStringValue(Object objValue, String strDefault) {
if (objValue == null) {
return strDefault;
}
if (objValue instanceof String) {
return (String) objValue;
}
if (objValue instanceof java.sql.Timestamp||objValue instanceof java.sql.Date||objValue instanceof java.util.Date) {
String rt=datetimeFormat.format(objValue);
if(rt.endsWith(" 00:00:00")) {
rt=dayFormat.format(objValue);
}
else if(rt.endsWith(":00")) {
rt=datetimeFormat2.format(objValue);
}
return rt;
}
return objValue.toString();
}
public static <T> Object objectValueOf(Class<T> type,Object fieldValue) {
if(fieldValue==null) {
return null;
}
Object resultValue=fieldValue;
String targetType=type.getSimpleName();
if(targetType.equalsIgnoreCase(fieldValue.getClass().getSimpleName())){
return resultValue;
}
if(targetType.equals("Boolean")){
resultValue=getBooleanValue(fieldValue,false);
}
else if(targetType.equals("Character")){
resultValue=getCharacterValue(fieldValue,null);
}
else if(targetType.equals("Byte")){
resultValue=getBinaryValue(fieldValue,null);
}
else if(targetType.equals("Short")){
resultValue=Short.valueOf(fieldValue.toString());
}
else if(targetType.equals("Integer")){
resultValue= getIntegerValue(fieldValue,null);
}
else if(targetType.equals("Long")){
resultValue=getLongValue(fieldValue,null);
}
else if(targetType.equals("Float")){
resultValue= getFloatValue(fieldValue,null);
}
else if(targetType.equals("Double")){
resultValue= getDoubleValue(fieldValue,null);
}
else if(targetType.equals("BigDecimal")){
resultValue= getBigDecimalValue(fieldValue,null);
}
else if(targetType.equals("BigInteger")){
resultValue= getBigIntegerValue(fieldValue,null);
}
else if(targetType.equals("Timestamp")){
resultValue= getTimestampValue(fieldValue,null);
}
else if(targetType.equals("String")) {
resultValue= getStringValue(fieldValue,null);
}
if(resultValue==null) {
return null;
}
return resultValue;
}
public static <T> T valueOf(Class<T> type,Object fieldValue) {
return (T)objectValueOf(type,fieldValue);
}
final static public JSONObject getJSONObjectValue(Object objValue, JSONObject jDefault) {
if (objValue == null) {
return jDefault;
}
if(objValue instanceof JSONObject) {
return (JSONObject)objValue;
}
String strValue = objValue.toString();
try {
return JSONObject.parseObject(strValue);
}
catch (Exception ex)
{
return jDefault;
}
}
final static public JSONArray getJSONArrayValue(Object objValue, JSONArray jDefault) {
if (objValue == null) {
return jDefault;
}
if(objValue instanceof JSONArray) {
return (JSONArray)objValue;
}
String strValue = objValue.toString();
try {
return JSONArray.parseArray(strValue);
}
catch (Exception ex)
{
return jDefault;
}
}
final static public List<String> getListValue(Object objValue) {
if (objValue == null) {
return new ArrayList<String>();
}
JSONArray arr=(getJSONArrayValue(objValue,null));
if(arr!=null)
{
List<String> chk1=new ArrayList<>();
for(int i=0;i<arr.size();i++)
{
if(arr.get(i) instanceof String) {
chk1.add(arr.getString(i));
}
}
return chk1;
}
else
{
return new ArrayList<String>();
}
}
final static public Boolean getBooleanValue(Object objValue,Boolean bDefault) {
if (objValue == null) {
return bDefault;
}
if (objValue instanceof Boolean) {
return (Boolean) objValue;
}
return objValue.toString().equalsIgnoreCase("true")||objValue.toString().equals("1")||objValue.toString().equals("y");
}
final static public char[] getCharacterValue(Object objValue,char[] cDefault) {
if (objValue == null) {
return cDefault;
}
return objValue.toString().toCharArray();
}
final static public Double getDoubleValue(Object objValue,Double dDefault) {
if (objValue == null) {
return dDefault;
}
if (objValue instanceof Double) {
return (Double) objValue;
}
String strValue = objValue.toString();
if (StringUtils.isEmpty(strValue)) {
return null;
}
strValue = strValue.replace(",", "");
return Double.parseDouble(strValue);
}
final static public int getIntegerValue( Object objValue, Integer nDefault) {
if (objValue == null) {
return nDefault;
}
if(objValue instanceof Integer) {
return (Integer)objValue;
}
if (objValue instanceof Double) {
return ((Double) objValue).intValue();
}
if (objValue instanceof BigDecimal) {
return ((BigDecimal) objValue).intValue();
}
String strValue = objValue.toString();
if(StringUtils.isEmpty(strValue)) {
return nDefault;
}
strValue = strValue.replace(",", "");
return Integer.parseInt(strValue);
}
final static public Float getFloatValue( Object objValue, Float fDefault) {
if (objValue == null) {
return fDefault;
}
try {
if(objValue instanceof Float) {
return (Float)objValue;
}
String strValue = objValue.toString();
if(StringUtils.isEmpty(strValue)) {
return fDefault;
}
strValue = strValue.replace(",", "");
return Float.parseFloat(strValue);
} catch (Exception ex) {
return fDefault;
}
}
final static public BigDecimal getBigDecimalValue( Object objValue, BigDecimal fDefault) {
if (objValue == null) {
return fDefault;
}
try {
if(objValue instanceof BigDecimal){
return (BigDecimal)(objValue);
}
if(objValue instanceof Double){
return BigDecimal.valueOf((Double)objValue);
}
if(objValue instanceof Long){
return BigDecimal.valueOf((Long)objValue);
}
String strValue = objValue.toString();
if(StringUtils.isEmpty(strValue)) {
return fDefault;
}
strValue = strValue.replace(",", "");
return BigDecimal.valueOf(Double.parseDouble(strValue));
} catch (Exception ex) {
return fDefault;
}
}
final static public BigInteger getBigIntegerValue( Object objValue, BigInteger fDefault) {
if (objValue == null) {
return fDefault;
}
try {
if(objValue instanceof BigInteger){
return (BigInteger)(objValue);
}
else {
Long l=getLongValue(objValue,null);
if(l!=null) {
return BigInteger.valueOf(l);
}
}
} catch (Exception ex) {
}
return fDefault;
}
final static public Long getLongValue( Object objValue, Long nDefault) {
if (objValue == null) {
return nDefault;
}
try {
if (objValue instanceof Long) return (Long) objValue;
if (objValue instanceof Integer) {
return ((Integer) objValue).longValue();
}
if (objValue instanceof Double) {
return ((Double) objValue).longValue();
}
if (objValue instanceof BigDecimal) {
return ((BigDecimal) objValue).longValue();
}
String strValue = objValue.toString();
if(StringUtils.isEmpty(strValue)) {
return nDefault;
}
strValue = strValue.replace(",", "");
return Long.parseLong(strValue);
} catch (Exception ex) {
return nDefault;
}
}
final static public byte[] getBinaryValue(Object objValue, byte[] def) {
if (objValue == null) {
return def;
}
if(objValue instanceof byte[]){
return (byte[])objValue;
}
if (objValue instanceof String){
return Base64.getDecoder().decode((String) objValue);
}
return def;
}
/**
* 转换对象值到时间值
*
* @param objValue
* @return
* @
*/
final static public java.sql.Timestamp getTimestampValue(Object objValue,java.sql.Timestamp tDefault) {
if (objValue == null) {
return tDefault;
}
if (objValue instanceof java.sql.Timestamp) {
java.sql.Timestamp ti = (java.sql.Timestamp) objValue;
return ti;
}
if (objValue instanceof java.sql.Date) {
java.sql.Date date = (java.sql.Date) objValue;
return new java.sql.Timestamp(date.getTime());
}
if (objValue instanceof java.util.Date) {
java.util.Date date = (java.util.Date) objValue;
return new java.sql.Timestamp(date.getTime());
}
if (objValue instanceof String) {
String strValue = (String) objValue;
strValue = strValue.trim();
if (StringUtils.isEmpty(strValue)) {
return null;
}
try {
java.util.Date date = parse((String) objValue);
return new java.sql.Timestamp(date.getTime());
}
catch (Exception ex)
{
return tDefault;
}
}
if(objValue instanceof Long)
{
Long lValue = (Long)objValue;
return new java.sql.Timestamp(lValue);
}
if(objValue instanceof Integer)
{
int lValue = (int)objValue;
return new java.sql.Timestamp(lValue);
}
return tDefault;
}
public static Object testDateTime(String strInput) throws Exception{
return testDateTime(strInput, null);
}
/**
* 转换文本值到日期时间
*
* @param strInput
* @param timeZone
* @return
* @
*/
public static Object testDateTime(String strInput, TimeZone timeZone) throws Exception{
if (StringUtils.isEmpty(strInput)) {
return null;
}
Date dtDate = parse(strInput, timeZone);
java.sql.Timestamp retDate = new java.sql.Timestamp(dtDate.getTime());
return retDate;
}
/**
* 转换字符串到时间对象
*
* @param strTimeString
* @return
* @throws ParseException
* @
*/
public static Date parse(String strTimeString) throws ParseException, Exception {
return parse(strTimeString, null);
}
/**
* 分析时间串
*
* @param strTimeString MM/dd/yy yy-MM-dd HH:mm:ss 格式
* @param timeZone
* @return
* @throws ParseException
* @
*/
public static Date parse(String strTimeString, TimeZone timeZone) throws ParseException, Exception {
strTimeString = strTimeString.trim();
if(StringUtils.isEmpty(strTimeString)){
throw new Exception("unknown date(time) string");
}
if(strTimeString.indexOf("Z")!=-1){
//有时区
String[] parts = strTimeString.split("[Z]");
if(parts.length>=1){
strTimeString = parts[0];
}
if(parts.length>=2){
if(timeZone == null){
if(!StringUtils.isEmpty(parts[1])){
timeZone = TimeZone.getTimeZone(parts[1]);
}
}
}
}
// 判断是长数据还是短数据
String strPart[] = null;
if(strTimeString.indexOf("T")!=-1){
strPart = strTimeString.split("[T]");
}
else{
strPart = strTimeString.split(" ");
}
if (strPart.length == 2) {
// 两个部分
String strDate = "";
String strTime = "";
if (strPart[0].indexOf(":") != -1) {
strTime = strPart[0];
strDate = strPart[1];
} else {
strTime = strPart[1];
strDate = strPart[0];
}
strDate = strDate.trim();
strTime = strTime.trim();
strDate = getFormatDateString(strDate);
strTime = getFormatTimeString(strTime);
DateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (timeZone != null) {
dtFormat.setTimeZone(timeZone);
}
return dtFormat.parse(strDate + " " + strTime);
} else {
// 一个部分
if (strTimeString.indexOf(":") != -1) {
// 时间
strTimeString = getFormatTimeString(strTimeString);
DateFormat dtFormat = new SimpleDateFormat("HH:mm:ss");
if (timeZone != null) {
dtFormat.setTimeZone(timeZone);
}
return dtFormat.parse(strTimeString);
} else {
// 作为日期处理
strTimeString = getFormatDateString(strTimeString);
DateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd");
if (timeZone != null) {
dtFormat.setTimeZone(timeZone);
}
return dtFormat.parse(strTimeString);
}
}
}
/**
* 获取时间格式化串
*
* @param strOrigin
* @return
*/
private static String getFormatTimeString(String strOrigin) {
int nDotPos = strOrigin.indexOf(".");
if (nDotPos != -1) {
strOrigin = strOrigin.substring(0, nDotPos);
}
Object Time[] = new Object[3];
Time[0] = 0;
Time[1] = 0;
Time[2] = 0;
String timepart[] = strOrigin.split(":");
int nTimePartLength = timepart.length;
if (nTimePartLength > 3) {
nTimePartLength = 3;
}
for (int i = 0; i < nTimePartLength; i++) {
Time[i] = Integer.parseInt(timepart[i]);
}
return String.format("%1$02d:%2$02d:%3$02d", Time);
}
/**
* 获取时日期格式化串
*
* @param strOrigin
* @return
* @
*/
private static String getFormatDateString(String strOrigin) throws Exception{
return getFormatDateString(strOrigin, true);
}
/**
* 获取时日期格式化串
*
* @param strOrigin
* @param bAdv
* @return
* @
*/
private static String getFormatDateString(String strOrigin, boolean bAdv) throws Exception{
Object Date[] = new Object[3];
Date[0] = 1970;
Date[1] = 1;
Date[2] = 1;
if (strOrigin.indexOf("-") != -1) {
String datePart[] = strOrigin.split("-");
if (datePart.length >= 1) {
Date[0] = Integer.parseInt(datePart[0]);
}
if (datePart.length >= 2) {
Date[1] = Integer.parseInt(datePart[1]);
}
if (datePart.length >= 3) {
Date[2] = Integer.parseInt(datePart[2]);
}
}
else if (strOrigin.indexOf("/") != -1) {
String datePart[] = strOrigin.split("/");
if (datePart.length >= 1) {
Date[1] = Integer.parseInt(datePart[0]);
}
if (datePart.length >= 2) {
Date[2] = Integer.parseInt(datePart[1]);
}
if (datePart.length >= 3) {
Date[0] = Integer.parseInt(datePart[2]);
}
} else {
if (bAdv) {
strOrigin = strOrigin.replace(".", "-");
strOrigin = strOrigin.replace("日", "");
strOrigin = strOrigin.replace("天", "");
strOrigin = strOrigin.replace("年", "-");
strOrigin = strOrigin.replace("月", "-");
return getFormatDateString(strOrigin, false);
} else
throw new Exception("无法识别的时间字符串,"+strOrigin);
}
return String.format("%1$04d-%2$02d-%3$02d", Date);
}
public static Timestamp getBeginDate()
{
Calendar cl=Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
cl.set(1900,1,1);
return new Timestamp(cl.getTime().getTime());
}
public static Timestamp getEndDate()
{
Calendar cl=Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
cl.set(2100,12,31,23,59,59);
return new Timestamp(cl.getTime().getTime());
}
public static Timestamp getNow()
{
Calendar cl=Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
return new Timestamp(cl.getTime().getTime());
}
}
package cn.ibizlab.util.helper;
import java.util.regex.PatternSyntaxException;
/**
* Copy from class sun.nio.fs.Globs
*/
public class Globs {
private Globs() { }
private static final String regexMetaChars = ".^$+{[]|()";
private static final String globMetaChars = "\\*?[{";
private static boolean isRegexMeta(char c) {
return regexMetaChars.indexOf(c) != -1;
}
private static boolean isGlobMeta(char c) {
return globMetaChars.indexOf(c) != -1;
}
private static char EOL = 0; //TBD
private static char next(String glob, int i) {
if (i < glob.length()) {
return glob.charAt(i);
}
return EOL;
}
/**
* Creates a regex pattern from the given glob expression.
*
* @throws PatternSyntaxException
*/
private static String toRegexPattern(String globPattern, boolean isDos) {
boolean inGroup = false;
StringBuilder regex = new StringBuilder("^");
int i = 0;
while (i < globPattern.length()) {
char c = globPattern.charAt(i++);
switch (c) {
case '\\':
// escape special characters
if (i == globPattern.length()) {
throw new PatternSyntaxException("No character to escape",
globPattern, i - 1);
}
char next = globPattern.charAt(i++);
if (isGlobMeta(next) || isRegexMeta(next)) {
regex.append('\\');
}
regex.append(next);
break;
case '/':
if (isDos) {
regex.append("\\\\");
} else {
regex.append(c);
}
break;
case '[':
// don't match name separator in class
if (isDos) {
regex.append("[[^\\\\]&&[");
} else {
regex.append("[[^/]&&[");
}
if (next(globPattern, i) == '^') {
// escape the regex negation char if it appears
regex.append("\\^");
i++;
} else {
// negation
if (next(globPattern, i) == '!') {
regex.append('^');
i++;
}
// hyphen allowed at start
if (next(globPattern, i) == '-') {
regex.append('-');
i++;
}
}
boolean hasRangeStart = false;
char last = 0;
while (i < globPattern.length()) {
c = globPattern.charAt(i++);
if (c == ']') {
break;
}
if (c == '/' || (isDos && c == '\\')) {
throw new PatternSyntaxException("Explicit 'name separator' in class",
globPattern, i - 1);
}
// TBD: how to specify ']' in a class?
if (c == '\\' || c == '[' ||
c == '&' && next(globPattern, i) == '&') {
// escape '\', '[' or "&&" for regex class
regex.append('\\');
}
regex.append(c);
if (c == '-') {
if (!hasRangeStart) {
throw new PatternSyntaxException("Invalid range",
globPattern, i - 1);
}
if ((c = next(globPattern, i++)) == EOL || c == ']') {
break;
}
if (c < last) {
throw new PatternSyntaxException("Invalid range",
globPattern, i - 3);
}
regex.append(c);
hasRangeStart = false;
} else {
hasRangeStart = true;
last = c;
}
}
if (c != ']') {
throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
}
regex.append("]]");
break;
case '{':
if (inGroup) {
throw new PatternSyntaxException("Cannot nest groups",
globPattern, i - 1);
}
regex.append("(?:(?:");
inGroup = true;
break;
case '}':
if (inGroup) {
regex.append("))");
inGroup = false;
} else {
regex.append('}');
}
break;
case ',':
if (inGroup) {
regex.append(")|(?:");
} else {
regex.append(',');
}
break;
case '*':
if (next(globPattern, i) == '*') {
// crosses directory boundaries
regex.append(".*");
i++;
} else {
// within directory boundary
if (isDos) {
regex.append("[^\\\\]*");
} else {
regex.append("[^/]*");
}
}
break;
case '?':
if (isDos) {
regex.append("[^\\\\]");
} else {
regex.append("[^/]");
}
break;
default:
if (isRegexMeta(c)) {
regex.append('\\');
}
regex.append(c);
}
}
if (inGroup) {
throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
}
return regex.append('$').toString();
}
public static String toUnixRegexPattern(String globPattern) {
return toRegexPattern(globPattern, false);
}
public static String toWindowsRegexPattern(String globPattern) {
return toRegexPattern(globPattern, true);
}
}
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.job;
import cn.ibizlab.util.client.IBZUAAFeignClient;
import cn.ibizlab.util.client.IBZLiteFeignClient;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.DigestUtils;
import java.io.InputStream;
import java.util.*;
/**
* 权限:向uaa同步当前系统菜单、权限资源任务类
*/
@Slf4j
@Component
@ConditionalOnProperty( name = "ibiz.enablePermissionValid", havingValue = "true")
public class PermissionSyncJob implements ApplicationRunner {
@Value("${ibiz.systemid:ibznotify}")
private String systemId;
@Value("${ibiz.systemname:ibznotify}")
private String systemName;
@Autowired
@Lazy
private IBZUAAFeignClient uaaClient;
@Autowired
@Lazy
IBZLiteFeignClient liteClient;
@Override
public void run(ApplicationArguments args) {
try {
Thread.sleep(10000);
InputStream permission = this.getClass().getResourceAsStream("/permission/systemResource.json"); //权限资源
if (!ObjectUtils.isEmpty(permission)) {
String strPermission = IOUtils.toString(permission, "UTF-8");
JSONObject system = new JSONObject() {{
put("pssystemid", systemId);
put("pssystemname", systemName);
put("sysstructure", JSONObject.parseObject(strPermission));
put("md5check", DigestUtils.md5DigestAsHex(strPermission.getBytes()));
}};
if (uaaClient.syncSysAuthority(system)) {
log.info("向[uaa]同步系统资源成功");
} else {
log.error("向[uaa]同步系统资源失败");
}
}
} catch (Exception ex) {
log.error("向[uaa]同步系统资源失败,请检查[uaa]服务是否正常运行! {}", ex.getMessage());
}
try {
InputStream model = this.getClass().getResourceAsStream("/sysmodel/ibznotify.json"); //系统模型
if (!ObjectUtils.isEmpty(model)) {
String strModel = IOUtils.toString(model, "UTF-8");
if (liteClient.syncSysModel(JSONObject.parseObject(strModel))) {
log.info("向[lite]同步模型成功");
} else {
log.error("向[lite]同步模型失败");
}
}
} catch (Exception ex) {
log.error("向[lite]同步系统模型失败,请检查[lite]服务是否正常运行! {}", ex.getMessage());
}
}
}
\ No newline at end of file
package cn.ibizlab.util.rest;
import cn.ibizlab.util.security.AuthenticationInfo;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.security.AuthorizationLogin;
import cn.ibizlab.util.security.AuthTokenUtil;
import cn.ibizlab.util.service.AuthenticationUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@RestController
@RequestMapping("/")
@ConditionalOnProperty( name = "ibiz.enablePermissionValid", havingValue = "false")
public class AuthenticationController
{
@Value("${ibiz.jwt.header:Authorization}")
private String tokenHeader;
@Autowired
private AuthTokenUtil jwtTokenUtil;
@Autowired
private AuthenticationUserService userDetailsService;
@PostMapping(value = "${ibiz.auth.path:v7/login}")
public ResponseEntity<AuthenticationInfo> login(@Validated @RequestBody AuthorizationLogin authorizationLogin){
userDetailsService.resetByUsername(authorizationLogin.getUsername());
final AuthenticationUser authuserdetail = userDetailsService.loadUserByLogin(authorizationLogin.getUsername(),authorizationLogin.getPassword());
// 生成令牌
final String token = jwtTokenUtil.generateToken(authuserdetail);
// 返回 token
return ResponseEntity.ok().body(new AuthenticationInfo(token,authuserdetail));
}
@GetMapping(value = "${ibiz.auth.account:ibizutil/account}")
public ResponseEntity<AuthenticationUser> getUserInfo(){
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
AuthenticationUser authuserdetail=new AuthenticationUser();
if(userDetails==null){
throw new RuntimeException("未能获取用户信息");
}
else if(userDetails instanceof AuthenticationUser ) {
authuserdetail= (AuthenticationUser)userDetails;
}
else {
authuserdetail= userDetailsService.loadUserByUsername(userDetails.getUsername());
}
return ResponseEntity.ok().body(authuserdetail);
}
}
......@@ -17,63 +17,8 @@ import java.util.*;
@RestController
@RequestMapping(value = "")
public class AppController {
public class ConfigController {
@Value("${ibiz.enablePermissionValid:false}")
boolean enablePermissionValid; //是否开启权限校验
@Value("${ibiz.systemid:ibznotify}")
private String systemId;
@Autowired
private AuthenticationUserService userDetailsService;
@RequestMapping(method = RequestMethod.GET, value = "/appdata")
public ResponseEntity<JSONObject> getAppData() {
JSONObject appData = new JSONObject() ;
Set<String> appMenu = new HashSet();
Set<String> uniRes = new HashSet();
AuthenticationUser curUser = AuthenticationUser.getAuthenticationUser();
if(enablePermissionValid){
Collection<GrantedAuthority> authorities=curUser.getAuthorities();
Iterator it = authorities.iterator();
while(it.hasNext()) {
GrantedAuthority authority = (GrantedAuthority)it.next();
String strAuthority=authority.getAuthority();
if(strAuthority.startsWith("UNIRES_"+systemId)) {
uniRes.add(strAuthority.substring(systemId.length()+8));
}
else if(strAuthority.startsWith("APPMENU_"+systemId)){
appMenu.add(strAuthority.substring(systemId.length()+9));
}
}
}
Map<String,Object> context = new HashMap<>();
context.putAll(curUser.getSessionParams());
context.put("srfusername",curUser.getPersonname());
appData.put("context",context);
appData.put("unires",uniRes);
appData.put("appmenu",appMenu);
appData.put("enablepermissionvalid",enablePermissionValid);
if(curUser.getSuperuser()==1){
appData.put("enablepermissionvalid",false);
}
else{
appData.put("enablepermissionvalid",enablePermissionValid);
}
fillAppData(appData);
return ResponseEntity.status(HttpStatus.OK).body(appData);
}
@RequestMapping(method = RequestMethod.GET, value = "${ibiz.auth.logoutpath:v7/logout}")
public void logout() {
if(AuthenticationUser.getAuthenticationUser()!=null){
userDetailsService.resetByUsername(AuthenticationUser.getAuthenticationUser().getUsername());
}
}
@Autowired
private IBZConfigService ibzConfigService;
......
package cn.ibizlab.util.rest;
import cn.ibizlab.util.domain.FileItem;
import cn.ibizlab.util.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
@Slf4j
@RestController
@RequestMapping("/")
public class FileController
{
@Autowired
private FileService fileService;
@PostMapping(value = "${ibiz.file.uploadpath:ibizutil/upload}")
public ResponseEntity<FileItem> upload(@RequestParam("file") MultipartFile multipartFile){
return ResponseEntity.ok().body(fileService.saveFile(multipartFile));
}
private final String defaultdownloadpath="ibizutil/download/{id}";
@GetMapping(value = "${ibiz.file.downloadpath:"+defaultdownloadpath+"}")
@ResponseStatus(HttpStatus.OK)
public void download(@PathVariable String id, HttpServletResponse response){
File file= fileService.getFile(id);
response.setHeader("Content-Disposition", "attachment;filename="+getFileName(file.getName()));
this.sendRespose(response, file);
}
protected void sendRespose(HttpServletResponse response, File file){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(file));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
}
catch (Exception e) {
//throw e;
}
finally {
if (bis != null) {
try {
bis.close();
}
catch (IOException e) {
}
}
if (bos != null) {
try {
bos.close();
}
catch (IOException e) {
}
}
}
}
protected String getFileName(String fileName){
try {
return new String(fileName.getBytes("utf-8"),"iso8859-1");//防止中文乱码
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return fileName;
}
}
\ No newline at end of file
package cn.ibizlab.util.security;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.SneakyThrows;
import cn.ibizlab.util.annotation.DEField;
import cn.ibizlab.util.domain.EntityBase;
import cn.ibizlab.util.enums.DEPredefinedFieldType;
import cn.ibizlab.util.filter.QueryWrapperContext;
import cn.ibizlab.util.helper.DEFieldCacheMap;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.function.Consumer;
/**
* spring security 权限管理类
* 重写权限控制方法
*/
@Component
public class AuthPermissionEvaluator implements PermissionEvaluator {
@Value("${ibiz.enablePermissionValid:false}")
boolean enablePermissionValid; //是否开启权限校验
/**
* 服务接口鉴权
* @param authentication 用户
* @param entity 实体
* @param action 操作
* @return
*/
@Override
@SneakyThrows
public boolean hasPermission(Authentication authentication, Object entity, Object action) {
if(!enablePermissionValid){
return true;
}
Object principal = authentication.getPrincipal();
if(ObjectUtils.isEmpty(principal)){
return false;
}
AuthenticationUser authenticationUser= (AuthenticationUser) authentication.getPrincipal();
if(authenticationUser.getSuperuser()==1){
return true;
}
String strAction=String.valueOf(action);
Set<String> userAuthorities = getAuthorities(authentication,strAction);
if(userAuthorities.size()==0){
return false;
}
if(isAllData(strAction,userAuthorities)){
return true;
}
if(entity instanceof ArrayList){
List<EntityBase> entities= (List<EntityBase>) entity;
for(EntityBase entityBase: entities){
boolean result=actionValid(entityBase, strAction ,userAuthorities,authenticationUser);
if(!result){
return false;
}
}
}
else if (entity instanceof QueryWrapperContext){
QueryWrapperContext queryWrapperContext= (QueryWrapperContext) entity;
setPermissionCondToSearchContext(getEntity(queryWrapperContext),queryWrapperContext,userAuthorities,authenticationUser);
}
else{
EntityBase entityBase= (EntityBase) entity;
return actionValid(entityBase , strAction ,userAuthorities,authenticationUser);
}
return true;
}
/**
* 获取实体信息
* @param qc
* @return
*/
@SneakyThrows
private EntityBase getEntity(QueryWrapperContext qc){
EntityBase entity=null;
Type type =qc.getClass().getGenericSuperclass();
if(type instanceof ParameterizedType){
ParameterizedType parameterizedType= (ParameterizedType) qc.getClass().getGenericSuperclass();
Type [] typeArr= parameterizedType.getActualTypeArguments();
if(typeArr.length>0){
Class<EntityBase> entityClass = (Class) typeArr[0];
return entityClass.newInstance();
}
}
return entity;
}
/**
* 在searchContext中拼接权限条件
* @param entity 实体
* @param qc 查询上下文
* @param userAuthorities 用户权限
* @param authenticationUser 当前用户
*/
@SneakyThrows
private void setPermissionCondToSearchContext(EntityBase entity, QueryWrapperContext qc , Set<String> userAuthorities ,AuthenticationUser authenticationUser){
if(entity==null){
return ;
}
Map<String,String> permissionField=getPermissionField(entity);//获取组织、部门预置属性
String orgField=permissionField.get("orgfield");
String orgDeptField=permissionField.get("orgsecfield");
String createManField=permissionField.get("createmanfield");
Map<String, Set<String>> userInfo = authenticationUser.getOrgInfo();
Set<String> orgParent = userInfo.get("parentorg");
Set<String> orgChild = userInfo.get("suborg");
Set<String> orgDeptParent = userInfo.get("parentdept");
Set<String> orgDeptChild = userInfo.get("subdept");
Set<String> userOrg = new HashSet<>();
Set<String> userOrgDept = new HashSet<>();
Set<String> userCreateMan = new HashSet<>();
for(String authority:userAuthorities){
if(authority.endsWith("curorg")){ //本单位
userOrg.add(authenticationUser.getOrgid());
}
else if(authority.endsWith("porg")){//上级单位
userOrg.addAll(orgParent);
}
else if(authority.endsWith("sorg")){//下级单位
userOrg.addAll(orgChild);
}
else if(authority.endsWith("curorgdept")){//本部门
userOrgDept.add(authenticationUser.getMdeptid());
}
else if(authority.endsWith("porgdept")){//上级部门
userOrgDept.addAll(orgDeptParent);
}
else if(authority.endsWith("sorgdept")){//下级部门
userOrgDept.addAll(orgDeptChild);
}
else if (authority.endsWith("createman")){
userCreateMan.add(authority);
}
}
if(userOrg.size()==0 && userOrgDept.size()==0 && userCreateMan.size()==0){
qc.getSelectCond().apply("1<>1");
}
else{
Consumer<QueryWrapper> consumer = qw -> {
if(userOrg.size()>0){
Consumer<QueryWrapper> org = orgQw -> {
orgQw.in(orgField,userOrg);
};
qw.or(org);
}
if(userOrgDept.size()>0){
Consumer<QueryWrapper> dept = deptQw -> {
deptQw.in(orgDeptField,userOrgDept);
};
qw.or(dept);
}
if(userCreateMan.size()>0){
Consumer<QueryWrapper> createMan = createManQw -> {
createManQw.eq(createManField,authenticationUser.getUserid());
};
qw.or(createMan);
}
};
qc.getSelectCond().and(consumer);
}
}
@Override
public boolean hasPermission(Authentication authentication, Serializable id, String action, Object params) {
return true;
}
/**
* 获取用户权限资源
* @param authentication
* @param action
* @return
*/
private Set<String> getAuthorities(Authentication authentication , String action){
Collection authorities=authentication.getAuthorities();
Set<String> userAuthorities = new HashSet();
Iterator it = authorities.iterator();
while(it.hasNext()) {
GrantedAuthority authority = (GrantedAuthority)it.next();
if(authority.getAuthority().contains(action)){
userAuthorities.add(authority.getAuthority());
}
}
return userAuthorities;
}
/**
* 是否为全部数据
* @param action
* @param entityDataRange
* @return
*/
private boolean isAllData(String action , Set<String> entityDataRange) {
for(String dataRange : entityDataRange ){
if(dataRange.endsWith(String.format("%s-all",action))){
return true;
}
}
return false;
}
/**
* 实体行为权限校验
* @param entity
* @param userAuthorities
* @return
*/
private boolean actionValid(EntityBase entity, String action , Set<String> userAuthorities ,AuthenticationUser authenticationUser){
Map<String,String> permissionField=getPermissionField(entity);//获取组织、部门预置属性
String orgField=permissionField.get("orgfield");
String orgDeptField=permissionField.get("orgsecfield");
String createManField=permissionField.get("createmanfield");
Map<String, Set<String>> userInfo = authenticationUser.getOrgInfo();
Set<String> orgParent = userInfo.get("parentorg");
Set<String> orgChild = userInfo.get("suborg");
Set<String> orgDeptParent = userInfo.get("parentdept");
Set<String> orgDeptChild = userInfo.get("subdept");
Object orgFieldValue=entity.get(orgField);
Object orgDeptFieldValue=entity.get(orgDeptField);
Object crateManFieldValue=entity.get(createManField);
Set<String> userOrg = new HashSet<>();
Set<String> userOrgDept = new HashSet<>();
for(String authority:userAuthorities){
if(authority.endsWith("curorg")){ //本单位
userOrg.add(authenticationUser.getOrgid());
}
else if(authority.endsWith("porg")){//上级单位
userOrg.addAll(orgParent);
}
else if(authority.endsWith("sorg")){//下级单位
userOrg.addAll(orgChild);
}
else if(authority.endsWith("curorgdept")){//本部门
userOrgDept.add(authenticationUser.getMdeptid());
}
else if(authority.endsWith("porgdept")){//上级部门
userOrgDept.addAll(orgDeptParent);
}
else if(authority.endsWith("sorgdept")){//下级部门
userOrgDept.addAll(orgDeptChild);
}
}
if(action.endsWith("Create") || action.endsWith("Save")){
if(!ObjectUtils.isEmpty(orgFieldValue) && !userOrg.contains(orgFieldValue)){
return false;
}
if(!ObjectUtils.isEmpty(orgDeptFieldValue) && !userOrgDept.contains(orgDeptFieldValue)){
return false;
}
if(!ObjectUtils.isEmpty(crateManFieldValue) && !authenticationUser.getUserid().equals(crateManFieldValue)){
return false;
}
return true;
}
else{
if(!ObjectUtils.isEmpty(orgFieldValue) && userOrg.contains(orgFieldValue)){
return true;
}
if(!ObjectUtils.isEmpty(orgDeptFieldValue) && userOrgDept.contains(orgDeptFieldValue)){
return true;
}
if(!ObjectUtils.isEmpty(crateManFieldValue) && authenticationUser.getUserid().equals(crateManFieldValue)){
return true;
}
return false;
}
}
/**
* 获取实体权限字段 orgid/orgsecid
* @param entityBase
* @return
*/
private Map<String,String> getPermissionField(EntityBase entityBase){
Map<String,String> permissionFiled=new HashMap<>();
String orgField="orgid"; //组织属性
String orgDeptField="orgsectorid"; //部门属性
String createManField="createman"; //创建人属性
DEFieldCacheMap.getFieldMap(entityBase.getClass().getName());
Map <String, DEField> preFields= DEFieldCacheMap.getDEFields(entityBase.getClass()); //从缓存中获取当前类预置属性
for (Map.Entry<String,DEField> entry : preFields.entrySet()){
DEField fieldAnnotation=entry.getValue();//获取注解值
String fieldName=fieldAnnotation.name();//获取注解字段
DEPredefinedFieldType prefieldType=fieldAnnotation.preType();
if(!StringUtils.isEmpty(fieldName)){
//用户配置系统预置属性-组织机构标识
if(prefieldType==prefieldType.ORGID){
orgField=fieldName;
}
//用户配置系统预置属性-部门标识
if(prefieldType==prefieldType.ORGSECTORID){
orgDeptField=fieldName;
}
//用户配置系统预置属性-部门标识
if(prefieldType==prefieldType.CREATEMAN){
createManField=fieldName;
}
}
}
permissionFiled.put("orgfield",orgField);
permissionFiled.put("orgsecfield",orgDeptField);
permissionFiled.put("createmanfield",createManField);
return permissionFiled;
}
}
\ 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.security;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
@Component
public class AuthenticationEntryPoint implements org.springframework.security.web.AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
/**
* 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
*/
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "账号身份已过期,请重新登录。");
}
}
package cn.ibizlab.util.security;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.io.Serializable;
@Getter
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class AuthenticationInfo implements Serializable {
private String token;
private AuthenticationUser user;
public AuthenticationInfo() {
}
}
package cn.ibizlab.util.security;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.ObjectUtils;
import java.sql.Timestamp;
import java.util.*;
import com.alibaba.fastjson.JSONObject;
@Data
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class AuthenticationUser implements UserDetails
{
public AuthenticationUser(){}
/**
* 用戶标识
*/
private String userid;
/**
* 用户全局名
*/
private String username;
/**
* 用户姓名
*/
private String personname;
/**
* 登录名
*/
private String loginname;
/**
* 用户工号
*/
private String usercode;
/**
* 登录密码
*/
private String password;
/**
* 区属
*/
private String domain;
/**
* 租户
*/
private String srfdcid;
/**
* 系统标识
*/
private String srfsystemid;
/**
/**
* 动态实例标识
*/
private String srfdynainstid;
/**
* 部门标识
*/
private String mdeptid;
/**
* 部门编码
*/
private String mdeptcode;
/**
* 部门名称
*/
private String mdeptname;
/**
* 业务编码
*/
private String bcode;
/**
* 岗位标识
*/
private String postid;
/**
* 岗位代码
*/
private String postcode;
/**
* 岗位名称
*/
private String postname;
/**
* 单位标识
*/
private String orgid;
/**
* 单位编码
*/
private String orgcode;
/**
* 单位名称
*/
private String orgname;
/**
* 昵称别名
*/
private String nickname;
/**
* 邮箱
*/
private String email;
/**
* 社交账号
*/
private String avatar;
/**
* 电话
*/
private String phone;
/**
* 照片
*/
private String usericon;
/**
* 性别
*/
private String sex;
/**
* 出生日期
*/
private Timestamp birthday;
/**
* 证件号码
*/
private String certcode;
/**
* 地址
*/
private String addr;
/**
* 主题
*/
private String theme;
/**
* 字号
*/
private String fontsize;
/**
* 语言
*/
private String lang;
/**
* 备注
*/
private String memo;
/**
* 保留字段
*/
private String reserver;
/**
* 用户上下文参数
*/
private Map <String,Object> sessionParams;
/**
* 用户权限资源
*/
@JsonIgnore
private Collection<GrantedAuthority> authorities;
/**
* 是否为超级管理员
*/
private int superuser;
/**
* 用户权限资源
*/
private JSONObject permissionList;
/**
* 用户上下文参数
*/
@JsonIgnore
private Map<String,Object> userSessionParam;
/**
* 当前用户上下级组织信息
*/
private Map<String, Set<String>> orgInfo;
/**
* 上级组织
*/
private String porg;
/**
* 下级组织
*/
private String sorg;
/**
* 上级部门
*/
private String pdept;
/**
* 下级部门
*/
private String sdept;
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonIgnore
@Override
public String getPassword() {
return password;
}
@Override
public boolean isEnabled() {
return true;
}
public static AuthenticationUser getAuthenticationUser()
{
if(SecurityContextHolder.getContext()==null||SecurityContextHolder.getContext().getAuthentication()==null||SecurityContextHolder.getContext().getAuthentication().getPrincipal()==null){
return new AuthenticationUser();
}
Object userDetails = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
AuthenticationUser authuserdetail;
if(userDetails instanceof AuthenticationUser ) {
authuserdetail= (AuthenticationUser)userDetails;
}
else {
authuserdetail=new AuthenticationUser();
}
return authuserdetail;
}
public static AuthenticationUser setAuthenticationUser(String userId , String userName) {
AuthenticationUser user = new AuthenticationUser();
user.setUserid(userId);
user.setPersonname(userName);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
return user;
}
public Map <String,Object> getSessionParams()
{
if(this.sessionParams==null)
{
sessionParams = getUserSessionParam();
sessionParams.put("srfsystemid",this.getSrfsystemid());
sessionParams.put("srfpersonid", this.getUserid());
sessionParams.put("srfpersonname", this.getPersonname());
sessionParams.put("srforgsectorid", this.getMdeptid());
sessionParams.put("srforgsectorcode", this.getMdeptcode());
sessionParams.put("srforgsectorname", this.getMdeptname());
sessionParams.put("srforgid", this.getOrgid());
sessionParams.put("srforgcode", this.getOrgcode());
sessionParams.put("srforgname", this.getOrgname());
sessionParams.put("srfuserid", this.getUserid());
sessionParams.put("srfusername", this.getPersonname());
sessionParams.put("srfusermode", "");
sessionParams.put("srforgsectorbc", this.getBcode());
sessionParams.put("srfloginname", this.getLoginname());
sessionParams.put("srflocale", this.getLang());
sessionParams.put("srftimezone", "");
sessionParams.put("srfusercode", this.getUsercode());
sessionParams.put("srfporg", this.getPorg());
sessionParams.put("srfsorg", this.getSorg());
sessionParams.put("srfpdept", this.getPdept());
sessionParams.put("srfsdept", this.getSdept());
}
return this.sessionParams;
}
private Map<String, Object> getUserSessionParam() {
if(userSessionParam!=null){
return userSessionParam;
}
else{
return new HashMap<>();
}
}
public void setOrgInfo(Map<String, Set<String>> orgInfo) {
this.orgInfo = orgInfo;
if(!ObjectUtils.isEmpty(orgInfo) && !ObjectUtils.isEmpty(orgInfo.get("parentorg"))){
porg=(String.format("'%s'",String.join("','",orgInfo.get("parentorg"))));
this.getSessionParams().put("srfporg",porg);
}
if(!ObjectUtils.isEmpty(orgInfo) && !ObjectUtils.isEmpty(orgInfo.get("suborg")) ){
sorg=(String.format("'%s'",String.join("','",orgInfo.get("suborg"))));
this.getSessionParams().put("srfsorg",sorg);
}
if(!ObjectUtils.isEmpty(orgInfo) && !ObjectUtils.isEmpty(orgInfo.get("parentdept"))){
pdept=(String.format("'%s'",String.join("','",orgInfo.get("parentdept"))));
this.getSessionParams().put("srfpdept",pdept);
}
if(!ObjectUtils.isEmpty(orgInfo) && !ObjectUtils.isEmpty(orgInfo.get("subdept"))){
sdept=(String.format("'%s'",String.join("','",orgInfo.get("subdept"))));
this.getSessionParams().put("srfsdept",sdept);
}
}
public void setPermissionList(JSONObject permissionList) {
this.permissionList = permissionList;
if(authorities==null && permissionList !=null){
if(permissionList.getJSONArray("authorities")!=null){
authorities=new ArrayList<>();
permissionList.getJSONArray("authorities").
forEach(item->authorities.add(new SimpleGrantedAuthority(String.valueOf(item))));
}
}
}
}
package cn.ibizlab.util.security;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;
import javax.validation.constraints.NotBlank;
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class AuthorizationLogin
{
private String domain;
@NotBlank(message="用户名不能为空")
private String loginname;
@NotBlank(message="密码不能为空")
private String password;
public String getUsername()
{
if(!StringUtils.isEmpty(domain))
return loginname+"|"+domain;
return loginname;
}
@Override
public String toString()
{
return "AuthorizationLogin{" +
"domain='" + domain + '\'' +
", loginname='" + loginname + '\'' +
", password='××××××'}";
}
}
package cn.ibizlab.util.security;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import cn.ibizlab.util.service.AuthenticationUserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.beans.factory.annotation.Qualifier;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import org.springframework.util.StringUtils;
@Slf4j
@Component
public class AuthorizationTokenFilter extends OncePerRequestFilter {
private final AuthenticationUserService userDetailsService;
private final AuthTokenUtil authTokenUtil;
private final String tokenHeader;
private Set<String> excludesPattern = new HashSet<String>();
private PathMatcher pathMatcher = new AntPathMatcher();
public AuthorizationTokenFilter(AuthenticationUserService userDetailsService, AuthTokenUtil authTokenUtil, @Value("${ibiz.jwt.header:Authorization}") String tokenHeader) {
this.userDetailsService = userDetailsService;
this.authTokenUtil = authTokenUtil;
this.tokenHeader = tokenHeader;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
if (isExclusion(request.getRequestURI())) {
chain.doFilter(request, response);
return;
}
final String requestHeader = request.getHeader(this.tokenHeader);
String username = null;
String authToken = null;
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
authToken = requestHeader.substring(7);
try {
username = authTokenUtil.getUsernameFromToken(authToken);
} catch (ExpiredJwtException e) {
log.error(e.getMessage());
}
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (authTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
public void setExcludesPattern(String excludesPattern) {
this.excludesPattern = new HashSet(Arrays.asList(excludesPattern.split("\\s*,\\s*")));
}
public void addExcludePattern(String excludePattern) {
excludesPattern.add(excludePattern);
}
private boolean isExclusion(String requestURI) {
if (this.excludesPattern == null) {
return false;
} else {
Iterator excludeIterator = this.excludesPattern.iterator();
String pattern;
do {
if (!excludeIterator.hasNext()) {
return false;
}
pattern = (String) excludeIterator.next();
} while (!pathMatcher.match(pattern, requestURI));
return true;
}
}
}
package cn.ibizlab.util.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
@Component
@ConditionalOnExpression("(!${ibiz.enablePermissionValid:false})&&'${ibiz.auth.token.util:UAATokenUtil}'.equals('SimpleTokenUtil')")
public class SimpleTokenUtil implements AuthTokenUtil,Serializable {
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
@Value("${ibiz.jwt.secret:ibzsecret}")
private String secret;
@Value("${ibiz.jwt.expiration:7200000}")
private Long expiration;
@Value("${ibiz.jwt.header:Authorization}")
private String tokenHeader;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
return (lastPasswordReset != null && created.before(lastPasswordReset));
}
private Boolean ignoreTokenExpiration(String token) {
// here you specify tokens, for that the expiration is ignored
return false;
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
final Date created = getIssuedAtDateFromToken(token);
return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
&& (!isTokenExpired(token) || ignoreTokenExpiration(token));
}
public String refreshToken(String token) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
final Claims claims = getAllClaimsFromToken(token);
claims.setIssuedAt(createdDate);
claims.setExpiration(expirationDate);
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
AuthenticationUser user = (AuthenticationUser) userDetails;
final Date created = getIssuedAtDateFromToken(token);
return (!isTokenExpired(token) );
}
private Date calculateExpirationDate(Date createdDate) {
return new Date(createdDate.getTime() + expiration);
}
/**
* Get the login of the current user.
*
* @return the login of the current user
*/
public static Optional<String> getCurrentUserLogin() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> {
if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
return springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof String) {
return (String) authentication.getPrincipal();
}
return null;
});
}
/**
* Check if a user is authenticated.
*
* @return true if the user is authenticated, false otherwise
*/
public static boolean isAuthenticated() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> authentication.getAuthorities().stream()
.noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals("ANONYMOUS")))
.orElse(false);
}
/**
* If the current user has a specific authority (security role).
* <p>
* The name of this method comes from the isUserInRole() method in the Servlet API
*
* @param authority the authority to check
* @return true if the current user has the authority, false otherwise
*/
public static boolean isCurrentUserInRole(String authority) {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication())
.map(authentication -> authentication.getAuthorities().stream()
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority)))
.orElse(false);
}
}
package cn.ibizlab.util.security;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextHolder implements ApplicationContextAware
{
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextHolder.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
assertApplicationContext();
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanName) {
assertApplicationContext();
return (T) applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> requiredType) {
assertApplicationContext();
return applicationContext.getBean(requiredType);
}
private static void assertApplicationContext() {
if (SpringContextHolder.applicationContext == null) {
throw new RuntimeException("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!");
}
}
}
\ No newline at end of file
package cn.ibizlab.util.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Clock;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClock;
import lombok.SneakyThrows;
import cn.ibizlab.util.client.IBZUAAFeignClient;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.Serializable;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
@ConditionalOnExpression("${ibiz.enablePermissionValid:false}||'${ibiz.auth.token.util:UAATokenUtil}'.equals('UAATokenUtil')")
public class UAATokenUtil implements AuthTokenUtil, Serializable {
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
@Value("${ibiz.jwt.secret:ibzsecret}")
private String secret;
@Value("${ibiz.jwt.expiration:7200000}")
private Long expiration;
@Value("${ibiz.jwt.header:Authorization}")
private String tokenHeader;
@Autowired
private IBZUAAFeignClient uaaFeignClient;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
public Claims getAllClaimsFromToken(String token) {
PublicKey publicKey = getPublicKey(getPublicKeyString());
return Jwts.parser()
.setSigningKey(publicKey)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
public String generateToken(UserDetails userDetails) {
return null;
}
public Boolean validateToken(String token, UserDetails userDetails) {
AuthenticationUser user = (AuthenticationUser) userDetails;
final Date created = getIssuedAtDateFromToken(token);
return (!isTokenExpired(token) );
}
private String getPublicKeyString(){
return uaaFeignClient.getPublicKey();
}
/**
* 获取PublicKey对象
* @param publicKeyBase64
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
@SneakyThrows
public PublicKey getPublicKey(String publicKeyBase64) {
byte[] byteKey = Base64.decodeBase64(publicKeyBase64);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(x509EncodedKeySpec);
}
}
package cn.ibizlab.util.service;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.security.AuthenticationUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
public interface AuthenticationUserService extends UserDetailsService {
@Override
@Cacheable( value="ibzuaa_users", key = "'getByUsername:'+#p0")
default AuthenticationUser loadUserByUsername(String username){
return null ;
}
@Cacheable( value="ibzuaa_users", key = "'getByUsername:'+#p0")
AuthenticationUser loadUserByLogin(String username,String password);
@CacheEvict( value="ibzuaa_users", key = "'glob:*getByUsername:'+#p0")
default void resetByUsername(String username){}
}
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
package cn.ibizlab.util.service;
import com.alibaba.fastjson.JSONObject;
import cn.ibizlab.util.client.IBZOUFeignClient;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.client.IBZUAAFeignClient;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.security.AuthorizationLogin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
/**
* 实体[IBZUSER] 服务对象接口实现
*/
@Service("IBZUAAUserService")
@ConditionalOnExpression("${ibiz.enablePermissionValid:false}||'${ibiz.auth.service:IBZUAAUserService}'.equals('IBZUAAUserService')")
public class IBZUAAUserService implements AuthenticationUserService{
@Autowired
private IBZUAAFeignClient uaaFeignClient;
@Override
public AuthenticationUser loadUserByUsername(String username) {
AuthenticationUser user = uaaFeignClient.loginByUsername(username);
if(user == null) {
throw new BadRequestAlertException("登录失败","IBZUAAUser",username);
}
return user;
}
@Override
public AuthenticationUser loadUserByLogin(String username, String password) {
String[] data = username.split("[|]");
String loginname = username;
String domains = "";
if(data.length==2) {
loginname=data[0].trim();
domains=data[1].trim();
}
AuthorizationLogin logininfo = new AuthorizationLogin();
logininfo.setDomain(domains);
logininfo.setLoginname(loginname);
logininfo.setPassword(password);
AuthenticationUser user = uaaFeignClient.login(logininfo);
if(user == null){
throw new BadRequestAlertException("登录失败","IBZUAAUser", username);
}
return user;
}
}
package cn.ibizlab.util.service;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.*;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
* 自定义feigen客户端配置
*
* @author
*/
@Service
public class RemoteService {
/**
* FeignClientFactoryBean
*/
@Autowired
protected FeignContext feignContext;
/**
* FeignClient 默认LoadBalancerFeignClient
*/
@Autowired
private Client feignClient;
private static final Map<String, Object> FEIGN_CLIENTS = new ConcurrentHashMap<>();
/**
* 定义远程通用接口
*/
public interface RemoteFeignClient {
@RequestMapping(method = RequestMethod.POST, value = "/{path}")
JSONObject post( @PathVariable("path") String path, @RequestHeader("Authorization") String token, @RequestBody Map param);
@RequestMapping(method = RequestMethod.GET, value = "/{path}")
JSONObject request( @PathVariable("path") String path, @RequestHeader("Authorization") String token, Map param);
@RequestMapping(method = RequestMethod.GET, value = "/{path}")
JSONObject get( @PathVariable("path") String path, @RequestHeader("Authorization") String token);
@RequestMapping(method = RequestMethod.PUT, value = "/{path}")
JSONObject put( @PathVariable("path") String path, @RequestHeader("Authorization") String token,@RequestBody Map param);
@RequestMapping(method = RequestMethod.DELETE, value = "/{path}")
JSONObject delete(@PathVariable("path") String path, @RequestHeader("Authorization") String token);
}
/**
* @param serverId
* @return
*/
public RemoteFeignClient getClient(String serverId) {
return this.create(RemoteFeignClient.class, serverId);
}
/**
* 设置编码解码器为FastJson
*
* @param clazz
* @param serviceId
* @param <T>
* @return
*/
private synchronized <T> T create(Class<T> clazz, String serviceId) {
Object object = FEIGN_CLIENTS.get(serviceId);
if (Objects.isNull(object)) {
object = Feign.builder()
//decoder指定对象解码方式
.decoder(this.feignDecoder())
.encoder(this.feignEncoder())
.client(feignClient)
//options方法指定连接超时时长及响应超时时长
.options(new Request.Options(5000, 50000))
//retryer方法指定重试策略
//.retryer(new Retryer.Default(5000, 5000, 3))
.contract(feignContext.getInstance(serviceId, Contract.class))
//target方法绑定接口与服务端地址。返回类型为绑定的接口类型。
.target(clazz, "http://"+serviceId);
FEIGN_CLIENTS.put(serviceId, object);
}
return (T) object;
}
private Decoder feignDecoder() {
return new SpringDecoder(feignHttpMessageConverter());
}
private Encoder feignEncoder() {
return new SpringEncoder(feignHttpMessageConverter());
}
private ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(new ObjectMapper());
final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(jsonConverter);
return () -> httpMessageConverters;
}
}
\ No newline at end of file
package cn.ibizlab.util.service;
import cn.ibizlab.util.domain.FileItem;
import cn.ibizlab.util.errors.InternalServerErrorException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
@Primary
@Slf4j
@Service
public class SimpleFileService implements FileService {
@Value("${ibiz.filePath:/app/file/}")
private String fileRoot;
@Override
public FileItem saveFile(MultipartFile multipartFile) {
FileItem item = null;
// 获取文件名
String fileName = multipartFile.getOriginalFilename();
// 获取文件后缀
String extname = "."+getExtensionName(fileName);
try {
String fileid = DigestUtils.md5DigestAsHex(multipartFile.getInputStream());
String fileFullPath = this.fileRoot+"ibizutil"+File.separator+fileid+File.separator+fileName;
File file = new File(fileFullPath);
File parent = new File(file.getParent());
if(!parent.exists()) {
parent.mkdirs();
}
FileCopyUtils.copy(multipartFile.getInputStream(), Files.newOutputStream(file.toPath()));
item = new FileItem(fileid, fileName, fileid, fileName, (int)multipartFile.getSize(), extname);
} catch (IOException e) {
throw new InternalServerErrorException("文件上传失败,"+e);
}
return item;
}
@Override
public File getFile(String fileid) {
String dirpath = this.fileRoot+"ibizutil"+File.separator+fileid;
File parent = new File(dirpath);
if (parent.exists() && parent.isDirectory() && parent.listFiles().length > 0) {
return parent.listFiles()[0];
}
throw new InternalServerErrorException("文件未找到");
}
/**
* 获取文件扩展名
* @param filename
* @return
*/
public static String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return filename;
}
}
\ No newline at end of file
package cn.ibizlab.util.service;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.client.IBZUAAFeignClient;
import cn.ibizlab.util.client.IBZOUFeignClient;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.security.core.authority.AuthorityUtils;
/**
* 实体[IBZUSER] 服务对象接口实现
*/
@Primary
@Service("SimpleUserService")
@ConditionalOnExpression("(!${ibiz.enablePermissionValid:false})&&'${ibiz.auth.service:IBZUAAUserService}'.equals('SimpleUserService')")
public class SimpleUserService implements AuthenticationUserService {
@Override
public AuthenticationUser loadUserByUsername(String username) {
AuthenticationUser user = new AuthenticationUser();
String[] data = username.split("[|]");
String loginname = username;
String domains = "";
String password = "";
if(data.length==2) {
loginname = data[0].trim();
domains = data[1].trim();
}
user.setUserid(username);
user.setUsercode(loginname);
user.setUsername(username);
user.setLoginname(loginname);
user.setPersonname(loginname);
user.setDomain(domains);
user.setPassword(password);
user.setOrgid(domains);
user.setOrgcode(domains);
user.setOrgname(domains);
user.setSuperuser(1);
user.setAuthorities(AuthorityUtils.createAuthorityList("ROLE_SUPERADMIN"));
return user;
}
@Override
public AuthenticationUser loadUserByLogin(String username, String password) {
AuthenticationUser authuserdetail = loadUserByUsername(username);
return authuserdetail;
}
@Override
public void resetByUsername(String username) {
}
}
package cn.ibizlab.util.web;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
/**
* feign请求拦截器
* 拦截所有使用feign发出的请求,附加原始请求Header参数及Token
*/
@Configuration
public class FeignRequestInterceptor implements RequestInterceptor {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = requestAttributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
if (name.equalsIgnoreCase("transfer-encoding")) {
continue;
}
String values = request.getHeader(name);
requestTemplate.header(name, values);
}
logger.info("feign interceptor header:{}", requestTemplate);
}
}
}
}
\ No newline at end of file
#eureka配置中心
spring:
cloud:
nacos:
discovery:
enabled: false
eureka:
client:
enabled: true
serviceUrl:
defaultZone: http://127.0.0.1:8762/eureka/
#nacos配置中心
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
enabled: true
eureka:
client:
enabled: false
#缓存、数据源
spring:
cache:
redis:
time-to-live: 3600
caffeine:
spec: initialCapacity=5,maximumSize=500,expireAfterWrite=3600s
redis:
host: 127.0.0.1
port: 6379
password:
database: 0
lettuce:
pool:
max-active: 32
max-wait: 300ms
max-idle: 16
min-idle: 8
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/a_A_5d9d78509?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true&allowMultiQueries=true
driver-class-name: com.mysql.jdbc.Driver
isSyncDBSchema: false
defaultSchema: a_A_5d9d78509
dynamic:
druid: #以下是全局默认值,可以全局更改
filters: stat,log4j2
#配置初始化大小/最小/最大
initial-size: 1
min-idle: 1
max-active: 20
#获取连接等待超时时间
max-wait: 60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
#一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
datasource:
master:
username: ${spring.datasource.username}
password: ${spring.datasource.password}
url: ${spring.datasource.url}
driver-class-name: ${spring.datasource.driver-class-name}
conf: classpath:liquibase/master.xml
isSyncDBSchema: ${spring.datasource.isSyncDBSchema}
defaultSchema: ${spring.datasource.defaultSchema}
db2:
username: ${spring.datasource.username}
password: ${spring.datasource.password}
url: ${spring.datasource.url}
driver-class-name: ${spring.datasource.driver-class-name}
conf: classpath:liquibase/master.xml
isSyncDBSchema: ${spring.datasource.isSyncDBSchema}
defaultSchema: ${spring.datasource.defaultSchema}
#Mybatis-plus配置
mybatis-plus:
global-config:
refresh-mapper: true
db-config:
# 全局逻辑已删除默认值
logic-delete-value: 0
# 全局逻辑未删除默认值
logic-not-delete-value: 1
mapper-locations: classpath*:/mapper/*/*/*.xml
configuration:
jdbc-type-for-null: 'null'
map-underscore-to-camel-case: false
#阿里sentinel熔断器
feign:
httpclient:
enabled: true
sentinel:
enabled: true
compression:
request:
enabled: true
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
min-response-size: 10240
response:
enabled: true
#Log配置
logging:
level:
cn.ibizlab: debug
org.springframework.boot.autoconfigure: ERROR
#zuul网关超时设置
ribbon:
ReadTimeout: 60000
ConnectTimeout: 60000
#系统是否开启权限验证、是否开启缓存
#缓存级别:无缓存(无配置项)、一级缓存(L1)、二级缓存(L2)
ibiz:
enablePermissionValid: true
cacheLevel: L1 #(L1)一级本地caffeine缓存;(L2)caffeine缓存+Redis缓存
### jobs
jobs:
#admin-address: http://127.0.0.1:40005
app-name: ibznotify
app-port: 9999
#app-ip: 127.0.0.1
### 启用Gzip压缩
server:
compression:
enabled: true
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
min-response-size: 10240
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册