浏览代码

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
冷冷 6 年之前
父节点
当前提交
2b2507a068
共有 85 个文件被更改,包括 1423 次插入629 次删除
  1. 1 1
      doc/db/2pigxx.sql
  2. 13 1
      pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java
  3. 5 2
      pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/WebSecurityConfigurer.java
  4. 5 0
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java
  5. 1 1
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/SpringContextHolder.java
  6. 3 1
      pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/WebUtils.java
  7. 3 1
      pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/datascope/DataScopeInterceptor.java
  8. 14 2
      pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/mybatis/MybatisPlusConfig.java
  9. 29 0
      pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantConfigProperties.java
  10. 6 5
      pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantHandler.java
  11. 3 3
      pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantContextHolderFilter.java
  12. 1 0
      pigx-common/pigx-common-data/src/main/resources/META-INF/spring.factories
  13. 16 15
      pigx-common/pigx-common-job/src/main/java/com/pig4cloud/pigx/common/job/jobinit/AbstractJobInitialization.java
  14. 3 2
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java
  15. 8 3
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java
  16. 6 6
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogEvent.java
  17. 1 2
      pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java
  18. 20 13
      pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/http/MinioEndpoint.java
  19. 44 46
      pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java
  20. 3 1
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxAuth2ExceptionSerializer.java
  21. 3 2
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerConfigurerAdapter.java
  22. 3 1
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxSecurityInnerAspect.java
  23. 1 1
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxWebResponseExceptionTranslator.java
  24. 3 1
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/ResourceAuthExceptionEntryPoint.java
  25. 68 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginConfiguration.java
  26. 129 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginErrorDecoder.java
  27. 57 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginException.java
  28. 57 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginFallbackFactory.java
  29. 0 47
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignClientConfiguration.java
  30. 38 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignFallbackMethod.java
  31. 289 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixFeign.java
  32. 217 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixInvocationHandler.java
  33. 33 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/package-info.java
  34. 6 5
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationFilter.java
  35. 3 2
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationProvider.java
  36. 34 32
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationToken.java
  37. 3 1
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxClientDetailsService.java
  38. 5 2
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsServiceImpl.java
  39. 5 5
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/AuthUtils.java
  40. 90 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/ConcurrentDateFormat.java
  41. 1 1
      pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories
  42. 1 2
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/TransactionConfiguration.java
  43. 4 1
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/http/TransactionHttpRequestInterceptor.java
  44. 5 3
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TransactionAspect.java
  45. 3 1
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TxManagerInterceptor.java
  46. 2 2
      pigx-config/src/main/resources/config/application-dev.yml
  47. 8 0
      pigx-config/src/main/resources/config/pigx-activiti-dev.yml
  48. 19 6
      pigx-config/src/main/resources/config/pigx-upms-biz-dev.yml
  49. 7 5
      pigx-eureka/src/main/java/com/pig4cloud/pigx/eureka/security/WebSecurityConfig.java
  50. 3 1
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java
  51. 3 2
      pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ValidateCodeGatewayFilter.java
  52. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysDept.java
  53. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysDeptRelation.java
  54. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysDict.java
  55. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysMenu.java
  56. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysOauthClientDetails.java
  57. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysRole.java
  58. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysRoleMenu.java
  59. 4 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysRouteConf.java
  60. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysSocialDetails.java
  61. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java
  62. 0 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserRole.java
  63. 1 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java
  64. 3 2
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteTokenService.java
  65. 3 4
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java
  66. 0 38
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteLogServiceFallbackFactory.java
  67. 0 38
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteTokenServiceFallbackFactory.java
  68. 0 38
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteUserServiceFallbackFactory.java
  69. 0 51
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java
  70. 0 65
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteTokenServiceFallbackImpl.java
  71. 0 79
      pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java
  72. 0 7
      pigx-upms/pigx-upms-api/src/main/resources/META-INF/spring.factories
  73. 10 1
      pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/ActivitiConfig.java
  74. 66 0
      pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/WebSocketConfig.java
  75. 11 0
      pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/listener/LeaveProcessTaskListener.java
  76. 4 2
      pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/controller/SysGeneratorController.java
  77. 7 3
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/controller/AdminController.java
  78. 1 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiAdminService.java
  79. 3 1
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiAdminServiceImpl.java
  80. 5 3
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/service/impl/CompensateServiceImpl.java
  81. 5 13
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/TxManagerSenderServiceImpl.java
  82. 2 12
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ChannelSender.java
  83. 10 12
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/handler/TxCoreServerHandler.java
  84. 1 6
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/BaseSignalTaskService.java
  85. 2 2
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/NettyServerServiceImpl.java

文件差异内容过多而无法显示
+ 1 - 1
doc/db/2pigxx.sql


+ 13 - 1
pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java

@@ -26,6 +26,7 @@ import com.pig4cloud.pigx.common.security.service.PigxClientDetailsService;
 import com.pig4cloud.pigx.common.security.service.PigxUser;
 import com.pig4cloud.pigx.common.security.service.PigxUserDetailsService;
 import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.data.redis.connection.RedisConnectionFactory;
@@ -62,7 +63,8 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
 	private final RedisConnectionFactory redisConnectionFactory;
 
 	@Override
-	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
+	@SneakyThrows
+	public void configure(ClientDetailsServiceConfigurer clients) {
 		PigxClientDetailsService clientDetailsService = new PigxClientDetailsService(dataSource);
 		clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT);
 		clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT);
@@ -102,9 +104,19 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
 		return tokenStore;
 	}
 
