spring cloud openFeign传参的一些总结(有错,待更新)

1. 客户端注解问题

spring cloud openFeign 的客户端 ,即调用方,在启动类中一定要加上 @EnableFeignClients 这个注解,service接口上的@service注解和@FeignClient("微服务名") 都写在一起,如果不加,会报@service 没初始化这个service接口。

2. openFeign的http连接优化选择

openFeign 默认用的是jdk的httpUrlConnection,没有连接池,http连接没复用,性能不太好,我们可以集成 httpClient 或者 okHttp,二选一,不用指定版本号,他会自动根据你的spring cloud 的openfeign 解析出来。

 <dependency>
         <groupId>io.github.openfeign</groupId>
         <artifactId>feign-okhttp</artifactId>
 </dependency>

或者

<dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
</dependency>

3.关于记录feign调用日志,可以配置如下:

@Configuration
public class FeignLogConfig {

    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;
    }
}

4. 关于微服务传参

公共bean
@Data
public class Trans implements Serializable {

    private Integer id;

    private Date date;

    private LocalDateTime ldt;

    private String name;

    private Double money;

    private InnerTrans innerTrans;
}

@Data
public class InnerTrans implements Serializable {

    private String code;

    private Integer age;
}
调用方
@Service
@FeignClient("provider")
public interface TestService {
    @GetMapping("/test/getWithInt")
    Integer getWithInt(@RequestParam("i") Integer i);

    @GetMapping("/test/getWithDouble")
    Double getWithDouble(@RequestParam("d") Double d);

    @GetMapping("/test/getWithString")
    String getWithString(@RequestParam("str") String s);

    @GetMapping("/test/getWithPvInt/{id}")
    Integer getWithPvInt(@PathVariable("id") Integer id);

    @GetMapping("/test/getWithPvStr/{code}")
    String getWithPvStr(@PathVariable("code") String code);

    @GetMapping("/test/getWithMap")
    //Map getWithMap(@RequestParam("m") Map m);
    Map getWithMap(@SpringQueryMap Map m);

    //复杂类型接收失败(bean 嵌 bean)
    @GetMapping("/test/getWithBean")
    Trans getWithBean(@SpringQueryMap Trans t);

    @GetMapping("/test/getWithSimpleBean")
    InnerTrans getWithSimpleBean(@SpringQueryMap InnerTrans t);

    //-------------------------------**- get  end -**-------------------------------------

    //---------------------------------  post  start -------------------------------------
    @PostMapping("/test/postWithInt")
    Integer postWithInt(@RequestParam("i") Integer i);

    @PostMapping("/test/postWithDouble")
    Double postWithDouble(@RequestParam("d") Double d);

    @PostMapping("/test/postWithString")
    String postWithString(@RequestParam("s") String s);

    @PostMapping("/test/postWithMap")
    Map postWithMap(Map m);

    @PostMapping("/test/postWithList")
    List<Trans> postWithList(List l);

    @PostMapping("/test/postWithBean")
    Trans postWithBean(Trans t);

    @PostMapping("/test/postWithSimpleBean")
    InnerTrans postWithSimpleBean(InnerTrans t);

}
被调用方:
@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/getWithInt")
    public Integer getWithInt(@RequestParam Integer i) {
        return i + 10;
    }

    @GetMapping("/getWithDouble")
    public Double getWithDouble(@RequestParam Double d) {
        return d + 10;
    }

    @GetMapping("/getWithString")
    public String getWithString(@RequestParam String str) {
        return "provider-a test getWithString : " + str + " return";
    }

    @GetMapping("/getWithPvInt/{id}")
    public String getWithPvInt(@PathVariable(name = "id") Integer id) {
        return "provider-a test getWithPvInt : " + id + " return";
    }

    @GetMapping("/getWithPvStr/{code}")
    public String getWithPvStr(@PathVariable(name = "code") String code) {
        return "provider-a test getWithPvStr : " + code + " return";
    }

    @GetMapping("/getWithMap")
    public Map getWithMap(@RequestParam Map m) {
        System.out.println(m);
        return m;
    }

    @GetMapping("/getWithBean")
    public Trans getWithBean(Trans t) {
        System.out.println(t.toString());
        t.setName("provider-a test getBean return");
        return t;
    }

    @GetMapping("/getWithSimpleBean")
    public InnerTrans getWithSimpleBean(InnerTrans t) {
        System.out.println(t.toString());
        t.setCode("provider-a test getBean return");
        return t;
    }

    @GetMapping("/getString")
    public String getString() {
        return "provider-a test getString";
    }

    @GetMapping("/getBean")
    public Trans getBean() {
        Trans trans = new Trans();
        trans.setDate(new Date());
        trans.setLdt(LocalDateTime.now().minusYears(1L));
        trans.setId(99);
        trans.setMoney(99.99);
        trans.setName("provider-a test getBean");
        InnerTrans innerTrans = new InnerTrans();
        innerTrans.setAge(88);
        innerTrans.setCode("inner");
        trans.setInnerTrans(innerTrans);
        return trans;
    }


    //----------------  post -----------------

    @PostMapping("/postWithInt")
    public Integer postWithInt(@RequestParam Integer i){
        return i + 20;
    }

    @PostMapping("/postWithDouble")
    public Double postWithDouble(@RequestParam Double d){
        return d + 4;
    }

    @PostMapping("/postWithString")
    public String postWithString(@RequestParam String s){
        return "test postWithString : provider-a receive " + s + " and return";
    }

    @PostMapping("/postWithMap")
    public Map postWithMap(@RequestBody Map m){
        System.out.println(m);
        return m;
    }

    @PostMapping("/postWithList")
    public List<Trans> postWithList(@RequestBody List<Trans> l){
        System.out.println(Arrays.toString(l.toArray()));
        return l;
    }

    @PostMapping("/postWithBean")
    public Trans postWithBean(@RequestBody Trans t){
        System.out.println(t.toString());
        return t;
    }

    @PostMapping("/postWithSimpleBean")
    public InnerTrans postWithSimpleBean(@RequestBody InnerTrans t){
        System.out.println(t.toString());
        return t;
    }

