Sfoglia il codice sorgente

:recycle: 重构代码,重构自动降级

冷冷 6 anni fa
parent
commit
35e0c6327f
18 ha cambiato i file con 328 aggiunte e 866 eliminazioni
  1. 11 12
      pigx-common/pigx-common-security/pom.xml
  2. 11 13
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PermissionService.java
  3. 17 0
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerTokenRelayAutoConfiguration.java
  4. 4 25
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignConfiguration.java
  5. 0 129
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignErrorDecoder.java
  6. 0 57
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignException.java
  7. 0 57
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignFallbackFactory.java
  8. 0 38
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignFallbackMethod.java
  9. 0 289
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixFeign.java
  10. 0 217
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixInvocationHandler.java
  11. 4 7
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/ConcurrentDateFormat.java
  12. 11 13
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/SecurityUtils.java
  13. 5 8
      pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/package-info.java
  14. 45 0
      pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxFallbackFactory.java
  15. 81 0
      pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxFeignFallback.java
  16. 42 0
      pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxHystrixFeignTargeterConfiguration.java
  17. 96 0
      pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxHystrixTargeter.java
  18. 1 1
      pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories

+ 11 - 12
pigx-common/pigx-common-security/pom.xml

@@ -1,20 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~
   ~      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:
+  ~   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)
+  ~   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)
   ~
   -->
 

+ 11 - 13
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PermissionService.java

@@ -1,20 +1,18 @@
 /*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
  *
- *      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:
+ * 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)
- *
+ * 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.component;

+ 17 - 0
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerTokenRelayAutoConfiguration.java

@@ -1,3 +1,20 @@
+/*
+ *    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.component;
 
 import org.springframework.boot.autoconfigure.AutoConfigureAfter;

+ 4 - 25
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignConfiguration.java

@@ -1,37 +1,29 @@
 /*
- * *************************************************************************
- *   Copyright (c) 2018-2025, dreamlu.net All rights reserved.
+ *    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:
+ * 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
+ * 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: chunmeng.lu (qq596392912@gmail.com)
- * *************************************************************************
+ * Author: lengleng (wangiegie@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;
 
@@ -52,17 +44,4 @@ public class PigxFeignConfiguration {
 		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 PigxFeignErrorDecoder());
-		}
-	}
-
 }

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

@@ -1,129 +0,0 @@
-/*
- * *************************************************************************
- *   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 PigxFeignErrorDecoder extends ErrorDecoder.Default {
-	private final RetryAfterDecoder retryAfterDecoder = new RetryAfterDecoder();
-	private static final String REGEX = "^[0-9]+$";
-
-
-	@Override
-	public Exception decode(String methodKey, Response response) {
-		PigxFeignException exception = errorStatus(methodKey, response);
-		Date retryAfter = retryAfterDecoder.apply(firstOrNull(response.headers()));
-		return new RetryableException(exception.getMessage(), response.request().httpMethod(), exception, retryAfter);
-	}
-
-	private static PigxFeignException errorStatus(String methodKey, Response response) {
-		try {
-			if (response.body() != null) {
-				Reader reader = response.body().asReader();
-				return new PigxFeignException(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 PigxFeignException(message);
-	}
-
-	@Nullable
-	private <T> T firstOrNull(Map<String, Collection<T>> map) {
-		String key = feign.Util.RETRY_AFTER;
-		if (map.containsKey(key) && !map.get(key).isEmpty()) {
-			return map.get(key).iterator().next();
-		}
-		return null;
-	}
-
-	/**
-	 * Decodes a {@link feign.Util#RETRY_AFTER} header into an absolute date, if possible. <br> See <a
-	 * href="https://tools.ietf.org/html/rfc2616#section-14.37">Retry-After format</a>
-	 */
-	static class RetryAfterDecoder {
-
-		static final ConcurrentDateFormat RFC822_FORMAT = ConcurrentDateFormat.of
-				("EEE, dd MMM yyyy HH:mm:ss 'GMT'", US, TimeZone.getTimeZone(ZoneId.of("GMT")));
-		private final ConcurrentDateFormat rfc822Format;
-
-		RetryAfterDecoder() {
-			this(RFC822_FORMAT);
-		}
-
-		RetryAfterDecoder(ConcurrentDateFormat rfc822Format) {
-			this.rfc822Format = checkNotNull(rfc822Format, "rfc822Format");
-		}
-
-		private long currentTimeMillis() {
-			return System.currentTimeMillis();
-		}
-
-		/**
-		 * returns a date that corresponds to the first time a request can be retried.
-		 *
-		 * @param retryAfter String in <a href="https://tools.ietf.org/html/rfc2616#section-14.37">Retry-After format</a>
-		 */
-		@Nullable
-		Date apply(@Nullable String retryAfter) {
-			if (retryAfter == null) {
-				return null;
-			}
-			if (retryAfter.matches(REGEX)) {
-				long deltaMillis = SECONDS.toMillis(Long.parseLong(retryAfter));
-				return new Date(currentTimeMillis() + deltaMillis);
-			}
-			try {
-				return rfc822Format.parse(retryAfter);
-			} catch (ParseException ignored) {
-				return null;
-			}
-		}
-	}
-}

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