+	/**
+	 * token增强,客户端模式不增强。
+	 *
+	 * @return TokenEnhancer
+	 */
 	@Bean
 	public TokenEnhancer tokenEnhancer() {
 		return (accessToken, authentication) -> {
+			if (SecurityConstants.CLIENT_CREDENTIALS
+					.equals(authentication.getOAuth2Request().getGrantType())) {
+				return accessToken;
+			}
+
 			final Map<String, Object> additionalInfo = new HashMap<>(8);
 			PigxUser pigxUser = (PigxUser) authentication.getUserAuthentication().getPrincipal();
 			additionalInfo.put("user_id", pigxUser.getId());

+ 5 - 2
pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/WebSecurityConfigurer.java

@@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.pig4cloud.pigx.common.security.handler.MobileLoginSuccessHandler;
 import com.pig4cloud.pigx.common.security.mobile.MobileSecurityConfigurer;
 import com.pig4cloud.pigx.common.security.service.PigxUserDetailsService;
+import lombok.SneakyThrows;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -59,7 +60,8 @@ public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
 	private AuthorizationServerTokenServices defaultAuthorizationServerTokenServices;
 
 	@Override
-	protected void configure(HttpSecurity http) throws Exception {
+	@SneakyThrows
+	protected void configure(HttpSecurity http) {
 		http
 			.formLogin()
 			.loginPage("/token/login")
@@ -87,7 +89,8 @@ public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
 
 	@Bean
 	@Override
-	public AuthenticationManager authenticationManagerBean() throws Exception {
+	@SneakyThrows
+	public AuthenticationManager authenticationManagerBean() {
 		return super.authenticationManagerBean();
 	}
 

+ 5 - 0
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java

@@ -120,4 +120,9 @@ public interface SecurityConstants {
 	 */
 	String RESOURCE_SERVER_CONFIGURER = "resourceServerConfigurerAdapter";
 
+	/**
+	 * 客户端模式
+	 */
+	String CLIENT_CREDENTIALS = "client_credentials";
+
 }

+ 1 - 1
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/SpringContextHolder.java

@@ -95,7 +95,7 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
 	 * 实现DisposableBean接口, 在Context关闭时清理静态变量.
 	 */
 	@Override
-	public void destroy() throws Exception {
+	public void destroy() {
 		SpringContextHolder.clearHolder();
 	}
 

+ 3 - 1
pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/WebUtils.java

@@ -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_)) {

+ 3 - 1
pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/datascope/DataScopeInterceptor.java

@@ -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);

+ 14 - 2
pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/mybatis/MybatisPlusConfig.java

@@ -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;

+ 29 - 0
pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantConfigProperties.java

@@ -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<>();
+}

+ 6 - 5
pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/PigxTenantHandler.java

@@ -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);
 	}
 }

+ 3 - 3
pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/tenant/TenantContextHolderFilter.java

@@ -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;
 

+ 1 - 0
pigx-common/pigx-common-data/src/main/resources/META-INF/spring.factories

@@ -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

+ 16 - 15
pigx-common/pigx-common-job/src/main/java/com/pig4cloud/pigx/common/job/jobinit/AbstractJobInitialization.java

@@ -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);
 		}

+ 3 - 2
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java

@@ -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);
 	}
 }

+ 8 - 3
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java

@@ -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;
 	}
 

+ 6 - 6
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogEvent.java

@@ -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;
 }

+ 1 - 2
pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java

@@ -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);
 	}
 }

+ 20 - 13
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/http/MinioEndpoint.java

@@ -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);
 	}

+ 44 - 46
pigx-common/pigx-common-minio/src/main/java/com/pig4cloud/common/minio/service/MinioTemplate.java

@@ -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);
 	}
+
 }

+ 3 - 1
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxAuth2ExceptionSerializer.java

@@ -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());

+ 3 - 2
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerConfigurerAdapter.java

@@ -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>

+ 3 - 1
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxSecurityInnerAspect.java

@@ -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());

+ 1 - 1
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxWebResponseExceptionTranslator.java

@@ -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);

+ 3 - 1
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/ResourceAuthExceptionEntryPoint.java

@@ -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<>();

+ 68 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginConfiguration.java

@@ -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());
+		}
+	}
+
+}

+ 129 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginErrorDecoder.java

@@ -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;
+			}
+		}
+	}
+}

+ 57 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginException.java

@@ -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;
+	}
+}

+ 57 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginFallbackFactory.java

@@ -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;
+	}
+}

+ 0 - 47
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignClientConfiguration.java

@@ -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);
-	}
-}

+ 38 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignFallbackMethod.java

@@ -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;
+	}
+}

+ 289 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixFeign.java

@@ -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);
+		}
+	}
+
+}

+ 217 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixInvocationHandler.java

@@ -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();
+	}
+}

+ 33 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/package-info.java

@@ -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;

+ 6 - 5
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationFilter.java

@@ -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);
 			}

+ 3 - 2
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationProvider.java

@@ -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();

+ 34 - 32
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/mobile/MobileAuthenticationToken.java

@@ -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();
+	}
 }
 

+ 3 - 1
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxClientDetailsService.java

@@ -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);
 	}
 }

+ 5 - 2
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsServiceImpl.java

@@ -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));
 	}
 

+ 5 - 5
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/AuthUtils.java

