Merge branch 'leng_dev' into greenwich

# Conflicts:
#	pigx-auth/pom.xml
#	pigx-common/pigx-common-core/pom.xml
#	pigx-common/pigx-common-data/pom.xml
#	pigx-common/pigx-common-gateway/pom.xml
#	pigx-common/pigx-common-job/pom.xml
#	pigx-common/pigx-common-log/pom.xml
#	pigx-common/pigx-common-minio/pom.xml
#	pigx-common/pigx-common-security/pom.xml
#	pigx-common/pigx-common-swagger/pom.xml
#	pigx-common/pigx-common-transaction/pom.xml
#	pigx-common/pom.xml
#	pigx-config/pom.xml
#	pigx-config/src/main/resources/config/pigx-upms-biz-dev.yml
#	pigx-eureka/pom.xml
#	pigx-gateway/pom.xml
#	pigx-upms/pigx-upms-api/pom.xml
#	pigx-upms/pigx-upms-biz/pom.xml
#	pigx-upms/pom.xml
#	pigx-visual/pigx-activiti/pom.xml
#	pigx-visual/pigx-codegen/pom.xml
#	pigx-visual/pigx-daemon/pom.xml
#	pigx-visual/pigx-monitor/pom.xml
#	pigx-visual/pigx-sso-client-demo/pom.xml
#	pigx-visual/pigx-tx-manager/pom.xml
#	pigx-visual/pom.xml
#	pom.xml
This commit is contained in:
冷冷 committed 2019-01-23 18:31:50 +08:00
commit 2b2507a068
85 files changed
+1423 -629

No files matched your search