@@ -1,57 +0,0 @@
-/*
- * *************************************************************************
- *   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 PigxFeignException extends RuntimeException {
-	@Getter
-	private final R result;
-
-	public PigxFeignException(R result) {
-		super(result.getMsg());
-		this.result = result;
-	}
-
-	public PigxFeignException(String message) {
-		super(message);
-		this.result = R.builder()
-				.code(CommonConstants.FAIL)
-				.msg(message).build();
-	}
-
-	/**
-	 * 提高性能
-	 *
-	 * @return {Throwable}
-	 */
-	@Override
-	public Throwable fillInStackTrace() {
-		return this;
-	}
-}

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

@@ -1,57 +0,0 @@
-/*
- * *************************************************************************
- *   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 PigxFeignFallbackFactory<T> implements FallbackFactory<T> {
-	public static final PigxFeignFallbackFactory INSTANCE = new PigxFeignFallbackFactory();
-	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 - 38
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignFallbackMethod.java

@@ -1,38 +0,0 @@
-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 PigxFeignException ?
-					((PigxFeignException) cause).getResult() : R.builder()
-					.code(CommonConstants.FAIL)
-					.msg(cause.getMessage()).build();
-			return result;
-		}
-		return null;
-	}
-}

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

@@ -1,289 +0,0 @@
-/*
- * *************************************************************************
- *   Copyright (c) 2018-2025, dreamlu.net All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * Neither the name of the dreamlu.net developer nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * Author: chunmeng.lu (qq596392912@gmail.com)
- * *************************************************************************
- */
-
-package com.pig4cloud.pigx.common.security.feign;
-
-import com.netflix.hystrix.HystrixCommand;
-import feign.*;
-import feign.codec.Decoder;
-import feign.codec.Encoder;
-import feign.codec.ErrorDecoder;
-import feign.hystrix.FallbackFactory;
-import feign.hystrix.HystrixDelegatingContract;
-import feign.hystrix.SetterFactory;
-import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.cloud.openfeign.FeignContext;
-import org.springframework.core.annotation.AnnotatedElementUtils;
-import org.springframework.lang.Nullable;
-import org.springframework.util.Assert;
-
-/**
- * 自定义 Hystrix Feign 实现默认 fallBack
- *
- * @author L.cm
- */
-public class PigxHystrixFeign {
-
-	public static PigxHystrixFeign.Builder builder(FeignContext feignContext) {
-		return new PigxHystrixFeign.Builder(feignContext);
-	}
-
-	public static final class Builder extends Feign.Builder {
-		private Contract contract = new Contract.Default();
-		private SetterFactory setterFactory = new SetterFactory.Default();
-		private final FeignContext feignContext;
-
-		public Builder(FeignContext feignContext) {
-			this.feignContext = feignContext;
-		}
-
-		/**
-		 * Allows you to override hystrix properties such as thread pools and command keys.
-		 */
-		public PigxHystrixFeign.Builder setterFactory(SetterFactory setterFactory) {
-			this.setterFactory = setterFactory;
-			return this;
-		}
-
-		@Override
-		public <T> T target(Target<T> target) {
-			Class<T> targetType = target.type();
-			FeignClient feignClient = AnnotatedElementUtils.getMergedAnnotation(targetType, FeignClient.class);
-			String factoryName = feignClient.name();
-			SetterFactory setterFactoryBean = this.getOptional(factoryName, feignContext, SetterFactory.class);
-			if (setterFactoryBean != null) {
-				this.setterFactory(setterFactoryBean);
-			}
-			Class<?> fallback = feignClient.fallback();
-			if (fallback != void.class) {
-				return targetWithFallback(factoryName, feignContext, target, this, fallback);
-			}
-			Class<?> fallbackFactory = feignClient.fallbackFactory();
-			if (fallbackFactory != void.class) {
-				return targetWithFallbackFactory(factoryName, feignContext, target, this, fallbackFactory);
-			}
-			return build().newInstance(target);
-		}
-
-		@SuppressWarnings("unchecked")
-		private <T> T targetWithFallbackFactory(String feignClientName, FeignContext context,
-												Target<T> target,
-												PigxHystrixFeign.Builder builder,
-												Class<?> fallbackFactoryClass) {
-			FallbackFactory<? extends T> fallbackFactory = (FallbackFactory<? extends T>)
-					getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class);
-		/* We take a sample fallback from the fallback factory to check if it returns a fallback
-		that is compatible with the annotated feign interface. */
-			Object exampleFallback = fallbackFactory.create(new RuntimeException());
-			Assert.notNull(exampleFallback,
-					String.format(
-							"Incompatible fallbackFactory instance for feign client %s. Factory may not produce null!",
-							feignClientName));
-			if (!target.type().isAssignableFrom(exampleFallback.getClass())) {
-				throw new IllegalStateException(
-						String.format(
-								"Incompatible fallbackFactory instance for feign client %s. Factory produces instances of '%s', but should produce instances of '%s'",
-								feignClientName, exampleFallback.getClass(), target.type()));
-			}
-			return builder.target(target, fallbackFactory);
-		}
-
-
-		private <T> T targetWithFallback(String feignClientName, FeignContext context,
-										 Target<T> target,
-										 PigxHystrixFeign.Builder builder, Class<?> fallback) {
-			T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type());
-			return builder.target(target, fallbackInstance);
-		}
-
-		@SuppressWarnings("unchecked")
-		private <T> T getFromContext(String fallbackMechanism, String feignClientName, FeignContext context,
-									 Class<?> beanType, Class<T> targetType) {
-			Object fallbackInstance = context.getInstance(feignClientName, beanType);
-			if (fallbackInstance == null) {
-				throw new IllegalStateException(String.format(
-						"No %s instance of type %s found for feign client %s",
-						fallbackMechanism, beanType, feignClientName));
-			}
-
-			if (!targetType.isAssignableFrom(beanType)) {
-				throw new IllegalStateException(
-						String.format(
-								"Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s",
-								fallbackMechanism, beanType, targetType, feignClientName));
-			}
-			return (T) fallbackInstance;
-		}
-
-		@Nullable
-		private <T> T getOptional(String feignClientName, FeignContext context, Class<T> beanType) {
-			return context.getInstance(feignClientName, beanType);
-		}
-
-		/**
-		 * @see #target(Class, String, Object)
-		 */
-		public <T> T target(Target<T> target, @Nullable T fallback) {
-			return build(fallback != null ? new FallbackFactory.Default<T>(fallback) : null)
-					.newInstance(target);
-		}
-
-		/**
-		 * @see #target(Class, String, FallbackFactory)
-		 */
-		public <T> T target(Target<T> target, FallbackFactory<? extends T> fallbackFactory) {
-			return build(fallbackFactory).newInstance(target);
-		}
-
-		/**
-		 * Like {@link Feign#newInstance(Target)}, except with {@link HystrixCommand
-		 * fallback} support.
-		 *
-		 * <p>Fallbacks are known values, which you return when there's an error invoking an http
-		 * method. For example, you can return a cached result as opposed to raising an error to the
-		 * caller. To use this feature, pass a safe implementation of your target interface as the last
-		 * parameter.
-		 * <p>
-		 * Here's an example:
-		 * <pre>
-		 * {@code
-		 *
-		 * // When dealing with fallbacks, it is less tedious to keep interfaces small.
-		 * interface GitHub {
-		 *   @RequestLine("GET /repos/{owner}/{repo}/contributors")
-		 *   List<String> contributors(@Param("owner") String owner, @Param("repo") String repo);
-		 * }
-		 *
-		 * // This instance will be invoked if there are errors of any kind.
-		 * GitHub fallback = (owner, repo) -> {
-		 *   if (owner.equals("Netflix") && repo.equals("feign")) {
-		 *     return Arrays.asList("stuarthendren"); // inspired this approach!
-		 *   } else {
-		 *     return Collections.emptyList();
-		 *   }
-		 * };
-		 *
-		 * GitHub github = HystrixFeign.builder()
-		 *                             ...
-		 *                             .target(GitHub.class, "https://api.github.com", fallback);
-		 * }</pre>
-		 *
-		 * @see #target(Target, Object)
-		 */
-		public <T> T target(Class<T> apiType, String url, T fallback) {
-			return target(new Target.HardCodedTarget<T>(apiType, url), fallback);
-		}
-
-		/**
-		 * Same as {@link #target(Class, String, T)}, except you can inspect a source exception before
-		 * creating a fallback object.
-		 */
-		public <T> T target(Class<T> apiType, String url, FallbackFactory<? extends T> fallbackFactory) {
-			return target(new Target.HardCodedTarget<T>(apiType, url), fallbackFactory);
-		}
-
-		@Override
-		public Feign.Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory) {
-			throw new UnsupportedOperationException();
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder contract(Contract contract) {
-			this.contract = contract;
-			return this;
-		}
-
-		@Override
-		public Feign build() {
-			return build(null);
-		}
-
-		/**
-		 * Configures components needed for hystrix integration.
-		 */
-		Feign build(@Nullable final FallbackFactory<?> nullableFallbackFactory) {
-			super.invocationHandlerFactory((target, dispatch) ->
-					new PigxHystrixInvocationHandler(target, dispatch, setterFactory, nullableFallbackFactory));
-			super.contract(new HystrixDelegatingContract(contract));
-			return super.build();
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder logLevel(Logger.Level logLevel) {
-			return (PigxHystrixFeign.Builder) super.logLevel(logLevel);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder client(Client client) {
-			return (PigxHystrixFeign.Builder) super.client(client);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder retryer(Retryer retryer) {
-			return (PigxHystrixFeign.Builder) super.retryer(retryer);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder logger(Logger logger) {
-			return (PigxHystrixFeign.Builder) super.logger(logger);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder encoder(Encoder encoder) {
-			return (PigxHystrixFeign.Builder) super.encoder(encoder);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder decoder(Decoder decoder) {
-			return (PigxHystrixFeign.Builder) super.decoder(decoder);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder mapAndDecode(ResponseMapper mapper, Decoder decoder) {
-			return (PigxHystrixFeign.Builder) super.mapAndDecode(mapper, decoder);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder decode404() {
-			return (PigxHystrixFeign.Builder) super.decode404();
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder errorDecoder(ErrorDecoder errorDecoder) {
-			return (PigxHystrixFeign.Builder) super.errorDecoder(errorDecoder);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder options(Request.Options options) {
-			return (PigxHystrixFeign.Builder) super.options(options);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder requestInterceptor(RequestInterceptor requestInterceptor) {
-			return (PigxHystrixFeign.Builder) super.requestInterceptor(requestInterceptor);
-		}
-
-		@Override
-		public PigxHystrixFeign.Builder requestInterceptors(Iterable<RequestInterceptor> requestInterceptors) {
-			return (PigxHystrixFeign.Builder) super.requestInterceptors(requestInterceptors);
-		}
-	}
-
-}

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

@@ -1,217 +0,0 @@
-/*
- * *************************************************************************
- *   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 = PigxFeignFallbackFactory.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();
-	}
-}

+ 4 - 7
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/ConcurrentDateFormat.java

@@ -1,21 +1,18 @@
 /*
- * *************************************************************************
- *   Copyright (c) 2018-2025, dreamlu.net All rights reserved.
+ *    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:
+ * 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
+ * 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: chunmeng.lu (qq596392912@gmail.com)
- * *************************************************************************
+ * Author: lengleng (wangiegie@gmail.com)
  */
 
 package com.pig4cloud.pigx.common.security.util;

+ 11 - 13
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/SecurityUtils.java

@@ -1,20 +1,18 @@
 /*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
  *
- *      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:
+ * 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)
- *
+ * 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.util;

+ 5 - 8
pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/package-info.java

@@ -1,21 +1,18 @@
 /*
- * *************************************************************************
- *   Copyright (c) 2018-2025, dreamlu.net All rights reserved.
+ *    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:
+ * 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
+ * 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: chunmeng.lu (qq596392912@gmail.com)
- * *************************************************************************
+ * Author: lengleng (wangiegie@gmail.com)
  */
 
 /**
@@ -27,7 +24,7 @@
  */
 @NonNullApi
 @NonNullFields
-package com.pig4cloud.pigx.common.security.feign;
+package com.pig4cloud.pigx.common.security.util;
 
 import org.springframework.lang.NonNullApi;
 import org.springframework.lang.NonNullFields;

+ 45 - 0
pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxFallbackFactory.java

@@ -0,0 +1,45 @@
+/*
+ *    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 org.springframework.cloud.openfeign;
+
+import feign.Target;
+import feign.hystrix.FallbackFactory;
+import lombok.AllArgsConstructor;
+import org.springframework.cglib.proxy.Enhancer;
+
+/**
+ * @author 冷冷
+ * <p>
+ * 默认 Fallback,避免写过多fallback类
+ */
+@AllArgsConstructor
+public class PigxFallbackFactory<T> implements FallbackFactory<T> {
+	private final Target<T> target;
+
+	@Override
+	@SuppressWarnings("unchecked")
+	public T create(Throwable cause) {
+		final Class<T> targetType = target.type();
+		final String targetName = target.name();
+		Enhancer enhancer = new Enhancer();
+		enhancer.setSuperclass(targetType);
+		enhancer.setUseCache(true);
+		enhancer.setCallback(new PigxFeignFallback<>(targetType, targetName, cause));
+		return (T) enhancer.create();
+	}
+}

+ 81 - 0
pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxFeignFallback.java

@@ -0,0 +1,81 @@
+/*
+ *    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 org.springframework.cloud.openfeign;
+
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.StrUtil;
+import com.pig4cloud.pigx.common.core.constant.CommonConstants;
+import com.pig4cloud.pigx.common.core.util.R;
+import feign.FeignException;
+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;
+import java.util.Objects;
+
+/**
+ * @author lengleng
+ * <p>
+ * fallBack 代理处理
+ */
+@Slf4j
+@AllArgsConstructor
+public class PigxFeignFallback<T> implements MethodInterceptor {
+	private final Class<T> targetType;
+	private final String targetName;
+	private final Throwable cause;
+
+	@Nullable
+	@Override
+	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
+		String errorMessage = cause.getMessage();
+		log.error("MicaFeignFallback:[{}.{}] serviceId:[{}] message:[{}]", targetType.getName(), method.getName(), targetName, errorMessage);
+		Class<?> returnType = method.getReturnType();
+		if (R.class != returnType) {
+			return null;
+		}
+		FeignException exception = (FeignException) cause;
+
+		byte[] content = exception.content();
+
+		String str = StrUtil.str(content, CharsetUtil.UTF_8);
+
+		return R.builder().code(CommonConstants.FAIL)
+				.msg(str).build();
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) {
+			return true;
+		}
+		if (o == null || getClass() != o.getClass()) {
+			return false;
+		}
+		PigxFeignFallback<?> that = (PigxFeignFallback<?>) o;
+		return targetType.equals(that.targetType);
+	}
+
+	@Override
+	public int hashCode() {
+		return Objects.hash(targetType);
+	}
+}

+ 42 - 0
pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxHystrixFeignTargeterConfiguration.java

@@ -0,0 +1,42 @@
+/*
+ *    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 org.springframework.cloud.openfeign;
+
+import feign.hystrix.HystrixFeign;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+/**
+ * @author lengleng
+ * <p>
+ * HystrixFeignTargeter 配置
+ */
+@Configuration
+@ConditionalOnClass(HystrixFeign.class)
+@ConditionalOnProperty("feign.hystrix.enabled")
+public class PigxHystrixFeignTargeterConfiguration {
+
+	@Bean
+	@Primary
+	public Targeter micaFeignTargeter() {
+		return new PigxHystrixTargeter();
+	}
+}

+ 96 - 0
pigx-common/pigx-common-security/src/main/java/org/springframework/cloud/openfeign/PigxHystrixTargeter.java

@@ -0,0 +1,96 @@
+/*
+ *    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 org.springframework.cloud.openfeign;
+
+import feign.Feign;
+import feign.Target;
+import feign.hystrix.FallbackFactory;
+import feign.hystrix.HystrixFeign;
+import feign.hystrix.SetterFactory;
+import org.springframework.lang.Nullable;
+
+/**
+ * @author lengleng
+ * <p>
+ * 注入默认的 fallbackFactory
+ */
+@SuppressWarnings("unchecked")
+class PigxHystrixTargeter implements Targeter {
+
+	@Override
+	public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
+						Target.HardCodedTarget<T> target) {
+		if (!(feign instanceof HystrixFeign.Builder)) {
+			return feign.target(target);
+		}
+		HystrixFeign.Builder builder = (HystrixFeign.Builder) feign;
+		SetterFactory setterFactory = getOptional(factory.getName(), context, SetterFactory.class);
+		if (setterFactory != null) {
+			builder.setterFactory(setterFactory);
+		}
+		Class<?> fallback = factory.getFallback();
+		if (fallback != void.class) {
+			return targetWithFallback(factory.getName(), context, target, builder, fallback);
+		}
+		Class<?> fallbackFactory = factory.getFallbackFactory();
+		if (fallbackFactory != void.class) {
+			return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory);
+		}
+
+		PigxFallbackFactory micaFallbackFactory = new PigxFallbackFactory(target);
+		return (T) builder.target(target, micaFallbackFactory);
+	}
+
+	private <T> T targetWithFallbackFactory(String feignClientName, FeignContext context,
+											Target.HardCodedTarget<T> target,
+											HystrixFeign.Builder builder,
+											Class<?> fallbackFactoryClass) {
+		FallbackFactory<? extends T> fallbackFactory = (FallbackFactory<? extends T>)
+				getFromContext("fallbackFactory", feignClientName, context, fallbackFactoryClass, FallbackFactory.class);
+		return builder.target(target, fallbackFactory);
+	}
+
+
+	private <T> T targetWithFallback(String feignClientName, FeignContext context,
+									 Target.HardCodedTarget<T> target,
+									 HystrixFeign.Builder builder, Class<?> fallback) {
+		T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type());
+		return builder.target(target, fallbackInstance);
+	}
+
+	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 " + fallbackMechanism +
+					" instance of type %s found for feign client %s", beanType, feignClientName));
+		}
+
+		if (!targetType.isAssignableFrom(beanType)) {
+			throw new IllegalStateException(String.format(
+					"Incompatible " + fallbackMechanism + " instance. Fallback/fallbackFactory of " +
+							"type %s is not assignable to %s for feign client %s", beanType, targetType, feignClientName));
+		}
+		return (T) fallbackInstance;
+	}
+
+	@Nullable
+	private <T> T getOptional(String feignClientName, FeignContext context, Class<T> beanType) {
+		return context.getInstance(feignClientName, beanType);
+	}
+}

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

@@ -1,4 +1,4 @@
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  org.springframework.cloud.openfeign.PigxHystrixFeignTargeterConfiguration,\
   com.pig4cloud.pigx.common.security.component.GlobalExceptionHandlerResolver,\
-  com.pig4cloud.pigx.common.security.feign.PigxFeignConfiguration,\
   com.pig4cloud.pigx.common.security.service.PigxUserDetailsServiceImpl