@@ -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_)) {

+ 90 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/ConcurrentDateFormat.java

@@ -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 - 1
pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories

@@ -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

+ 1 - 2
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/TransactionConfiguration.java

@@ -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
  */

+ 4 - 1
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/http/TransactionHttpRequestInterceptor.java

@@ -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();

+ 5 - 3
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TransactionAspect.java

@@ -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---->");

+ 3 - 1
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TxManagerInterceptor.java

@@ -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");

+ 2 - 2
pigx-config/src/main/resources/config/application-dev.yml

@@ -99,8 +99,8 @@ security:
     client:
       # 默认放行url,如果子模块重写这里的配置就会被覆盖
       ignore-urls:
-        - '/actuator/**'
-        - '/v2/api-docs'
+        - /actuator/**
+        - /v2/api-docs
     resource:
       loadBalanced: true
       token-info-uri: http://pigx-auth/oauth/check_token

+ 8 - 0
pigx-config/src/main/resources/config/pigx-activiti-dev.yml

@@ -13,6 +13,7 @@ security:
         - '/task/view/*'
         - '/process/resource/**'
         - '/modeler.html'
+        - '/ws/**'
 spring:
   autoconfigure:
     exclude: org.activiti.spring.boot.SecurityAutoConfiguration
@@ -24,3 +25,10 @@ spring:
     username: root
     password: root
     url: jdbc:mysql://pigx-mysql:3306/pigxx_ac?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
+
+# 租户表维护
+pigx:
+  tenant:
+    column: tenant_id
+    tables:
+      - oa_leave_bill

+ 19 - 6
pigx-config/src/main/resources/config/pigx-upms-biz-dev.yml

@@ -7,12 +7,12 @@ security:
       scope: server
       # 默认放行url,子模块重写时application-dev.yml中的公共配置会被覆盖,所以要把公共配置中的放行url再写一次
       ignore-urls:
-        - '/actuator/**'
-        - '/v2/api-docs'
-        - '/user/info/*'
-        - '/social/info/*'
-        - '/mobile/*'
-        - '/log/save'
+        - /actuator/**
+        - /v2/api-docs
+        - /user/info/*
+        - /social/info/*
+        - /mobile/*
+        - /log/save
 
 # 数据源
 spring:
@@ -44,3 +44,16 @@ minio:
 logging:
   level:
     com.pig4cloud.pigx.admin.mapper: debug
+
+# 租户表维护
+pigx:
+  tenant:
+    column: tenant_id
+    tables:
+      - sys_user
+      - sys_role
+      - sys_dept
+      - sys_log
+      - sys_social_details
+      - sys_dict
+      - sys_log

+ 7 - 5
pigx-eureka/src/main/java/com/pig4cloud/pigx/eureka/security/WebSecurityConfig.java

@@ -22,6 +22,7 @@ package com.pig4cloud.pigx.eureka.security;
  * @date 2018/7/12
  */
 
+import lombok.SneakyThrows;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@@ -29,11 +30,12 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
 @EnableWebSecurity
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 	@Override
-	protected void configure(HttpSecurity http) throws Exception {
+	@SneakyThrows
+	protected void configure(HttpSecurity http) {
 		http.csrf().disable()
-			.authorizeRequests()
-			.antMatchers("/actuator/**").permitAll()
-			.anyRequest()
-			.authenticated().and().httpBasic();
+				.authorizeRequests()
+				.antMatchers("/actuator/**").permitAll()
+				.anyRequest()
+				.authenticated().and().httpBasic();
 	}
 }

+ 3 - 1
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java

@@ -22,6 +22,7 @@ import cn.hutool.core.util.CharsetUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.gateway.filter.GatewayFilter;
@@ -51,7 +52,8 @@ public class PasswordDecoderFilter extends AbstractGatewayFilterFactory {
 	@Value("${security.encode.key:1234567812345678}")
 	private String encodeKey;
 
-	private static String decryptAES(String data, String pass) throws Exception {
+	@SneakyThrows
+	private static String decryptAES(String data, String pass) {
 		Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
 		SecretKeySpec keyspec = new SecretKeySpec(pass.getBytes(), KEY_ALGORITHM);
 		IvParameterSpec ivspec = new IvParameterSpec(pass.getBytes());

+ 3 - 2
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ValidateCodeGatewayFilter.java

@@ -27,6 +27,7 @@ import com.pig4cloud.pigx.common.core.util.R;
 import com.pig4cloud.pigx.common.core.util.WebUtils;
 import com.pig4cloud.pigx.gateway.config.FilterIgnorePropertiesConfig;
 import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.cloud.gateway.filter.GatewayFilter;
 import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
@@ -97,9 +98,9 @@ public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {
 	 * 检查code
 	 *
 	 * @param request
-	 * @throws ValidateCodeException 校验异常
 	 */
-	private void checkCode(ServerHttpRequest request) throws ValidateCodeException {
+	@SneakyThrows
+	private void checkCode(ServerHttpRequest request) {
 		String code = request.getQueryParams().getFirst("code");
 
 		if (StrUtil.isBlank(code)) {

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysDept.java

@@ -22,7 +22,6 @@ package com.pig4cloud.pigx.admin.api.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -40,7 +39,6 @@ import java.time.LocalDateTime;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_dept")
 public class SysDept extends Model<SysDept> {
 
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysDeptRelation.java

@@ -19,7 +19,6 @@
 
 package com.pig4cloud.pigx.admin.api.entity;
 
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -34,7 +33,6 @@ import lombok.EqualsAndHashCode;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_dept_relation")
 public class SysDeptRelation extends Model<SysDeptRelation> {
 
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysDict.java

@@ -22,7 +22,6 @@ package com.pig4cloud.pigx.admin.api.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -40,7 +39,6 @@ import java.time.LocalDateTime;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_dict")
 public class SysDict extends Model<SysDict> {
 
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysMenu.java

@@ -22,7 +22,6 @@ package com.pig4cloud.pigx.admin.api.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -41,7 +40,6 @@ import java.time.LocalDateTime;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_menu")
 public class SysMenu extends Model<SysMenu> {
 
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysOauthClientDetails.java

@@ -21,7 +21,6 @@ package com.pig4cloud.pigx.admin.api.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -39,7 +38,6 @@ import java.io.Serializable;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_oauth_client_details")
 public class SysOauthClientDetails extends Model<SysOauthClientDetails> {
 
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysRole.java

@@ -22,7 +22,6 @@ package com.pig4cloud.pigx.admin.api.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -42,7 +41,6 @@ import java.time.LocalDateTime;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_role")
 public class SysRole extends Model<SysRole> {
 
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysRoleMenu.java

@@ -19,7 +19,6 @@
 
 package com.pig4cloud.pigx.admin.api.entity;
 
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -34,7 +33,6 @@ import lombok.EqualsAndHashCode;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_role_menu")
 public class SysRoleMenu extends Model<SysRoleMenu> {
 
 	private static final long serialVersionUID = 1L;

+ 4 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysRouteConf.java

@@ -17,7 +17,10 @@
 
 package com.pig4cloud.pigx.admin.api.entity;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Data;
@@ -32,7 +35,6 @@ import java.time.LocalDateTime;
  * @date 2018-11-06 10:17:18
  */
 @Data
-@TableName("sys_route_conf")
 @EqualsAndHashCode(callSuper = true)
 public class SysRouteConf extends Model<SysRouteConf> {
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysSocialDetails.java

@@ -19,7 +19,6 @@ package com.pig4cloud.pigx.admin.api.entity;
 
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -35,7 +34,6 @@ import java.time.LocalDateTime;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_social_details")
 public class SysSocialDetails extends Model<SysSocialDetails> {
 	private static final long serialVersionUID = 1L;
 

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java

@@ -22,7 +22,6 @@ package com.pig4cloud.pigx.admin.api.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Data;
 
@@ -38,7 +37,6 @@ import java.time.LocalDateTime;
  * @since 2017-10-29
  */
 @Data
-@TableName("sys_user")
 public class SysUser implements Serializable {
 
 	private static final long serialVersionUID = 1L;

+ 0 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUserRole.java

@@ -19,7 +19,6 @@
 
 package com.pig4cloud.pigx.admin.api.entity;
 
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -34,7 +33,6 @@ import lombok.EqualsAndHashCode;
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("sys_user_role")
 public class SysUserRole extends Model<SysUserRole> {
 
 	private static final long serialVersionUID = 1L;

+ 1 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java

@@ -20,7 +20,6 @@
 package com.pig4cloud.pigx.admin.api.feign;
 
 import com.pig4cloud.pigx.admin.api.entity.SysLog;
-import com.pig4cloud.pigx.admin.api.feign.factory.RemoteLogServiceFallbackFactory;
 import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
 import com.pig4cloud.pigx.common.core.constant.ServiceNameConstants;
 import com.pig4cloud.pigx.common.core.util.R;
@@ -33,7 +32,7 @@ import org.springframework.web.bind.annotation.RequestHeader;
  * @author lengleng
  * @date 2018/6/28
  */
-@FeignClient(value = ServiceNameConstants.UMPS_SERVICE, fallbackFactory = RemoteLogServiceFallbackFactory.class)
+@FeignClient(value = ServiceNameConstants.UMPS_SERVICE)
 public interface RemoteLogService {
 	/**
 	 * 保存日志

+ 3 - 2
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteTokenService.java

@@ -18,7 +18,6 @@
 package com.pig4cloud.pigx.admin.api.feign;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pigx.admin.api.feign.factory.RemoteTokenServiceFallbackFactory;
 import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
 import com.pig4cloud.pigx.common.core.constant.ServiceNameConstants;
 import com.pig4cloud.pigx.common.core.util.R;
@@ -31,13 +30,14 @@ import java.util.Map;
  * @author lengleng
  * @date 2018/9/4
  */
-@FeignClient(value = ServiceNameConstants.AUTH_SERVICE, fallbackFactory = RemoteTokenServiceFallbackFactory.class)
+@FeignClient(value = ServiceNameConstants.AUTH_SERVICE)
 public interface RemoteTokenService {
 	/**
 	 * 分页查询token 信息
 	 *
 	 * @param from   内部调用标志
 	 * @param params 分页参数
+	 * @param from   内部调用标志
 	 * @return page
 	 */
 	@PostMapping("/token/page")
@@ -48,6 +48,7 @@ public interface RemoteTokenService {
 	 *
 	 * @param from  内部调用标志
 	 * @param token token
+	 * @param from  内部调用标志
 	 * @return
 	 */
 	@DeleteMapping("/token/{token}")

+ 3 - 4
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java

@@ -21,7 +21,6 @@ package com.pig4cloud.pigx.admin.api.feign;
 
 import com.pig4cloud.pigx.admin.api.dto.UserInfo;
 import com.pig4cloud.pigx.admin.api.entity.SysUser;
-import com.pig4cloud.pigx.admin.api.feign.factory.RemoteUserServiceFallbackFactory;
 import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
 import com.pig4cloud.pigx.common.core.constant.ServiceNameConstants;
 import com.pig4cloud.pigx.common.core.util.R;
@@ -36,7 +35,7 @@ import java.util.List;
  * @author lengleng
  * @date 2018/6/22
  */
-@FeignClient(value = ServiceNameConstants.UMPS_SERVICE, fallbackFactory = RemoteUserServiceFallbackFactory.class)
+@FeignClient(value = ServiceNameConstants.UMPS_SERVICE)
 public interface RemoteUserService {
 	/**
 	 * 通过用户名查询用户、角色信息
@@ -47,7 +46,7 @@ public interface RemoteUserService {
 	 */
 	@GetMapping("/user/info/{username}")
 	R<UserInfo> info(@PathVariable("username") String username
-		, @RequestHeader(SecurityConstants.FROM) String from);
+			, @RequestHeader(SecurityConstants.FROM) String from);
 
 	/**
 	 * 通过社交账号或手机号查询用户、角色信息
@@ -58,7 +57,7 @@ public interface RemoteUserService {
 	 */
 	@GetMapping("/social/info/{inStr}")
 	R<UserInfo> social(@PathVariable("inStr") String inStr
-		, @RequestHeader(SecurityConstants.FROM) String from);
+			, @RequestHeader(SecurityConstants.FROM) String from);
 
 	/**
 	 * 查询上级部门的用户信息

+ 0 - 38
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteLogServiceFallbackFactory.java

@@ -1,38 +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.admin.api.feign.factory;
-
-import com.pig4cloud.pigx.admin.api.feign.RemoteLogService;
-import com.pig4cloud.pigx.admin.api.feign.fallback.RemoteLogServiceFallbackImpl;
-import feign.hystrix.FallbackFactory;
-import org.springframework.stereotype.Component;
-
-/**
- * @author lengleng
- * @date 2018/9/4
- */
-@Component
-public class RemoteLogServiceFallbackFactory implements FallbackFactory<RemoteLogService> {
-
-	@Override
-	public RemoteLogService create(Throwable throwable) {
-		RemoteLogServiceFallbackImpl remoteLogServiceFallback = new RemoteLogServiceFallbackImpl();
-		remoteLogServiceFallback.setCause(throwable);
-		return remoteLogServiceFallback;
-	}
-}

+ 0 - 38
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteTokenServiceFallbackFactory.java

@@ -1,38 +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.admin.api.feign.factory;
-
-import com.pig4cloud.pigx.admin.api.feign.RemoteTokenService;
-import com.pig4cloud.pigx.admin.api.feign.fallback.RemoteTokenServiceFallbackImpl;
-import feign.hystrix.FallbackFactory;
-import org.springframework.stereotype.Component;
-
-/**
- * @author lengleng
- * @date 2018/9/4
- */
-@Component
-public class RemoteTokenServiceFallbackFactory implements FallbackFactory<RemoteTokenService> {
-
-	@Override
-	public RemoteTokenService create(Throwable throwable) {
-		RemoteTokenServiceFallbackImpl remoteTokenServiceFallback = new RemoteTokenServiceFallbackImpl();
-		remoteTokenServiceFallback.setCause(throwable);
-		return remoteTokenServiceFallback;
-	}
-}

+ 0 - 38
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteUserServiceFallbackFactory.java

@@ -1,38 +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.admin.api.feign.factory;
-
-import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
-import com.pig4cloud.pigx.admin.api.feign.fallback.RemoteUserServiceFallbackImpl;
-import feign.hystrix.FallbackFactory;
-import org.springframework.stereotype.Component;
-
-/**
- * @author lengleng
- * @date 2018/9/1
- */
-@Component
-public class RemoteUserServiceFallbackFactory implements FallbackFactory<RemoteUserService> {
-
-	@Override
-	public RemoteUserService create(Throwable throwable) {
-		RemoteUserServiceFallbackImpl remoteUserServiceFallback = new RemoteUserServiceFallbackImpl();
-		remoteUserServiceFallback.setCause(throwable);
-		return remoteUserServiceFallback;
-	}
-}

+ 0 - 51
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java

@@ -1,51 +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.admin.api.feign.fallback;
-
-import com.pig4cloud.pigx.admin.api.entity.SysLog;
-import com.pig4cloud.pigx.admin.api.feign.RemoteLogService;
-import com.pig4cloud.pigx.common.core.util.R;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-/**
- * @author lengleng
- * @date 2018/6/26
- */
-@Slf4j
-@Component
-public class RemoteLogServiceFallbackImpl implements RemoteLogService {
-	@Setter
-	private Throwable cause;
-
-	/**
-	 * 保存日志
-	 *
-	 * @param sysLog
-	 * @param from
-	 * @return R
-	 */
-	@Override
-	public R<Boolean> saveLog(SysLog sysLog, String from) {
-		log.error("feign 插入日志失败", cause);
-		return null;
-	}
-}

+ 0 - 65
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteTokenServiceFallbackImpl.java

@@ -1,65 +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.admin.api.feign.fallback;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.pig4cloud.pigx.admin.api.feign.RemoteTokenService;
-import com.pig4cloud.pigx.common.core.util.R;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-
-/**
- * @author lengleng
- * @date 2018/9/4
- * feign token  fallback
- */
-@Slf4j
-@Component
-public class RemoteTokenServiceFallbackImpl implements RemoteTokenService {
-	@Setter
-	private Throwable cause;
-
-	/**
-	 * 分页查询token 信息
-	 *
-	 * @param params 分页参数
-	 * @param from   内部调用标志
-	 * @return page
-	 */
-	@Override
-	public R<Page> getTokenPage(Map<String, Object> params, String from) {
-		log.error("调用认证中心查询token 失败", cause);
-		return null;
-	}
-
-	/**
-	 * 删除token
-	 *
-	 * @param token
-	 * @param from  内部调用标志
-	 * @return
-	 */
-	@Override
-	public R<Boolean> removeTokenById(String token, String from) {
-		log.error("删除token 失败 {}", token, cause);
-		return null;
-	}
-}

+ 0 - 79
pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java

@@ -1,79 +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.admin.api.feign.fallback;
-
-import com.pig4cloud.pigx.admin.api.dto.UserInfo;
-import com.pig4cloud.pigx.admin.api.entity.SysUser;
-import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
-import com.pig4cloud.pigx.common.core.util.R;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-/**
- * @author lengleng
- * @date 2018/6/26
- */
-@Slf4j
-@Component
-public class RemoteUserServiceFallbackImpl implements RemoteUserService {
-	@Setter
-	private Throwable cause;
-
-	/**
-	 * 通过用户名查询用户、角色信息
-	 *
-	 * @param username 用户名
-	 * @param from     内外标志
-	 * @return R
-	 */
-	@Override
-	public R<UserInfo> info(String username, String from) {
-		log.error("feign 查询用户信息失败:{}", username, cause);
-		return null;
-	}
-
-	/**
-	 * 通过社交账号查询用户、角色信息
-	 *
-	 * @param inStr appid@code
-	 * @param from  内外标志
-	 * @return
-	 */
-	@Override
-	public R<UserInfo> social(String inStr, String from) {
-		log.error("feign 查询用户信息失败:{}", inStr, cause);
-		return null;
-	}
-
-	/**
-	 * 查询上级部门的用户信息
-	 *
-	 * @param username 用户名
-	 * @return R
-	 */
-	@Override
-	public R<List<SysUser>> ancestorUsers(String username) {
-		log.error("feign 查询用户上级部门用户列失败:{}", username, cause);
-		return null;
-	}
-}

+ 0 - 7
pigx-upms/pigx-upms-api/src/main/resources/META-INF/spring.factories

@@ -1,7 +0,0 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-  com.pig4cloud.pigx.admin.api.feign.fallback.RemoteUserServiceFallbackImpl,\
-  com.pig4cloud.pigx.admin.api.feign.fallback.RemoteLogServiceFallbackImpl,\
-  com.pig4cloud.pigx.admin.api.feign.fallback.RemoteTokenServiceFallbackImpl,\
-  com.pig4cloud.pigx.admin.api.feign.factory.RemoteUserServiceFallbackFactory,\
-  com.pig4cloud.pigx.admin.api.feign.factory.RemoteLogServiceFallbackFactory,\
-  com.pig4cloud.pigx.admin.api.feign.factory.RemoteTokenServiceFallbackFactory

+ 10 - 1
pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/ActivitiConfig.java

@@ -21,6 +21,9 @@ import lombok.AllArgsConstructor;
 import org.activiti.spring.SpringProcessEngineConfiguration;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.transaction.PlatformTransactionManager;
 
 import javax.sql.DataSource;
@@ -39,7 +42,7 @@ public class ActivitiConfig {
 	@Bean
 	public SpringProcessEngineConfiguration getProcessEngineConfiguration() {
 		SpringProcessEngineConfiguration config =
-			new SpringProcessEngineConfiguration();
+				new SpringProcessEngineConfiguration();
 		// 流程图字体设置
 		config.setActivityFontName("宋体");
 		config.setAnnotationFontName("宋体");
@@ -51,4 +54,10 @@ public class ActivitiConfig {
 		config.setDatabaseSchemaUpdate("true");
 		return config;
 	}
+
+	@Bean
+	@Primary
+	public TaskExecutor primaryTaskExecutor() {
+		return new ThreadPoolTaskExecutor();
+	}
 }

+ 66 - 0
pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/config/WebSocketConfig.java

@@ -0,0 +1,66 @@
+package com.pig4cloud.pigx.act.config;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.simp.config.ChannelRegistration;
+import org.springframework.messaging.simp.config.MessageBrokerRegistry;
+import org.springframework.messaging.simp.stomp.StompCommand;
+import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
+import org.springframework.messaging.support.ChannelInterceptor;
+import org.springframework.messaging.support.MessageHeaderAccessor;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
+import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
+import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
+
+/**
+ * @author new
+ * <p>
+ * WebSocket配置类
+ */
+@Slf4j
+@Configuration
+@AllArgsConstructor
+@EnableWebSocketMessageBroker
+public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
+	private RemoteTokenServices tokenService;
+
+	@Override
+	public void registerStompEndpoints(StompEndpointRegistry registry) {
+		registry.addEndpoint("/ws")
+				.setAllowedOrigins("*")
+				.withSockJS();
+	}
+
+	@Override
+	public void configureMessageBroker(MessageBrokerRegistry registry) {
+		registry.setUserDestinationPrefix("/task/");
+	}
+
+	@Override
+	public void configureClientInboundChannel(ChannelRegistration registration) {
+		registration.interceptors(new ChannelInterceptor() {
+			@Override
+			public Message<?> preSend(Message<?> message, MessageChannel channel) {
+				StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
+				if (StompCommand.CONNECT.equals(accessor.getCommand())) {
+					String tokens = accessor.getFirstNativeHeader("Authorization");
+					log.info("webSocket token is {}", tokens);
+					if (StrUtil.isBlank(tokens)) {
+						return null;
+					}
+					OAuth2Authentication auth2Authentication = tokenService.loadAuthentication(tokens.split(" ")[1]);
+					SecurityContextHolder.getContext().setAuthentication(auth2Authentication);
+					accessor.setUser(() -> (String) auth2Authentication.getPrincipal());
+				}
+				return message;
+			}
+		});
+	}
+}

+ 11 - 0
pigx-visual/pigx-activiti/src/main/java/com/pig4cloud/pigx/act/listener/LeaveProcessTaskListener.java

@@ -22,11 +22,14 @@ import com.pig4cloud.pigx.admin.api.entity.SysUser;
 import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
 import com.pig4cloud.pigx.common.core.util.R;
 import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
+import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
 import com.pig4cloud.pigx.common.security.util.SecurityUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.activiti.engine.delegate.DelegateTask;
 import org.activiti.engine.delegate.TaskListener;
+import org.springframework.messaging.simp.SimpMessagingTemplate;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -45,18 +48,26 @@ public class LeaveProcessTaskListener implements TaskListener {
 	 */
 	@Override
 	public void notify(DelegateTask delegateTask) {
+		SimpMessagingTemplate simpMessagingTemplate = SpringContextHolder.getBean(SimpMessagingTemplate.class);
 		RemoteUserService userService = SpringContextHolder.getBean(RemoteUserService.class);
 
 		R<List<SysUser>> result = userService.ancestorUsers(SecurityUtils.getUsername());
+		List<String> remindUserList = new ArrayList<>();
 
 		if (CollUtil.isEmpty(result.getData())) {
 			log.info("用户 {} 不存在上级,任务单由当前用户审批", SecurityUtils.getUsername());
 			delegateTask.addCandidateUser(SecurityUtils.getUsername());
+			remindUserList.add(SecurityUtils.getUsername());
 		} else {
 			List<String> userList = result.getData().stream().map(SysUser::getUsername).collect(Collectors.toList());
 			log.info("当前任务 {},由 {}处理", delegateTask.getId(), userList);
 			delegateTask.addCandidateUsers(userList);
+			remindUserList.addAll(userList);
 		}
 
+		remindUserList.forEach(user -> {
+			String target = String.format("%s-%s", SecurityUtils.getUsername(), TenantContextHolder.getTenantId());
+			simpMessagingTemplate.convertAndSendToUser(target, "/remind", delegateTask.getName());
+		});
 	}
 }

+ 4 - 2
pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/controller/SysGeneratorController.java

@@ -23,6 +23,7 @@ import com.pig4cloud.pigx.codegen.entity.GenConfig;
 import com.pig4cloud.pigx.codegen.service.SysGeneratorService;
 import com.pig4cloud.pigx.common.core.util.R;
 import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
 import org.springframework.http.HttpHeaders;
 import org.springframework.web.bind.annotation.*;
 
@@ -55,13 +56,14 @@ public class SysGeneratorController {
 	/**
 	 * 生成代码
 	 */
+	@SneakyThrows
 	@PostMapping("/code")
-	public void generatorCode(@RequestBody GenConfig genConfig, HttpServletResponse response) throws IOException {
+	public void generatorCode(@RequestBody GenConfig genConfig, HttpServletResponse response) {
 		byte[] data = sysGeneratorService.generatorCode(genConfig);
 
 		response.reset();
 		response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s.zip", genConfig.getTableName()));
-		response.addHeader(HttpHeaders.CONTENT_LENGTH,  String.valueOf(data.length));
+		response.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(data.length));
 		response.setContentType("application/octet-stream; charset=UTF-8");
 
 		IoUtil.write(response.getOutputStream(), Boolean.TRUE, data);

+ 7 - 3
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/controller/AdminController.java

@@ -25,6 +25,7 @@ import com.pig4cloud.pigx.manager.model.ModelInfo;
 import com.pig4cloud.pigx.manager.model.ModelName;
 import com.pig4cloud.pigx.manager.model.TxState;
 import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -89,18 +90,21 @@ public class AdminController {
 		return apiAdminService.modelInfos(path);
 	}
 
+	@SneakyThrows
 	@RequestMapping(value = "/compensate", method = RequestMethod.GET)
-	public boolean compensate(@RequestParam("path") String path) throws ServiceException {
+	public boolean compensate(@RequestParam("path") String path) {
 		return apiAdminService.compensate(path);
 	}
 
+	@SneakyThrows
 	@RequestMapping(value = "/delCompensate", method = RequestMethod.GET)
-	public boolean delCompensate(@RequestParam("path") String path) throws ServiceException {
+	public boolean delCompensate(@RequestParam("path") String path) {
 		return apiAdminService.delCompensate(path);
 	}
 
+	@SneakyThrows
 	@RequestMapping(value = "/hasCompensate", method = RequestMethod.GET)
-	public boolean hasCompensate() throws ServiceException {
+	public boolean hasCompensate() {
 		return apiAdminService.hasCompensate();
 	}
 }

+ 1 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiAdminService.java

@@ -21,6 +21,7 @@ import com.lorne.core.framework.exception.ServiceException;
 import com.pig4cloud.pigx.manager.compensate.model.TxModel;
 import com.pig4cloud.pigx.manager.model.ModelName;
 import com.pig4cloud.pigx.manager.model.TxState;
+import lombok.SneakyThrows;
 
 import java.util.List;
 import java.util.Map;

+ 3 - 1
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiAdminServiceImpl.java

@@ -28,6 +28,7 @@ import com.pig4cloud.pigx.manager.model.ModelName;
 import com.pig4cloud.pigx.manager.model.TxState;
 import com.pig4cloud.pigx.manager.redis.RedisServerService;
 import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
@@ -108,7 +109,8 @@ public class ApiAdminServiceImpl implements ApiAdminService {
 	}
 
 	@Override
-	public boolean compensate(String path) throws ServiceException {
+	@SneakyThrows
+	public boolean compensate(String path) {
 		return compensateService.executeCompensate(path);
 	}
 

+ 5 - 3
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/service/impl/CompensateServiceImpl.java

@@ -36,6 +36,7 @@ import com.pig4cloud.pigx.manager.model.ModelInfo;
 import com.pig4cloud.pigx.manager.model.ModelName;
 import com.pig4cloud.pigx.manager.netty.model.TxGroup;
 import com.pig4cloud.pigx.manager.netty.model.TxInfo;
+import lombok.SneakyThrows;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -309,7 +310,8 @@ public class CompensateServiceImpl implements CompensateService {
 
 
 	@Override
-	public boolean executeCompensate(String path) throws ServiceException {
+	@SneakyThrows
+	public boolean executeCompensate(String path) {
 
 		String json = compensateDao.getCompensate(path);
 		if (json == null) {
@@ -326,8 +328,8 @@ public class CompensateServiceImpl implements CompensateService {
 		return false;
 	}
 
-
-	private boolean executeCompensateMethod(String json) throws ServiceException {
+	@SneakyThrows
+	private boolean executeCompensateMethod(String json) {
 		JSONObject jsonObject = JSON.parseObject(json);
 
 		String model = jsonObject.getString("model");

+ 5 - 13
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/TxManagerSenderServiceImpl.java

@@ -301,19 +301,11 @@ public class TxManagerSenderServiceImpl implements TxManagerSenderService {
 
 
 	private ScheduledFuture schedule(final String key, int delayTime) {
-		ScheduledFuture future = executorService.schedule(new Runnable() {
-			@Override
-			public void run() {
-				Task task = ConditionUtils.getInstance().getTask(key);
-				if (task != null && !task.isNotify()) {
-					task.setBack(new IBack() {
-						@Override
-						public Object doing(Object... objs) throws Throwable {
-							return "-2";
-						}
-					});
-					task.signalTask();
-				}
+		ScheduledFuture future = executorService.schedule(() -> {
+			Task task = ConditionUtils.getInstance().getTask(key);
+			if (task != null && !task.isNotify()) {
+				task.setBack(objs -> "-2");
+				task.signalTask();
 			}
 		}, delayTime, TimeUnit.SECONDS);
 

+ 2 - 12
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ChannelSender.java

@@ -64,22 +64,12 @@ public class ChannelSender {
 			final String res = HttpUtils.post(url, "msg=" + msg + "&model=" + modelName);
 			if (StringUtils.isNotEmpty(res)) {
 				if (task != null) {
-					task.setBack(new IBack() {
-						@Override
-						public Object doing(Object... objs) throws Throwable {
-							return res;
-						}
-					});
+					task.setBack(objs -> res);
 					task.signalTask();
 				}
 			} else {
 				if (task != null) {
-					task.setBack(new IBack() {
-						@Override
-						public Object doing(Object... objs) throws Throwable {
-							return "-2";
-						}
-					});
+					task.setBack(objs -> "-2");
 					task.signalTask();
 				}
 			}

+ 10 - 12
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/handler/TxCoreServerHandler.java

@@ -32,6 +32,7 @@ import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
+import lombok.SneakyThrows;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -62,15 +63,10 @@ public class TxCoreServerHandler extends ChannelInboundHandlerAdapter { // (1)
 	}
 
 	@Override
-	public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
+	public void channelRead(final ChannelHandlerContext ctx, Object msg) {
 		final String json = SocketUtils.getJson(msg);
 		logger.debug("request->" + json);
-		threadPool.execute(new Runnable() {
-			@Override
-			public void run() {
-				service(json, ctx);
-			}
-		});
+		threadPool.execute(() -> service(json, ctx));
 	}
 
 	private void service(String json, ChannelHandlerContext ctx) {
@@ -95,7 +91,8 @@ public class TxCoreServerHandler extends ChannelInboundHandlerAdapter { // (1)
 	}
 
 	@Override
-	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+	@SneakyThrows
+	public void channelRegistered(ChannelHandlerContext ctx) {
 
 		//是否到达最大上线连接数
 		if (SocketManager.getInstance().isAllowConnection()) {
@@ -107,7 +104,8 @@ public class TxCoreServerHandler extends ChannelInboundHandlerAdapter { // (1)
 	}
 
 	@Override
-	public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
+	@SneakyThrows
+	public void channelUnregistered(ChannelHandlerContext ctx) {
 
 		SocketManager.getInstance().removeClient(ctx.channel());
 		String modelName = ctx.channel().remoteAddress().toString();
@@ -118,18 +116,18 @@ public class TxCoreServerHandler extends ChannelInboundHandlerAdapter { // (1)
 	}
 
 	@Override
-	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+	public void channelReadComplete(ChannelHandlerContext ctx) {
 		ctx.flush();
 	}
 
 	@Override
-	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
 		cause.printStackTrace();
 		//ctx.close();
 	}
 
 	@Override
-	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
 		//心跳配置
 		if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
 			IdleStateEvent event = (IdleStateEvent) evt;

+ 1 - 6
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/BaseSignalTaskService.java

@@ -32,12 +32,7 @@ public class BaseSignalTaskService {
 		final String data = params.getString("d");
 		Task task = ConditionUtils.getInstance().getTask(key);
 		if (task != null) {
-			task.setBack(new IBack() {
-				@Override
-				public Object doing(Object... objs) throws Throwable {
-					return data;
-				}
-			});
+			task.setBack(objs -> data);
 			task.signalTask();
 		}
 		return res;

+ 2 - 2
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/NettyServerServiceImpl.java

@@ -81,7 +81,7 @@ public class NettyServerServiceImpl implements NettyServerService, DisposableBea
 				.handler(new LoggingHandler(LogLevel.INFO))
 				.childHandler(new ChannelInitializer<SocketChannel>() {
 					@Override
-					public void initChannel(SocketChannel ch) throws Exception {
+					public void initChannel(SocketChannel ch) {
 						ch.pipeline().addLast("timeout", new IdleStateHandler(heartTime, heartTime, heartTime, TimeUnit.SECONDS));
 
 						ch.pipeline().addLast(new LengthFieldPrepender(4, false));
@@ -113,7 +113,7 @@ public class NettyServerServiceImpl implements NettyServerService, DisposableBea
 	}
 
 	@Override
-	public void destroy() throws Exception {
+	public void destroy() {
 		close();
 		threadPool.shutdown();
 	}