@@ -120,4 +120,9 @@ public interface SecurityConstants {
*/
String RESOURCE_SERVER_CONFIGURER = "resourceServerConfigurerAdapter";
/**
* 客户端模式
*/
String CLIENT_CREDENTIALS = "client_credentials";
}
@@ -95,7 +95,7 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public void destroy() throws Exception {
public void destroy() {
SpringContextHolder.clearHolder();
}
@@ -23,6 +23,7 @@ import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.json.JSONUtil;
import com.pig4cloud.pigx.common.core.exception.CheckedException;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
@@ -204,7 +205,8 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
*
* @return
*/
public String[] getClientId(ServerHttpRequest request) throws Exception {
@SneakyThrows
public String[] getClientId(ServerHttpRequest request) {
String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (header == null || !header.startsWith(BASIC_)) {
@@ -29,6 +29,7 @@ import com.pig4cloud.pigx.common.data.enums.DataScopeTypeEnum;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
@@ -58,7 +59,8 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
private final DataSource dataSource;
@Override
public Object intercept(Invocation invocation) throws Throwable {
@SneakyThrows
public Object intercept(Invocation invocation) {
StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
this.sqlParser(metaObject);
@@ -41,18 +41,30 @@ import java.util.List;
@MapperScan("com.pig4cloud.pigx.*.mapper")
public class MybatisPlusConfig {
/**
* 创建租户维护处理器对象
*
* @return 处理后的租户维护处理器
*/
@Bean
@ConditionalOnMissingBean
public PigxTenantHandler pigxTenantHandler() {
return new PigxTenantHandler();
}
/**
* 分页插件
*
* @param tenantHandler 租户处理器
* @return PaginationInterceptor
*/
@Bean
@ConditionalOnMissingBean
public PaginationInterceptor paginationInterceptor() {
public PaginationInterceptor paginationInterceptor(PigxTenantHandler tenantHandler) {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
List<ISqlParser> sqlParserList = new ArrayList<>();
TenantSqlParser tenantSqlParser = new TenantSqlParser();
tenantSqlParser.setTenantHandler(new PigxTenantHandler());
tenantSqlParser.setTenantHandler(tenantHandler);
sqlParserList.add(tenantSqlParser);
paginationInterceptor.setSqlParserList(sqlParserList);
return paginationInterceptor;
@@ -0,0 +1,29 @@
package com.pig4cloud.pigx.common.data.tenant;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* 多租户配置
*
* @author oathsign
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "pigx.tenant")
public class PigxTenantConfigProperties {
/**
* 维护租户列名称
*/
private String column="tenant_id";
/**
* 多租户的数据表集合
*/
private List<String> tables = new ArrayList<>();
}
@@ -17,11 +17,12 @@
package com.pig4cloud.pigx.common.data.tenant;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @author lengleng
@@ -31,8 +32,8 @@ import net.sf.jsqlparser.expression.LongValue;
*/
@Slf4j
public class PigxTenantHandler implements TenantHandler {
private static final String[] TENANT_TABLES = new String[]{"sys_user", "sys_role", "sys_dept",
"sys_log", "sys_social_details", "sys_dict", "sys_log", "oa_leave_bill"};
@Autowired
private PigxTenantConfigProperties properties;
/**
* 获取租户值
@@ -53,7 +54,7 @@ public class PigxTenantHandler implements TenantHandler {
*/
@Override
public String getTenantIdColumn() {
return "tenant_id";
return properties.getColumn();
}
/**
@@ -64,6 +65,6 @@ public class PigxTenantHandler implements TenantHandler {
*/
@Override
public boolean doTableFilter(String tableName) {
return !ArrayUtil.contains(TENANT_TABLES, tableName);
return !properties.getTables().contains(tableName);
}
}
@@ -19,6 +19,7 @@ package com.pig4cloud.pigx.common.data.tenant;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
@@ -26,12 +27,10 @@ import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lengleng
@@ -43,7 +42,8 @@ import java.io.IOException;
public class TenantContextHolderFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
@SneakyThrows
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
@@ -2,6 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pig4cloud.pigx.common.data.cache.RedisTemplateConfig,\
com.pig4cloud.pigx.common.data.cache.RedisCacheManagerConfig,\
com.pig4cloud.pigx.common.data.cache.RedisCacheAutoConfiguration,\
com.pig4cloud.pigx.common.data.tenant.PigxTenantConfigProperties,\
com.pig4cloud.pigx.common.data.tenant.TenantContextHolderFilter,\
com.pig4cloud.pigx.common.data.tenant.PigxFeignTenantConfiguration,\
com.pig4cloud.pigx.common.data.mybatis.MybatisPlusConfig
@@ -31,8 +31,8 @@ import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import com.pig4cloud.pigx.common.job.properties.ElasticJobProperties;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -59,7 +59,8 @@ public abstract class AbstractJobInitialization implements ApplicationContextAwa
protected ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
@SneakyThrows
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@@ -166,13 +167,13 @@ public abstract class AbstractJobInitialization implements ApplicationContextAwa
private LiteJobConfiguration getLiteJobConfiguration(JobTypeConfiguration jobTypeConfiguration, ElasticJobProperties.JobConfiguration jobConfiguration) {
//构建Lite作业
return LiteJobConfiguration.newBuilder(Objects.requireNonNull(jobTypeConfiguration))
.monitorExecution(jobConfiguration.isMonitorExecution())
.monitorPort(jobConfiguration.getMonitorPort())
.maxTimeDiffSeconds(jobConfiguration.getMaxTimeDiffSeconds())
.jobShardingStrategyClass(jobConfiguration.getJobShardingStrategyClass())
.reconcileIntervalMinutes(jobConfiguration.getReconcileIntervalMinutes())
.disabled(jobConfiguration.isDisabled())
.overwrite(jobConfiguration.isOverwrite()).build();
.monitorExecution(jobConfiguration.isMonitorExecution())
.monitorPort(jobConfiguration.getMonitorPort())
.maxTimeDiffSeconds(jobConfiguration.getMaxTimeDiffSeconds())
.jobShardingStrategyClass(jobConfiguration.getJobShardingStrategyClass())
.reconcileIntervalMinutes(jobConfiguration.getReconcileIntervalMinutes())
.disabled(jobConfiguration.isDisabled())
.overwrite(jobConfiguration.isOverwrite()).build();
}
/**
@@ -184,11 +185,11 @@ public abstract class AbstractJobInitialization implements ApplicationContextAwa
*/
protected JobCoreConfiguration getJobCoreConfiguration(String jobName, ElasticJobProperties.JobConfiguration jobConfiguration) {
JobCoreConfiguration.Builder builder = JobCoreConfiguration.newBuilder(jobName, jobConfiguration.getCron(), jobConfiguration.getShardingTotalCount())
.shardingItemParameters(jobConfiguration.getShardingItemParameters())
.jobParameter(jobConfiguration.getJobParameter())
.failover(jobConfiguration.isFailover())
.misfire(jobConfiguration.isMisfire())
.description(jobConfiguration.getDescription());
.shardingItemParameters(jobConfiguration.getShardingItemParameters())
.jobParameter(jobConfiguration.getJobParameter())
.failover(jobConfiguration.isFailover())
.misfire(jobConfiguration.isMisfire())
.description(jobConfiguration.getDescription());
if (StringUtils.isNotBlank(jobConfiguration.getJobExceptionHandler())) {
builder.jobProperties(JobPropertiesEnum.JOB_EXCEPTION_HANDLER.getKey(), jobConfiguration.getJobExceptionHandler());
}
@@ -220,7 +221,7 @@ public abstract class AbstractJobInitialization implements ApplicationContextAwa
//注册分布式监听者
AbstractDistributeOnceElasticJobListener distributedListener = registerBean(listener.getDistributedListenerClass(), listener.getDistributedListenerClass(),
AbstractDistributeOnceElasticJobListener.class, listener.getStartedTimeoutMilliseconds(), listener.getCompletedTimeoutMilliseconds());
AbstractDistributeOnceElasticJobListener.class, listener.getStartedTimeoutMilliseconds(), listener.getCompletedTimeoutMilliseconds());
if (null != distributedListener) {
elasticJobListeners.add(distributedListener);
}
@@ -24,6 +24,7 @@ import com.pig4cloud.pigx.common.log.aspect.SysLogAspect;
import com.pig4cloud.pigx.common.log.event.SysLogListener;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@@ -47,7 +48,7 @@ public class LogAutoConfiguration {
}
@Bean
public SysLogAspect sysLogAspect() {
return new SysLogAspect();
public SysLogAspect sysLogAspect(ApplicationEventPublisher publisher) {
return new SysLogAspect(publisher);
}
}
@@ -19,14 +19,16 @@
package com.pig4cloud.pigx.common.log.aspect;
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.log.event.SysLogEvent;
import com.pig4cloud.pigx.common.log.util.SysLogUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.ApplicationEventPublisher;
/**
* 操作日志使用spring event异步入库
@@ -35,10 +37,13 @@ import org.aspectj.lang.annotation.Aspect;
*/
@Slf4j
@Aspect
@AllArgsConstructor
public class SysLogAspect {
private final ApplicationEventPublisher publisher;
@SneakyThrows
@Around("@annotation(sysLog)")
public Object around(ProceedingJoinPoint point, SysLog sysLog) throws Throwable {
public Object around(ProceedingJoinPoint point, SysLog sysLog) {
String strClassName = point.getTarget().getClass().getName();
String strMethodName = point.getSignature().getName();
log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);
@@ -50,7 +55,7 @@ public class SysLogAspect {
Object obj = point.proceed();
Long endTime = System.currentTimeMillis();
logVo.setTime(endTime - startTime);
SpringContextHolder.publishEvent(new SysLogEvent(logVo));
publisher.publishEvent(new SysLogEvent(logVo));
return obj;
}
@@ -20,15 +20,15 @@
package com.pig4cloud.pigx.common.log.event;
import com.pig4cloud.pigx.admin.api.entity.SysLog;
import org.springframework.context.ApplicationEvent;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* 系统日志事件
*/
public class SysLogEvent extends ApplicationEvent {
public SysLogEvent(SysLog source) {
super(source);
}
@Getter
@AllArgsConstructor
public class SysLogEvent {
private final SysLog sysLog;
}
@@ -28,7 +28,6 @@ import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
/**
* @author lengleng
* 异步监听日志事件
@@ -42,7 +41,7 @@ public class SysLogListener {
@Order
@EventListener(SysLogEvent.class)
public void saveSysLog(SysLogEvent event) {
SysLog sysLog = (SysLog) event.getSource();
SysLog sysLog = event.getSysLog();
remoteLogService.saveLog(sysLog, SecurityConstants.FROM_IN);
}
}
@@ -22,6 +22,7 @@ import com.pig4cloud.common.minio.vo.MinioItem;
import com.pig4cloud.common.minio.vo.MinioObject;
import io.minio.messages.Bucket;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@@ -48,60 +49,65 @@ public class MinioEndpoint {
/**
* Bucket Endpoints
*/
@SneakyThrows
@PostMapping("/bucket/{bucketName}")
public Bucket createBucker(@PathVariable String bucketName) throws Exception {
public Bucket createBucker(@PathVariable String bucketName) {
template.createBucket(bucketName);
return template.getBucket(bucketName).get();
}
@SneakyThrows
@GetMapping("/bucket")
public List<Bucket> getBuckets() throws Exception {
public List<Bucket> getBuckets() {
return template.getAllBuckets();
}
@SneakyThrows
@GetMapping("/bucket/{bucketName}")
public Bucket getBucket(@PathVariable String bucketName) throws Exception {
public Bucket getBucket(@PathVariable String bucketName) {
return template.getBucket(bucketName).orElseThrow(() -> new IllegalArgumentException("Bucket Name not found!"));
}
@SneakyThrows
@DeleteMapping("/bucket/{bucketName}")
@ResponseStatus(HttpStatus.ACCEPTED)
public void deleteBucket(@PathVariable String bucketName) throws Exception {
public void deleteBucket(@PathVariable String bucketName) {
template.removeBucket(bucketName);
}
/**
* Object Endpoints
*/
@SneakyThrows
@PostMapping("/object/{bucketName}")
public MinioObject createObject(@RequestBody MultipartFile object, @PathVariable String bucketName) throws Exception {
public MinioObject createObject(@RequestBody MultipartFile object, @PathVariable String bucketName) {
String name = object.getOriginalFilename();
template.putObject(bucketName, name, object.getInputStream(), object.getSize(), object.getContentType());
return new MinioObject(template.getObjectInfo(bucketName, name));
}
@SneakyThrows
@PostMapping("/object/{bucketName}/{objectName}")
public MinioObject createObject(@RequestBody MultipartFile object, @PathVariable String bucketName, @PathVariable String objectName) throws Exception {
public MinioObject createObject(@RequestBody MultipartFile object, @PathVariable String bucketName, @PathVariable String objectName) {
template.putObject(bucketName, objectName, object.getInputStream(), object.getSize(), object.getContentType());
return new MinioObject(template.getObjectInfo(bucketName, objectName));
}
@SneakyThrows
@GetMapping("/object/{bucketName}/{objectName}")
public List<MinioItem> filterObject(@PathVariable String bucketName, @PathVariable String objectName) throws Exception {
public List<MinioItem> filterObject(@PathVariable String bucketName, @PathVariable String objectName) {
return template.getAllObjectsByPrefix(bucketName, objectName, true);
}
@SneakyThrows
@GetMapping("/object/{bucketName}/{objectName}/{expires}")
public Map<String, Object> getObject(@PathVariable String bucketName, @PathVariable String objectName, @PathVariable Integer expires) throws Exception {
public Map<String, Object> getObject(@PathVariable String bucketName, @PathVariable String objectName, @PathVariable Integer expires) {
Map<String, Object> responseBody = new HashMap<>(8);
// Put Object info
responseBody.put("bucket", bucketName);
@@ -111,9 +117,10 @@ public class MinioEndpoint {
return responseBody;
}
@DeleteMapping("/object/{bucketName}/{objectName}/")
@SneakyThrows
@ResponseStatus(HttpStatus.ACCEPTED)
public void deleteObject(@PathVariable String bucketName, @PathVariable String objectName) throws Exception {
@DeleteMapping("/object/{bucketName}/{objectName}/")
public void deleteObject(@PathVariable String bucketName, @PathVariable String objectName) {
template.removeObject(bucketName, objectName);
}
@@ -23,8 +23,10 @@ import io.minio.ObjectStat;
import io.minio.Result;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import java.io.InputStream;
import java.util.ArrayList;
@@ -36,23 +38,20 @@ import java.util.Optional;
*
* @author lengleng
*/
@NoArgsConstructor
@AllArgsConstructor
public class MinioTemplate {
private String endpoint;
private String accessKey;
private String secretKey;
@RequiredArgsConstructor
public class MinioTemplate implements InitializingBean {
private final String endpoint;
private final String accessKey;
private final String secretKey;
private MinioClient client;
/**
* 创建bucket
*
* @param bucketName bucket名称
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#makeBucket
*/
public void createBucket(String bucketName) throws Exception {
MinioClient client = getMinioClient();
@SneakyThrows
public void createBucket(String bucketName) {
if (!client.bucketExists(bucketName)) {
client.makeBucket(bucketName);
}
@@ -63,24 +62,25 @@ public class MinioTemplate {
* <p>
* https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
*/
public List<Bucket> getAllBuckets() throws Exception {
return getMinioClient().listBuckets();
@SneakyThrows
public List<Bucket> getAllBuckets() {
return client.listBuckets();
}
/**
* @param bucketName bucket名称
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
*/
public Optional<Bucket> getBucket(String bucketName) throws Exception {
return getMinioClient().listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
@SneakyThrows
public Optional<Bucket> getBucket(String bucketName) {
return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* @param bucketName bucket名称
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeBucket
*/
public void removeBucket(String bucketName) throws Exception {
getMinioClient().removeBucket(bucketName);
@SneakyThrows
public void removeBucket(String bucketName) {
client.removeBucket(bucketName);
}
/**
@@ -89,16 +89,16 @@ public class MinioTemplate {
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return
* @throws Exception
* @return MinioItem 列表
*/
public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) throws Exception {
List objectList = new ArrayList();
Iterable<Result<Item>> objectsIterator = getMinioClient()
@SneakyThrows
public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
List<MinioItem> objectList = new ArrayList<>();
Iterable<Result<Item>> objectsIterator = client
.listObjects(bucketName, prefix, recursive);
while (objectsIterator.iterator().hasNext()) {
objectList.add(objectsIterator.iterator().next().get());
objectList.add(new MinioItem(objectsIterator.iterator().next().get()));
}
return objectList;
}
@@ -110,10 +110,10 @@ public class MinioTemplate {
* @param objectName 文件名称
* @param expires 过期时间 <=7
* @return url
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#getObject
*/
public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
return getMinioClient().presignedGetObject(bucketName, objectName, expires);
@SneakyThrows
public String getObjectURL(String bucketName, String objectName, Integer expires) {
return client.presignedGetObject(bucketName, objectName, expires);
}
/**
@@ -122,10 +122,10 @@ public class MinioTemplate {
* @param bucketName bucket名称
* @param objectName 文件名称
* @return 二进制流
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#getObject
*/
public InputStream getObject(String bucketName, String objectName) throws Exception {
return getMinioClient().getObject(bucketName, objectName);
@SneakyThrows
public InputStream getObject(String bucketName, String objectName) {
return client.getObject(bucketName, objectName);
}
/**
@@ -137,7 +137,7 @@ public class MinioTemplate {
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
getMinioClient().putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
client.putObject(bucketName, objectName, stream, stream.available(), "application/octet-stream");
}
/**
@@ -151,7 +151,7 @@ public class MinioTemplate {
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
getMinioClient().putObject(bucketName, objectName, stream, size, contextType);
client.putObject(bucketName, objectName, stream, size, contextType);
}
/**
@@ -162,7 +162,7 @@ public class MinioTemplate {
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
*/
public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {
return getMinioClient().statObject(bucketName, objectName);
return client.statObject(bucketName, objectName);
}
/**
@@ -173,17 +173,15 @@ public class MinioTemplate {
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject
*/
public void removeObject(String bucketName, String objectName) throws Exception {
getMinioClient().removeObject(bucketName, objectName);
client.removeObject(bucketName, objectName);
}
/**
* 获取minio 原生客户端
*
* @return
* @throws Exception
*/
public MinioClient getMinioClient() throws Exception {
return new MinioClient(endpoint, accessKey, secretKey);
@Override
public void afterPropertiesSet() throws Exception {
Assert.hasText(endpoint, "Minio url 为空");
Assert.hasText(accessKey, "Minio accessKey为空");
Assert.hasText(secretKey, "Minio secretKey为空");
this.client = new MinioClient(endpoint, accessKey, secretKey);
}
}
@@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.security.exception.PigxAuth2Exception;
import lombok.SneakyThrows;
import java.io.IOException;
@@ -37,7 +38,8 @@ public class PigxAuth2ExceptionSerializer extends StdSerializer<PigxAuth2Excepti
}
@Override
public void serialize(PigxAuth2Exception value, JsonGenerator gen, SerializerProvider provider) throws IOException {
@SneakyThrows
public void serialize(PigxAuth2Exception value, JsonGenerator gen, SerializerProvider provider) {
gen.writeStartObject();
gen.writeObjectField("code", CommonConstants.FAIL);
gen.writeStringField("msg", value.getMessage());
@@ -18,6 +18,7 @@
package com.pig4cloud.pigx.common.security.component;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -56,10 +57,10 @@ public class PigxResourceServerConfigurerAdapter extends ResourceServerConfigure
* 默认的配置,对外暴露
*
* @param httpSecurity
* @throws Exception
*/
@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
@SneakyThrows
public void configure(HttpSecurity httpSecurity) {
//允许使用iframe 嵌套,避免swagger-ui 不被加载的问题
httpSecurity.headers().frameOptions().disable();
ExpressionUrlAuthorizationConfigurer<HttpSecurity>
@@ -21,6 +21,7 @@ import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -43,8 +44,9 @@ import javax.servlet.http.HttpServletRequest;
public class PigxSecurityInnerAspect {
private final HttpServletRequest request;
@SneakyThrows
@Around("@annotation(inner)")
public Object around(ProceedingJoinPoint point, Inner inner) throws Throwable {
public Object around(ProceedingJoinPoint point, Inner inner) {
String header = request.getHeader(SecurityConstants.FROM);
if (inner.value() && !StrUtil.equals(SecurityConstants.FROM_IN, header)) {
log.warn("访问接口 {} 没有权限", point.getSignature().getName());
@@ -45,7 +45,7 @@ public class PigxWebResponseExceptionTranslator implements WebResponseExceptionT
private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
@Override
public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
public ResponseEntity<OAuth2Exception> translate(Exception e) {
// Try to extract a SpringSecurityException from the stacktrace
Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e);
@@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
@@ -46,8 +47,9 @@ public class ResourceAuthExceptionEntryPoint implements AuthenticationEntryPoint
private final ObjectMapper objectMapper;
@Override
@SneakyThrows
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
AuthenticationException authException) {
response.setCharacterEncoding(CommonConstants.UTF8);
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
R<String> result = new R<>();
@@ -0,0 +1,68 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
package com.pig4cloud.pigx.common.security.feign;
import com.netflix.hystrix.HystrixCommand;
import feign.Feign;
import feign.RequestInterceptor;
import feign.hystrix.HystrixFeign;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.cloud.security.oauth2.client.AccessTokenContextRelay;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
/**
* fegin 配置增强
*
* @author L.cm
*/
@Configuration
@ConditionalOnClass(Feign.class)
public class PigxFeginConfiguration {
@Bean
@ConditionalOnProperty("security.oauth2.client.client-id")
public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext,
OAuth2ProtectedResourceDetails resource,
AccessTokenContextRelay accessTokenContextRelay) {
return new PigxFeignClientInterceptor(oAuth2ClientContext, resource, accessTokenContextRelay);
}
@Configuration
@ConditionalOnClass({HystrixCommand.class, HystrixFeign.class})
protected static class HystrixFeignConfiguration {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ConditionalOnProperty("feign.hystrix.enabled")
public Feign.Builder feignHystrixBuilder(FeignContext feignContext) {
return PigxHystrixFeign.builder(feignContext)
.decode404()
.errorDecoder(new PigxFeginErrorDecoder());
}
}
}
@@ -0,0 +1,129 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
package com.pig4cloud.pigx.common.security.feign;
import cn.hutool.core.io.IoUtil;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.util.ConcurrentDateFormat;
import feign.Response;
import feign.RetryableException;
import feign.codec.ErrorDecoder;
import org.springframework.lang.Nullable;
import java.io.IOException;
import java.io.Reader;
import java.text.ParseException;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import static feign.Util.checkNotNull;
import static java.lang.String.format;
import static java.util.Locale.US;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* 异常处理,将返回的数据反序列化成 R
*
* @author L.cm
*/
public class PigxFeginErrorDecoder extends ErrorDecoder.Default {
private final RetryAfterDecoder retryAfterDecoder = new RetryAfterDecoder();
private static final String REGEX = "^[0-9]+$";
@Override
public Exception decode(String methodKey, Response response) {
PigxFeginException exception = errorStatus(methodKey, response);
Date retryAfter = retryAfterDecoder.apply(firstOrNull(response.headers()));
return new RetryableException(exception.getMessage(), exception, retryAfter);
}
private static PigxFeginException errorStatus(String methodKey, Response response) {
try {
if (response.body() != null) {
Reader reader = response.body().asReader();
return new PigxFeginException(R.builder()
.msg(IoUtil.read(reader))
.code(CommonConstants.FAIL).build());
}
} catch (IOException ignored) { // NOPMD
}
String message = format("status %s reading %s", response.status(), methodKey);
return new PigxFeginException(message);
}
@Nullable
private <T> T firstOrNull(Map<String, Collection<T>> map) {
String key = feign.Util.RETRY_AFTER;
if (map.containsKey(key) && !map.get(key).isEmpty()) {
return map.get(key).iterator().next();
}
return null;
}
/**
* Decodes a {@link feign.Util#RETRY_AFTER} header into an absolute date, if possible. <br> See <a
* href="https://tools.ietf.org/html/rfc2616#section-14.37">Retry-After format</a>
*/
static class RetryAfterDecoder {
static final ConcurrentDateFormat RFC822_FORMAT = ConcurrentDateFormat.of
("EEE, dd MMM yyyy HH:mm:ss 'GMT'", US, TimeZone.getTimeZone(ZoneId.of("GMT")));
private final ConcurrentDateFormat rfc822Format;
RetryAfterDecoder() {
this(RFC822_FORMAT);
}
RetryAfterDecoder(ConcurrentDateFormat rfc822Format) {
this.rfc822Format = checkNotNull(rfc822Format, "rfc822Format");
}
private long currentTimeMillis() {
return System.currentTimeMillis();
}
/**
* returns a date that corresponds to the first time a request can be retried.
*
* @param retryAfter String in <a href="https://tools.ietf.org/html/rfc2616#section-14.37">Retry-After format</a>
*/
@Nullable
Date apply(@Nullable String retryAfter) {
if (retryAfter == null) {
return null;
}
if (retryAfter.matches(REGEX)) {
long deltaMillis = SECONDS.toMillis(Long.parseLong(retryAfter));
return new Date(currentTimeMillis() + deltaMillis);
}
try {
return rfc822Format.parse(retryAfter);
} catch (ParseException ignored) {
return null;
}
}
}
}
@@ -0,0 +1,57 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
package com.pig4cloud.pigx.common.security.feign;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.Getter;
/**
* Fegin 异常
*
* @author L.cm
*/
public class PigxFeginException extends RuntimeException {
@Getter
private final R result;
public PigxFeginException(R result) {
super(result.getMsg());
this.result = result;
}
public PigxFeginException(String message) {
super(message);
this.result = R.builder()
.code(CommonConstants.FAIL)
.msg(message).build();
}
/**
* 提高性能
*
* @return {Throwable}
*/
@Override
public Throwable fillInStackTrace() {
return this;
}
}
@@ -0,0 +1,57 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
package com.pig4cloud.pigx.common.security.feign;
import feign.hystrix.FallbackFactory;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.Enhancer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* 默认 Fallback,避免写过多fallback类
*
* @param <T> 泛型标记
* @author L.cm
*/
@Slf4j
@NoArgsConstructor
public final class PigxFeginFallbackFactory<T> implements FallbackFactory<T> {
public static final PigxFeginFallbackFactory INSTANCE = new PigxFeginFallbackFactory();
private static final ConcurrentMap<Class<?>, Object> FALLBACK_MAP = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
public T create(final Class<?> type, final Throwable cause) {
return (T) FALLBACK_MAP.computeIfAbsent(type, key -> {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(key);
enhancer.setCallback(new PigxFeignFallbackMethod(type, cause));
return enhancer.create();
});
}
@Override
public T create(Throwable cause) {
return null;
}
}
@@ -1,47 +0,0 @@
/*
*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*
*/
package com.pig4cloud.pigx.common.security.feign;
import feign.RequestInterceptor;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.security.oauth2.client.AccessTokenContextRelay;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
/**
* @author lengleng
* @date 2018/6/22
* feign 拦截器传递 header 中oauth token,
* 使用hystrix 的信号量模式
*/
@Configuration
@AllArgsConstructor
@ConditionalOnProperty("security.oauth2.client.client-id")
public class PigxFeignClientConfiguration {
@Bean
public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext,
OAuth2ProtectedResourceDetails resource,
AccessTokenContextRelay accessTokenContextRelay) {
return new PigxFeignClientInterceptor(oAuth2ClientContext, resource,accessTokenContextRelay);
}
}
@@ -0,0 +1,38 @@
package com.pig4cloud.pigx.common.security.feign;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.lang.Nullable;
import java.lang.reflect.Method;
/**
* @author lengleng
* @date 2019-01-22
*/
@Slf4j
@AllArgsConstructor
public class PigxFeignFallbackMethod implements MethodInterceptor {
private Class<?> type;
private Throwable cause;
@Nullable
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) {
log.error("Fallback class:[{}] method:[{}] message:[{}]",
type.getName(), method.getName(), cause.getMessage());
if (R.class == method.getReturnType()) {
final R result = cause instanceof PigxFeginException ?
((PigxFeginException) cause).getResult() : R.builder()
.code(CommonConstants.FAIL)
.msg(cause.getMessage()).build();
return result;
}
return null;
}
}
@@ -0,0 +1,289 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
package com.pig4cloud.pigx.common.security.feign;
import com.netflix.hystrix.HystrixCommand;
import feign.*;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.hystrix.FallbackFactory;
import feign.hystrix.HystrixDelegatingContract;
import feign.hystrix.SetterFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* 自定义 Hystrix Feign 实现默认 fallBack
*
* @author L.cm
*/
public class PigxHystrixFeign {
public static PigxHystrixFeign.Builder builder(FeignContext feignContext) {
return new PigxHystrixFeign.Builder(feignContext);
}
public static final class Builder extends Feign.Builder {
private Contract contract = new Contract.Default();
private SetterFactory setterFactory = new SetterFactory.Default();
private final FeignContext feignContext;
public Builder(FeignContext feignContext) {
this.feignContext = feignContext;
}
/**
* Allows you to override hystrix properties such as thread pools and command keys.
*/
public PigxHystrixFeign.Builder setterFactory(SetterFactory setterFactory) {
this.setterFactory = setterFactory;
return this;
}
@Override
public <T> T target(Target<T> target) {
Class<T> targetType = target.type();
FeignClient feignClient = AnnotatedElementUtils.getMergedAnnotation(targetType, FeignClient.class);
String factoryName = feignClient.name();
SetterFactory setterFactoryBean = this.getOptional(factoryName, feignContext, SetterFactory.class);
if (setterFactoryBean != null) {
this.setterFactory(setterFactoryBean);
}
Class<?> fallback = feignClient.fallback();
if (fallback != void.class) {
return targetWithFallback(factoryName, feignContext, target, this, fallback);
}
Class<?> fallbackFactory = feignClient.fallbackFactory();
if (fallbackFactory != void.class) {
return targetWithFallbackFactory(factoryName, feignContext, target, this, fallbackFactory);
}
return build().newInstance(target);
}
@SuppressWarnings("unchecked")
private <T> T targetWithFallbackFactory(String feignClientName, FeignContext context,
Target<T> target,
PigxHystrixFeign.Builder builder,
Class<?> fallbackFactoryClass) {
FallbackFactory<? extends T> fallbackFactory = (FallbackFactory<? extends T>)
getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class);
/* We take a sample fallback from the fallback factory to check if it returns a fallback
that is compatible with the annotated feign interface. */
Object exampleFallback = fallbackFactory.create(new RuntimeException());
Assert.notNull(exampleFallback,
String.format(
"Incompatible fallbackFactory instance for feign client %s. Factory may not produce null!",
feignClientName));
if (!target.type().isAssignableFrom(exampleFallback.getClass())) {
throw new IllegalStateException(
String.format(
"Incompatible fallbackFactory instance for feign client %s. Factory produces instances of '%s', but should produce instances of '%s'",
feignClientName, exampleFallback.getClass(), target.type()));
}
return builder.target(target, fallbackFactory);
}
private <T> T targetWithFallback(String feignClientName, FeignContext context,
Target<T> target,
PigxHystrixFeign.Builder builder, Class<?> fallback) {
T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type());
return builder.target(target, fallbackInstance);
}
@SuppressWarnings("unchecked")
private <T> T getFromContext(String fallbackMechanism, String feignClientName, FeignContext context,
Class<?> beanType, Class<T> targetType) {
Object fallbackInstance = context.getInstance(feignClientName, beanType);
if (fallbackInstance == null) {
throw new IllegalStateException(String.format(
"No %s instance of type %s found for feign client %s",
fallbackMechanism, beanType, feignClientName));
}
if (!targetType.isAssignableFrom(beanType)) {
throw new IllegalStateException(
String.format(
"Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s",
fallbackMechanism, beanType, targetType, feignClientName));
}
return (T) fallbackInstance;
}
@Nullable
private <T> T getOptional(String feignClientName, FeignContext context, Class<T> beanType) {
return context.getInstance(feignClientName, beanType);
}
/**
* @see #target(Class, String, Object)
*/
public <T> T target(Target<T> target, @Nullable T fallback) {
return build(fallback != null ? new FallbackFactory.Default<T>(fallback) : null)
.newInstance(target);
}
/**
* @see #target(Class, String, FallbackFactory)
*/
public <T> T target(Target<T> target, FallbackFactory<? extends T> fallbackFactory) {
return build(fallbackFactory).newInstance(target);
}
/**
* Like {@link Feign#newInstance(Target)}, except with {@link HystrixCommand
* fallback} support.
*
* <p>Fallbacks are known values, which you return when there's an error invoking an http
* method. For example, you can return a cached result as opposed to raising an error to the
* caller. To use this feature, pass a safe implementation of your target interface as the last
* parameter.
* <p>
* Here's an example:
* <pre>
* {@code
*
* // When dealing with fallbacks, it is less tedious to keep interfaces small.
* interface GitHub {
* @RequestLine("GET /repos/{owner}/{repo}/contributors")
* List<String> contributors(@Param("owner") String owner, @Param("repo") String repo);
* }
*
* // This instance will be invoked if there are errors of any kind.
* GitHub fallback = (owner, repo) -> {
* if (owner.equals("Netflix") && repo.equals("feign")) {
* return Arrays.asList("stuarthendren"); // inspired this approach!
* } else {
* return Collections.emptyList();
* }
* };
*
* GitHub github = HystrixFeign.builder()
* ...
* .target(GitHub.class, "https://api.github.com", fallback);
* }</pre>
*
* @see #target(Target, Object)
*/
public <T> T target(Class<T> apiType, String url, T fallback) {
return target(new Target.HardCodedTarget<T>(apiType, url), fallback);
}
/**
* Same as {@link #target(Class, String, T)}, except you can inspect a source exception before
* creating a fallback object.
*/
public <T> T target(Class<T> apiType, String url, FallbackFactory<? extends T> fallbackFactory) {
return target(new Target.HardCodedTarget<T>(apiType, url), fallbackFactory);
}
@Override
public Feign.Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory) {
throw new UnsupportedOperationException();
}
@Override
public PigxHystrixFeign.Builder contract(Contract contract) {
this.contract = contract;
return this;
}
@Override
public Feign build() {
return build(null);
}
/**
* Configures components needed for hystrix integration.
*/
Feign build(@Nullable final FallbackFactory<?> nullableFallbackFactory) {
super.invocationHandlerFactory((target, dispatch) ->
new PigxHystrixInvocationHandler(target, dispatch, setterFactory, nullableFallbackFactory));
super.contract(new HystrixDelegatingContract(contract));
return super.build();
}
@Override
public PigxHystrixFeign.Builder logLevel(Logger.Level logLevel) {
return (PigxHystrixFeign.Builder) super.logLevel(logLevel);
}
@Override
public PigxHystrixFeign.Builder client(Client client) {
return (PigxHystrixFeign.Builder) super.client(client);
}
@Override
public PigxHystrixFeign.Builder retryer(Retryer retryer) {
return (PigxHystrixFeign.Builder) super.retryer(retryer);
}
@Override
public PigxHystrixFeign.Builder logger(Logger logger) {
return (PigxHystrixFeign.Builder) super.logger(logger);
}
@Override
public PigxHystrixFeign.Builder encoder(Encoder encoder) {
return (PigxHystrixFeign.Builder) super.encoder(encoder);
}
@Override
public PigxHystrixFeign.Builder decoder(Decoder decoder) {
return (PigxHystrixFeign.Builder) super.decoder(decoder);
}
@Override
public PigxHystrixFeign.Builder mapAndDecode(ResponseMapper mapper, Decoder decoder) {
return (PigxHystrixFeign.Builder) super.mapAndDecode(mapper, decoder);
}
@Override
public PigxHystrixFeign.Builder decode404() {
return (PigxHystrixFeign.Builder) super.decode404();
}
@Override
public PigxHystrixFeign.Builder errorDecoder(ErrorDecoder errorDecoder) {
return (PigxHystrixFeign.Builder) super.errorDecoder(errorDecoder);
}
@Override
public PigxHystrixFeign.Builder options(Request.Options options) {
return (PigxHystrixFeign.Builder) super.options(options);
}
@Override
public PigxHystrixFeign.Builder requestInterceptor(RequestInterceptor requestInterceptor) {
return (PigxHystrixFeign.Builder) super.requestInterceptor(requestInterceptor);
}
@Override
public PigxHystrixFeign.Builder requestInterceptors(Iterable<RequestInterceptor> requestInterceptors) {
return (PigxHystrixFeign.Builder) super.requestInterceptors(requestInterceptors);
}
}
}
@@ -0,0 +1,217 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
package com.pig4cloud.pigx.common.security.feign;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommand.Setter;
import feign.InvocationHandlerFactory.MethodHandler;
import feign.Target;
import feign.hystrix.FallbackFactory;
import feign.hystrix.SetterFactory;
import org.springframework.lang.Nullable;
import rx.Completable;
import rx.Observable;
import rx.Single;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import static feign.Util.checkNotNull;
/**
* @author L.cm
* <p>
* 降级注入
*/
public final class PigxHystrixInvocationHandler implements InvocationHandler {
private static final String EQUALS = "equals";
private static final String HASH_CODE = "hashCode";
private static final String TO_STRING = "toString";
private final Target<?> target;
private final Map<Method, MethodHandler> dispatch;
@Nullable
private final FallbackFactory<?> fallbackFactory;
private final Map<Method, Method> fallbackMethodMap;
private final Map<Method, Setter> setterMethodMap;
PigxHystrixInvocationHandler(
Target<?> target, Map<Method,
MethodHandler> dispatch,
SetterFactory setterFactory,
FallbackFactory<?> fallbackFactory) {
this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch");
this.fallbackFactory = fallbackFactory;
this.fallbackMethodMap = toFallbackMethod(dispatch);
this.setterMethodMap = toSetters(setterFactory, target, dispatch.keySet());
}
/**
* If the method param of InvocationHandler.invoke is not accessible, i.e in a package-private
* interface, the fallback call in hystrix command will fail cause of access restrictions. But
* methods in dispatch are copied methods. So setting access to dispatch method doesn't take
* effect to the method in InvocationHandler.invoke. Use map to store a copy of method to invoke
* the fallback to bypass this and reducing the count of reflection calls.
*
* @return cached methods map for fallback invoking
*/
private static Map<Method, Method> toFallbackMethod(Map<Method, MethodHandler> dispatch) {
Map<Method, Method> result = new LinkedHashMap<>(dispatch.size());
for (Method method : dispatch.keySet()) {
method.setAccessible(true);
result.put(method, method);
}
return result;
}
/**
* Process all methods in the target so that appropriate setters are created.
*/
private static Map<Method, Setter> toSetters(
SetterFactory setterFactory, Target<?> target, Set<Method> methods) {
Map<Method, Setter> result = new LinkedHashMap<>(methods.size());
for (Method method : methods) {
method.setAccessible(true);
result.put(method, setterFactory.create(target, method));
}
return result;
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
// early exit if the invoked method is from java.lang.Object
// code is the same as ReflectiveFeign.FeignInvocationHandler
if (EQUALS.equals(method.getName())) {
try {
Object otherHandler = args.length > 0 && args[0] != null
? Proxy.getInvocationHandler(args[0]) : null;
return equals(otherHandler);
} catch (IllegalArgumentException e) {
return false;
}
} else if (HASH_CODE.equals(method.getName())) {
return hashCode();
} else if (TO_STRING.equals(method.getName())) {
return toString();
}
HystrixCommand<Object> hystrixCommand = new HystrixCommand<Object>(setterMethodMap.get(method)) {
@Override
protected Object run() throws Exception {
try {
return PigxHystrixInvocationHandler.this.dispatch.get(method).invoke(args);
} catch (Exception e) {
throw e;
} catch (Throwable t) {
throw (Error) t;
}
}
@Override
@Nullable
@SuppressWarnings("unchecked")
protected Object getFallback() {
Object fallback;
try {
if (fallbackFactory == null) {
fallback = PigxFeginFallbackFactory.INSTANCE.create(target.type(), getExecutionException());
} else {
fallback = fallbackFactory.create(getExecutionException());
}
Object result = fallbackMethodMap.get(method).invoke(fallback, args);
if (isReturnsHystrixCommand(method)) {
return ((HystrixCommand) result).execute();
} else if (isReturnsObservable(method)) {
// Create a cold Observable
return ((Observable) result).toBlocking().first();
} else if (isReturnsSingle(method)) {
// Create a cold Observable as a Single
return ((Single) result).toObservable().toBlocking().first();
} else if (isReturnsCompletable(method)) {
((Completable) result).await();
return null;
} else {
return result;
}
} catch (IllegalAccessException e) {
// shouldn't happen as method is public due to being an interface
throw new AssertionError(e);
} catch (InvocationTargetException e) {
// Exceptions on fallback are tossed by Hystrix
throw new AssertionError(e.getCause());
}
}
};
if (isReturnsHystrixCommand(method)) {
return hystrixCommand;
} else if (isReturnsObservable(method)) {
// Create a cold Observable
return hystrixCommand.toObservable();
} else if (isReturnsSingle(method)) {
// Create a cold Observable as a Single
return hystrixCommand.toObservable().toSingle();
} else if (isReturnsCompletable(method)) {
return hystrixCommand.toObservable().toCompletable();
}
return hystrixCommand.execute();
}
private boolean isReturnsCompletable(Method method) {
return Completable.class.isAssignableFrom(method.getReturnType());
}
private boolean isReturnsHystrixCommand(Method method) {
return HystrixCommand.class.isAssignableFrom(method.getReturnType());
}
private boolean isReturnsObservable(Method method) {
return Observable.class.isAssignableFrom(method.getReturnType());
}
private boolean isReturnsSingle(Method method) {
return Single.class.isAssignableFrom(method.getReturnType());
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PigxHystrixInvocationHandler) {
PigxHystrixInvocationHandler other = (PigxHystrixInvocationHandler) obj;
return target.equals(other.target);
}
return false;
}
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public String toString() {
return target.toString();
}
}
@@ -0,0 +1,33 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
/**
* Hystrix 默认 fallback
* <p>
* DefaultProperties: https://github.com/Netflix/Hystrix/issues/1446
*
* @author L.cm
*/
@NonNullApi
@NonNullFields
package com.pig4cloud.pigx.common.security.feign;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;
@@ -20,12 +20,12 @@ package com.pig4cloud.pigx.common.security.mobile;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.AuthenticationEntryPoint;
@@ -62,11 +62,12 @@ public class MobileAuthenticationFilter extends AbstractAuthenticationProcessing
}
@Override
@SneakyThrows
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
HttpServletResponse response) {
if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
"Authentication method not supported: " + request.getMethod());
}
String mobile = obtainMobile(request);
@@ -93,11 +94,11 @@ public class MobileAuthenticationFilter extends AbstractAuthenticationProcessing
logger.debug("Authentication request failed: " + failed);
eventPublisher.publishAuthenticationFailure(new BadCredentialsException(failed.getMessage(), failed),
new PreAuthenticatedAuthenticationToken("access-token", "N/A"));
new PreAuthenticatedAuthenticationToken("access-token", "N/A"));
try {
authenticationEntryPoint.commence(request, response,
new UsernameNotFoundException(failed.getMessage(), failed));
new UsernameNotFoundException(failed.getMessage(), failed));
} catch (Exception e) {
logger.error("authenticationEntryPoint handle error:{}", failed);
}
@@ -21,12 +21,12 @@ import com.pig4cloud.pigx.common.security.component.PigxPreAuthenticationChecks;
import com.pig4cloud.pigx.common.security.service.PigxUserDetailsService;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsChecker;
@@ -47,7 +47,8 @@ public class MobileAuthenticationProvider implements AuthenticationProvider {
private PigxUserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
@SneakyThrows
public Authentication authenticate(Authentication authentication) {
MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;
String principal = mobileAuthenticationToken.getPrincipal().toString();
@@ -17,6 +17,7 @@
package com.pig4cloud.pigx.common.security.mobile;
import lombok.SneakyThrows;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
@@ -30,46 +31,47 @@ import java.util.Collection;
*/
public class MobileAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Object principal;
private final Object principal;
public MobileAuthenticationToken(String mobile) {
super(null);
this.principal = mobile;
setAuthenticated(false);
}
public MobileAuthenticationToken(String mobile) {
super(null);
this.principal = mobile;
setAuthenticated(false);
}
public MobileAuthenticationToken(Object principal,
public MobileAuthenticationToken(Object principal,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
super.setAuthenticated(true);
}
super(authorities);
this.principal = principal;
super.setAuthenticated(true);
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getCredentials() {
return null;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException(
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
}
@Override
@SneakyThrows
public void setAuthenticated(boolean isAuthenticated) {
if (isAuthenticated) {
throw new IllegalArgumentException(
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
}
super.setAuthenticated(false);
}
super.setAuthenticated(false);
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
}
}
@@ -18,6 +18,7 @@
package com.pig4cloud.pigx.common.security.service;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import lombok.SneakyThrows;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.provider.ClientDetails;
@@ -45,8 +46,9 @@ public class PigxClientDetailsService extends JdbcClientDetailsService {
* @throws InvalidClientException
*/
@Override
@SneakyThrows
@Cacheable(value = SecurityConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null")
public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException {
public ClientDetails loadClientByClientId(String clientId) {
return super.loadClientByClientId(clientId);
}
}
@@ -26,6 +26,7 @@ import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
@@ -60,7 +61,8 @@ public class PigxUserDetailsServiceImpl implements PigxUserDetailsService {
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
@SneakyThrows
public UserDetails loadUserByUsername(String username) {
Cache cache = cacheManager.getCache("user_details");
if (cache != null && cache.get(username) != null) {
return (PigxUser) cache.get(username).get();
@@ -81,7 +83,8 @@ public class PigxUserDetailsServiceImpl implements PigxUserDetailsService {
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserBySocial(String inStr) throws UsernameNotFoundException {
@SneakyThrows
public UserDetails loadUserBySocial(String inStr) {
return getUserDetails(remoteUserService.social(inStr, SecurityConstants.FROM_IN));
}
@@ -19,6 +19,7 @@ package com.pig4cloud.pigx.common.security.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
@@ -43,8 +44,8 @@ public class AuthUtils {
* @throws RuntimeException if the Basic header is not present or is not valid
* Base64
*/
public String[] extractAndDecodeHeader(String header)
throws IOException {
@SneakyThrows
public String[] extractAndDecodeHeader(String header) {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
@@ -70,10 +71,9 @@ public class AuthUtils {
*
* @param request
* @return
* @throws IOException
*/
public String[] extractAndDecodeHeader(HttpServletRequest request)
throws IOException {
@SneakyThrows
public String[] extractAndDecodeHeader(HttpServletRequest request) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
if (header == null || !header.startsWith(BASIC_)) {
@@ -0,0 +1,90 @@
/*
* *************************************************************************
* Copyright (c) 2018-2025, dreamlu.net All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: chunmeng.lu (qq596392912@gmail.com)
* *************************************************************************
*/
package com.pig4cloud.pigx.common.security.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Queue;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* 参考tomcat8中的并发DateFormat
* <p>
* {@link SimpleDateFormat}的线程安全包装器。
* 不使用ThreadLocal,创建足够的SimpleDateFormat对象来满足并发性要求。
*
* @author L.cm
*/
public class ConcurrentDateFormat {
private final String format;
private final Locale locale;
private final TimeZone timezone;
private final Queue<SimpleDateFormat> queue = new ConcurrentLinkedQueue<>();
private ConcurrentDateFormat(String format, Locale locale, TimeZone timezone) {
this.format = format;
this.locale = locale;
this.timezone = timezone;
SimpleDateFormat initial = createInstance();
queue.add(initial);
}
public static ConcurrentDateFormat of(String format) {
return new ConcurrentDateFormat(format, Locale.getDefault(), TimeZone.getDefault());
}
public static ConcurrentDateFormat of(String format, TimeZone timezone) {
return new ConcurrentDateFormat(format, Locale.getDefault(), timezone);
}
public static ConcurrentDateFormat of(String format, Locale locale, TimeZone timezone) {
return new ConcurrentDateFormat(format, locale, timezone);
}
public String format(Date date) {
SimpleDateFormat sdf = queue.poll();
if (sdf == null) {
sdf = createInstance();
}
String result = sdf.format(date);
queue.add(sdf);
return result;
}
public Date parse(String source) throws ParseException {
SimpleDateFormat sdf = queue.poll();
if (sdf == null) {
sdf = createInstance();
}
Date result = sdf.parse(source);
queue.add(sdf);
return result;
}
private SimpleDateFormat createInstance() {
SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
sdf.setTimeZone(timezone);
return sdf;
}
}
@@ -1,3 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pig4cloud.pigx.common.security.feign.PigxFeignClientConfiguration,\
com.pig4cloud.pigx.common.security.feign.PigxFeginConfiguration,\
com.pig4cloud.pigx.common.security.service.PigxUserDetailsServiceImpl
@@ -21,8 +21,7 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
*@author LCN on 2017/6/26.
*
* @author LCN on 2017/6/26.
* @author LCN
* @since 4.1.0
*/
@@ -18,6 +18,7 @@
package com.pig4cloud.pigx.common.transaction.tx.springcloud.http;
import com.codingapi.tx.aop.bean.TxTransactionLocal;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
@@ -34,8 +35,10 @@ import java.io.IOException;
*/
@Slf4j
public class TransactionHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
@SneakyThrows
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
TxTransactionLocal txTransactionLocal = TxTransactionLocal.current();
String groupId = txTransactionLocal == null ? null : txTransactionLocal.getGroupId();
@@ -17,6 +17,7 @@
package com.pig4cloud.pigx.common.transaction.tx.springcloud.interceptor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -41,17 +42,18 @@ public class TransactionAspect implements Ordered {
@Autowired
private TxManagerInterceptor txManagerInterceptor;
@SneakyThrows
@Around("@annotation(com.codingapi.tx.annotation.TxTransaction)")
public Object transactionRunning(ProceedingJoinPoint point) throws Throwable {
public Object transactionRunning(ProceedingJoinPoint point) {
log.debug("annotation-TransactionRunning-start---->");
Object obj = txManagerInterceptor.around(point);
log.debug("annotation-TransactionRunning-end---->");
return obj;
}
@SneakyThrows
@Around("this(com.codingapi.tx.annotation.ITxTransaction) && execution( * *(..))")
public Object around(ProceedingJoinPoint point) throws Throwable {
public Object around(ProceedingJoinPoint point) {
log.debug("interface-ITransactionRunning-start---->");
Object obj = txManagerInterceptor.around(point);
log.debug("interface-ITransactionRunning-end---->");
@@ -18,6 +18,7 @@
package com.pig4cloud.pigx.common.transaction.tx.springcloud.interceptor;
import com.codingapi.tx.aop.service.AspectBeforeService;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -39,7 +40,8 @@ public class TxManagerInterceptor {
@Autowired
private AspectBeforeService aspectBeforeService;
public Object around(ProceedingJoinPoint point) throws Throwable {
@SneakyThrows
public Object around(ProceedingJoinPoint point) {
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String groupId = request.getHeader("tx-group");