经过测试,得到以下结论:

对于GET
  • 参数是基本的类型(integer、string这些),调用方 必须加上@RequestParam,而且还要在@RequestParam那加上被 调用方 端参数的别名,如@RequestParam("xxx") ,@PathVariable 依然是如此,否则应用也报错启动不了,而 被调用方 则可加可不加,为保持一致,还是加上好点。

  • 参数是map,调用方 可以使用@RequestParam 或 @SpringQueryMap,被调用方则用 @RequestParam,必须用,如springmvc那样,不加的话直接访问 被调用方 也是报错的。

  • 参数是bean,复合的bean会有问题(即bean里面有别的自定义bean参数),简单类型参数的bean就没问题。因为参数都拼接在后面,如
    http://provider/test/getWithBean?date=2021-10-22 23:14:04&money=99.99&name=consumer-a test getWithBean&innerTrans=InnerTrans(code=inner, age=88, favor=null, time=2019-10-22T23:14:04.828, date=Fri Oct 22 23:14:04 CST 2021)&id=99&ldt=2020-10-22 23:14:04,会报错。

错误如下:

2021-10-22 11:51:19.131 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] ---> GET http://provider/test/getWithBean?date=Fri%20Oct%2022%2011%3A51%3A19%20CST%202021&money=99.99&name=consumer-a%20test%20getWithBean&innerTrans=InnerTrans%28code%3Dinner%2C%20age%3D88%29&id=99&ldt=2020-10-22T11%3A51%3A19.128 HTTP/1.1
2021-10-22 11:51:19.131 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] ---> END HTTP (0-byte body)
2021-10-22 11:51:19.142 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] <--- HTTP/1.1 400 (10ms)
2021-10-22 11:51:19.142 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] connection: close
2021-10-22 11:51:19.142 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] content-type: application/json
2021-10-22 11:51:19.142 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] date: Fri, 22 Oct 2021 03:51:19 GMT
2021-10-22 11:51:19.142 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] transfer-encoding: chunked
2021-10-22 11:51:19.143 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] 
2021-10-22 11:51:19.143 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] {"timestamp":"2021-10-22 11:51:19","status":400,"error":"Bad Request","message":"","path":"/test/getWithBean"}
2021-10-22 11:51:19.143 DEBUG 11640 --- [nio-8000-exec-8] com.orion.service.TestService            : [TestService#getWithBean] <--- END HTTP (110-byte body)
2021-10-22 11:51:19.145 ERROR 11640 --- [nio-8000-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.FeignException$BadRequest: [400] during [GET] to [http://provider/test/getWithBean?date=Fri%20Oct%2022%2011%3A51%3A19%20CST%202021&money=99.99&name=consumer-a%20test%20getWithBean&innerTrans=InnerTrans%28code%3Dinner%2C%20age%3D88%29&id=99&ldt=2020-10-22T11%3A51%3A19.128] [TestService#getWithBean(Trans)]: [{"timestamp":"2021-10-22 11:51:19","status":400,"error":"Bad Request","message":"","path":"/test/getWithBean"}]] with root cause

feign.FeignException$BadRequest: [400] during [GET] to [http://provider/test/getWithBean?date=Fri%20Oct%2022%2011%3A51%3A19%20CST%202021&money=99.99&name=consumer-a%20test%20getWithBean&innerTrans=InnerTrans%28code%3Dinner%2C%20age%3D88%29&id=99&ldt=2020-10-22T11%3A51%3A19.128] [TestService#getWithBean(Trans)]: [{"timestamp":"2021-10-22 11:51:19","status":400,"error":"Bad Request","message":"","path":"/test/getWithBean"}]
    at feign.FeignException.clientErrorStatus(FeignException.java:195) ~[feign-core-10.10.1.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:177) ~[feign-core-10.10.1.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:169) ~[feign-core-10.10.1.jar:na]
    at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92) ~[feign-core-10.10.1.jar:na]
    at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96) ~[feign-core-10.10.1.jar:na]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138) ~[feign-core-10.10.1.jar:na]
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) ~[feign-core-10.10.1.jar:na]
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-10.10.1.jar:na]
    at com.sun.proxy.$Proxy111.getWithBean(Unknown Source) ~[na:na]
    at com.orion.controller.TestController.getWithBean(TestController.java:69) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_191]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_191]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_191]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_191]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.37.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.37.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_191]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_191]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.37.jar:9.0.37]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]

