From 17c23a1c8a5fc3317bd77da38e3b020be8125ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B7=E5=86=B7?= Date: Sun, 20 Jan 2019 21:14:38 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=B7=BB=E5=8A=A0=E6=96=B0?= =?UTF-8?q?=E7=89=B9=E6=80=A7=EF=BC=8Cfeign=20=E8=87=AA=E5=8A=A8=E9=99=8D?= =?UTF-8?q?=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feign/PigxFeginConfiguration.java | 68 +++++ .../security/feign/PigxFeginErrorDecoder.java | 129 ++++++++ .../security/feign/PigxFeginException.java | 57 ++++ .../feign/PigxFeginFallbackFactory.java | 69 +++++ .../feign/PigxFeignClientConfiguration.java | 47 --- .../security/feign/PigxHystrixFeign.java | 289 ++++++++++++++++++ .../feign/PigxHystrixInvocationHandler.java | 218 +++++++++++++ .../common/security/feign/package-info.java | 33 ++ .../security/util/ConcurrentDateFormat.java | 90 ++++++ .../main/resources/META-INF/spring.factories | 2 +- .../admin/api/feign/RemoteLogService.java | 3 +- .../admin/api/feign/RemoteTokenService.java | 9 +- .../admin/api/feign/RemoteUserService.java | 7 +- .../RemoteLogServiceFallbackFactory.java | 38 --- .../RemoteTokenServiceFallbackFactory.java | 38 --- .../RemoteUserServiceFallbackFactory.java | 38 --- .../RemoteLogServiceFallbackImpl.java | 51 ---- .../RemoteTokenServiceFallbackImpl.java | 65 ---- .../RemoteUserServiceFallbackImpl.java | 79 ----- .../main/resources/META-INF/spring.factories | 7 - 20 files changed, 963 insertions(+), 374 deletions(-) create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginConfiguration.java create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginErrorDecoder.java create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginException.java create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginFallbackFactory.java delete mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignClientConfiguration.java create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixFeign.java create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixInvocationHandler.java create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/package-info.java create mode 100644 pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/ConcurrentDateFormat.java delete mode 100644 pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteLogServiceFallbackFactory.java delete mode 100644 pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteTokenServiceFallbackFactory.java delete mode 100644 pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteUserServiceFallbackFactory.java delete mode 100644 pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java delete mode 100644 pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteTokenServiceFallbackImpl.java delete mode 100644 pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java delete mode 100644 pigx-upms/pigx-upms-api/src/main/resources/META-INF/spring.factories diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginConfiguration.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginConfiguration.java new file mode 100644 index 000000000..6e90c8464 --- /dev/null +++ b/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()); + } + } + +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginErrorDecoder.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginErrorDecoder.java new file mode 100644 index 000000000..6ce2c2ec4 --- /dev/null +++ b/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 firstOrNull(Map> 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.
See Retry-After format + */ + 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 Retry-After format + */ + @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; + } + } + } +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginException.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginException.java new file mode 100644 index 000000000..e036fe800 --- /dev/null +++ b/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; + } +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginFallbackFactory.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginFallbackFactory.java new file mode 100644 index 000000000..c8262baeb --- /dev/null +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeginFallbackFactory.java @@ -0,0 +1,69 @@ +/* + * ************************************************************************* + * 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 feign.hystrix.FallbackFactory; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.MethodInterceptor; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * 默认 Fallback,避免写过多fallback类 + * + * @param 泛型标记 + * @author L.cm + */ +@Slf4j +@NoArgsConstructor +public final class PigxFeginFallbackFactory implements FallbackFactory { + public static final PigxFeginFallbackFactory INSTANCE = new PigxFeginFallbackFactory(); + private static final ConcurrentMap, Object> FALLBACK_MAP = new ConcurrentHashMap<>(); + + @SuppressWarnings("unchecked") + public T create(final Class type, final Throwable cause) { + // 重写 fegin ErrorDecoder,message 知己为 body 数据,反序列化为 Result + final R result = cause instanceof PigxFeginException ? + ((PigxFeginException) cause).getResult() : R.builder() + .code(CommonConstants.FAIL) + .msg(cause.getMessage()).build(); + return (T) FALLBACK_MAP.computeIfAbsent(type, key -> { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(key); + enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> { + log.error("Fallback class:[{}] method:[{}] message:[{}]", + type.getName(), method.getName(), cause.getMessage()); + return result; + }); + return enhancer.create(); + }); + } + + @Override + public T create(Throwable cause) { + return null; + } +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignClientConfiguration.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignClientConfiguration.java deleted file mode 100644 index c9c4fee6e..000000000 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxFeignClientConfiguration.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Copyright (c) 2018-2025, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - * - */ - -package com.pig4cloud.pigx.common.security.feign; - -import feign.RequestInterceptor; -import lombok.AllArgsConstructor; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.security.oauth2.client.AccessTokenContextRelay; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; - -/** - * @author lengleng - * @date 2018/6/22 - * feign 拦截器传递 header 中oauth token, - * 使用hystrix 的信号量模式 - */ -@Configuration -@AllArgsConstructor -@ConditionalOnProperty("security.oauth2.client.client-id") -public class PigxFeignClientConfiguration { - @Bean - public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, - OAuth2ProtectedResourceDetails resource, - AccessTokenContextRelay accessTokenContextRelay) { - return new PigxFeignClientInterceptor(oAuth2ClientContext, resource,accessTokenContextRelay); - } -} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixFeign.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixFeign.java new file mode 100644 index 000000000..640e1624c --- /dev/null +++ b/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 target(Target target) { + Class 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 targetWithFallbackFactory(String feignClientName, FeignContext context, + Target target, + PigxHystrixFeign.Builder builder, + Class fallbackFactoryClass) { + FallbackFactory fallbackFactory = (FallbackFactory) + 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 targetWithFallback(String feignClientName, FeignContext context, + Target target, + PigxHystrixFeign.Builder builder, Class fallback) { + T fallbackInstance = getFromContext("fallback", feignClientName, context, fallback, target.type()); + return builder.target(target, fallbackInstance); + } + + @SuppressWarnings("unchecked") + private T getFromContext(String fallbackMechanism, String feignClientName, FeignContext context, + Class beanType, Class 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 getOptional(String feignClientName, FeignContext context, Class beanType) { + return context.getInstance(feignClientName, beanType); + } + + /** + * @see #target(Class, String, Object) + */ + public T target(Target target, @Nullable T fallback) { + return build(fallback != null ? new FallbackFactory.Default(fallback) : null) + .newInstance(target); + } + + /** + * @see #target(Class, String, FallbackFactory) + */ + public T target(Target target, FallbackFactory fallbackFactory) { + return build(fallbackFactory).newInstance(target); + } + + /** + * Like {@link Feign#newInstance(Target)}, except with {@link HystrixCommand + * fallback} support. + * + *

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. + *

+ * Here's an example: + *

+		 * {@code
+		 *
+		 * // When dealing with fallbacks, it is less tedious to keep interfaces small.
+		 * interface GitHub {
+		 *   @RequestLine("GET /repos/{owner}/{repo}/contributors")
+		 *   List 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);
+		 * }
+ * + * @see #target(Target, Object) + */ + public T target(Class apiType, String url, T fallback) { + return target(new Target.HardCodedTarget(apiType, url), fallback); + } + + /** + * Same as {@link #target(Class, String, T)}, except you can inspect a source exception before + * creating a fallback object. + */ + public T target(Class apiType, String url, FallbackFactory fallbackFactory) { + return target(new Target.HardCodedTarget(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 requestInterceptors) { + return (PigxHystrixFeign.Builder) super.requestInterceptors(requestInterceptors); + } + } + +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixInvocationHandler.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixInvocationHandler.java new file mode 100644 index 000000000..2225ad6d6 --- /dev/null +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/PigxHystrixInvocationHandler.java @@ -0,0 +1,218 @@ +/* + * ************************************************************************* + * 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 + *

+ * 降级注入 + */ +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 dispatch; + @Nullable + private final FallbackFactory fallbackFactory; + private final Map fallbackMethodMap; + private final Map setterMethodMap; + + PigxHystrixInvocationHandler( + Target target, Map 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 toFallbackMethod(Map dispatch) { + Map 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 toSetters( + SetterFactory setterFactory, Target target, Set methods) { + Map 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 hystrixCommand = new HystrixCommand(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() { + final FallbackFactory localFallbackFactory = fallbackFactory == null ? PigxFeginFallbackFactory.INSTANCE : fallbackFactory; + Object fallback; + try { + if (localFallbackFactory instanceof PigxFeginFallbackFactory) { + fallback = ((PigxFeginFallbackFactory) localFallbackFactory).create(target.type(), getExecutionException()); + } else { + fallback = localFallbackFactory.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(); + } +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/package-info.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/feign/package-info.java new file mode 100644 index 000000000..ab9363e5e --- /dev/null +++ b/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 + *

+ * 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; diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/ConcurrentDateFormat.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/util/ConcurrentDateFormat.java new file mode 100644 index 000000000..e0416ca46 --- /dev/null +++ b/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 + *

+ * {@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 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; + } +} diff --git a/pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories b/pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories index b13fe1565..19d984da1 100644 --- a/pigx-common/pigx-common-security/src/main/resources/META-INF/spring.factories +++ b/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 diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java index 356c27352..c722f174f 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java +++ b/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 { /** * 保存日志 diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteTokenService.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteTokenService.java index 9b2689e41..f73f4a5df 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteTokenService.java +++ b/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,23 +30,25 @@ 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 params 分页参数 + * @param from 内部调用标志 * @return page */ @PostMapping("/token/page") - R getTokenPage(@RequestBody Map params,@RequestHeader(SecurityConstants.FROM) String from); + R getTokenPage(@RequestBody Map params, @RequestHeader(SecurityConstants.FROM) String from); /** * 删除token * * @param token token + * @param from 内部调用标志 * @return */ @DeleteMapping("/token/{token}") - R removeTokenById(@PathVariable("token") String token,@RequestHeader(SecurityConstants.FROM) String from); + R removeTokenById(@PathVariable("token") String token, @RequestHeader(SecurityConstants.FROM) String from); } diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java index 3c3100ca3..b4832a9c2 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java +++ b/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 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 social(@PathVariable("inStr") String inStr - , @RequestHeader(SecurityConstants.FROM) String from); + , @RequestHeader(SecurityConstants.FROM) String from); /** * 查询上级部门的用户信息 diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteLogServiceFallbackFactory.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteLogServiceFallbackFactory.java deleted file mode 100644 index f6b0ebd09..000000000 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteLogServiceFallbackFactory.java +++ /dev/null @@ -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 { - - @Override - public RemoteLogService create(Throwable throwable) { - RemoteLogServiceFallbackImpl remoteLogServiceFallback = new RemoteLogServiceFallbackImpl(); - remoteLogServiceFallback.setCause(throwable); - return remoteLogServiceFallback; - } -} diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteTokenServiceFallbackFactory.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteTokenServiceFallbackFactory.java deleted file mode 100644 index ebe82bc19..000000000 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteTokenServiceFallbackFactory.java +++ /dev/null @@ -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 { - - @Override - public RemoteTokenService create(Throwable throwable) { - RemoteTokenServiceFallbackImpl remoteTokenServiceFallback = new RemoteTokenServiceFallbackImpl(); - remoteTokenServiceFallback.setCause(throwable); - return remoteTokenServiceFallback; - } -} diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteUserServiceFallbackFactory.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteUserServiceFallbackFactory.java deleted file mode 100644 index 93dbb02b4..000000000 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/factory/RemoteUserServiceFallbackFactory.java +++ /dev/null @@ -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 { - - @Override - public RemoteUserService create(Throwable throwable) { - RemoteUserServiceFallbackImpl remoteUserServiceFallback = new RemoteUserServiceFallbackImpl(); - remoteUserServiceFallback.setCause(throwable); - return remoteUserServiceFallback; - } -} diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java deleted file mode 100644 index c95c1a393..000000000 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java +++ /dev/null @@ -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 saveLog(SysLog sysLog, String from) { - log.error("feign 插入日志失败", cause); - return null; - } -} diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteTokenServiceFallbackImpl.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteTokenServiceFallbackImpl.java deleted file mode 100644 index a57ad391b..000000000 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteTokenServiceFallbackImpl.java +++ /dev/null @@ -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 getTokenPage(Map params, String from) { - log.error("调用认证中心查询token 失败", cause); - return null; - } - - /** - * 删除token - * - * @param token - * @param from 内部调用标志 - * @return - */ - @Override - public R removeTokenById(String token, String from) { - log.error("删除token 失败 {}", token, cause); - return null; - } -} diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java deleted file mode 100644 index 1702fc84a..000000000 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java +++ /dev/null @@ -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 info(String username, String from) { - log.error("feign 查询用户信息失败:{}", username, cause); - return null; - } - - /** - * 通过社交账号查询用户、角色信息 - * - * @param inStr appid@code - * @param from 内外标志 - * @return - */ - @Override - public R social(String inStr, String from) { - log.error("feign 查询用户信息失败:{}", inStr, cause); - return null; - } - - /** - * 查询上级部门的用户信息 - * - * @param username 用户名 - * @return R - */ - @Override - public R> ancestorUsers(String username) { - log.error("feign 查询用户上级部门用户列失败:{}", username, cause); - return null; - } -} diff --git a/pigx-upms/pigx-upms-api/src/main/resources/META-INF/spring.factories b/pigx-upms/pigx-upms-api/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 5fab2a739..000000000 --- a/pigx-upms/pigx-upms-api/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -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