值得注意的是,多参数不建议用map,可读性差,如果少的话,可以用分开用多个参数来传,各个参数用 @RequestParam("xxx")注解就行,如果太多的话,建议封装成一个bean,使用@SpringQueryMap注解。

使用get方式发送,就是在url后面通过 & 把所有参数拼接起来一起传输,这个可以打开日志来观察即可。前提得配置,结论3 处。

对于post

  • 参数是基本的类型(integer、string这些),调用方 必须加上@RequestParam,而且还要在@RequestParam那加上被 调用方 端参数的别名,如@RequestParam("xxx") ,@PathVariable 依然是如此,否则应用也报错启动不了,而 被调用方 则可加可不加,为保持一致,还是加上好点。

  • 参数是map,list,bean嵌bean,简单参数bean,调用方 不需要加注解,被调用方则必须用 @RequestBody来接收,如果是list的话,必须指定list的泛型类型,不然报错。

注意:

get方法已经说了是在url后面拼接的,所以如果get的方式传@SpringQueryMap 的bean参数里面,如果有LocalDatetime、Date这类的属性,它们默认是用toString方法,所以Date是话使用cst这种时区,LocalDatetime有T这种时区在里面,不符合我们日常使用的yyyy-MM-dd HH:mm:ss 这种格式,必须自定义自己的QueryMapEncoder,其实现QueryMapEncoder接口,并配置上; 自定义feignBuilder会导致hystrix失效。

Post是不会有影响的

@Configuration
public class CustomFeignConfig {


    @Bean
    public Feign.Builder feignBuilder() {
        return Feign.builder()
                .queryMapEncoder(new QueryMapImproveEncoder())
                .retryer(Retryer.NEVER_RETRY);
    }

}
public class QueryMapImproveEncoder implements QueryMapEncoder {
    private final Map<Class<?>, ObjectParamMetadata> classToMetadata =
            new HashMap<>();
    private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern(JacksonConfig.PATTERN);



    @Override
    public Map<String, Object> encode(Object object) throws EncodeException {
        try {
            ObjectParamMetadata metadata = getMetadata(object.getClass());
            Map<String, Object> propertyNameToValue = new HashMap<>(16);
            for (PropertyDescriptor pd : metadata.objectProperties) {
                Method method = pd.getReadMethod();

                Object value = method.invoke(object);
                if (value != null && value != object) {
                    Param alias = method.getAnnotation(Param.class);
                    String name = alias != null ? alias.value() : pd.getName();


                    String handleClazzName = method.getReturnType().getName();
                    switch (handleClazzName){
                        case "java.time.LocalDateTime" :
                            propertyNameToValue.put(name, dtf.format((LocalDateTime) value));
                            break;
                        case "java.util.Date" :
                            LocalDateTime ldt = LocalDateTime.ofInstant(((Date)value).toInstant(), ZoneId.systemDefault());
                            propertyNameToValue.put(name, dtf.format(ldt));
                            break;
                        default:
                            propertyNameToValue.put(name, value);
                            break;
                    }
                }
            }
            return propertyNameToValue;
        } catch (IllegalAccessException | IntrospectionException | InvocationTargetException e) {
            throw new EncodeException("Failure encoding object into query map", e);
        }
    }

    private ObjectParamMetadata getMetadata(Class<?> objectType) throws IntrospectionException {
        ObjectParamMetadata metadata = classToMetadata.get(objectType);
        if (metadata == null) {
            metadata = ObjectParamMetadata.parseObjectType(objectType);
            classToMetadata.put(objectType, metadata);
        }
        return metadata;
    }

    private static class ObjectParamMetadata {

        private final List<PropertyDescriptor> objectProperties;

        private ObjectParamMetadata(List<PropertyDescriptor> objectProperties) {
            this.objectProperties = Collections.unmodifiableList(objectProperties);
        }

        private static ObjectParamMetadata parseObjectType(Class<?> type)
                throws IntrospectionException {
            List<PropertyDescriptor> properties = new ArrayList<>();

            for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) {
                boolean isGetterMethod = pd.getReadMethod() != null && !"class".equals(pd.getName());
                if (isGetterMethod) {
                    properties.add(pd);
                }
            }

            return new ObjectParamMetadata(properties);
        }
    }
}

参考:
SpringCloud中利用FeignClient发送请求时参数的传递和返回值

feign请求返回值反序列LocalDateTime异常记录

openfeign get请求参数dto包含LocalDateTime的处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容