Loading

Method has too many Body parameters openfeign

feign 调用问题,最新版本的feign和旧版本的稍微有一些不一样,具体如下(eureka 作为服务发现与注册 )

 依赖:

    compile('io.github.openfeign:feign-java8:9.6.0')
    compile('org.springframework.cloud:spring-cloud-openfeign-core')
    compile('org.springframework.cloud:spring-cloud-starter-openfeign')

feign client 接口,这里统一使用feign的@Param进行注解

import org.springframework.cloud.openfeign.FeignClient;

import feign.Headers;
import feign.Param;
import feign.RequestLine;

@FeignClient(value = "xxx-service")
public interface xxxServiceClient {

    @RequestLine("POST /xxx/save")
    String saveLog(@Param(value = "data") String data);

}

 

 对应xxx-service的具体rest,这里使用spring的@RequestParam 等进行参数的接收

    @RequestMapping(value = "/xxx/save", method = { RequestMethod.POST })
    public String saveLog(@RequestParam(value = "data", required = false) String data) String status) {
     // TODO
   return "xxx"; }

 

feign 基本请求格式

 ...
 @RequestLine("POST /servers")
 void post(@Param("serverId") String serverId, @Param("count") int count);
 ...

 @RequestLine("GET /servers/{serverId}?count={count}")
 void get(@Param("serverId") String serverId, @Param("count") int count);
...

 

对于post多参数问题,需要使用form的提交格式(某些字段是xml、json之类的参数),普通的提交,head里是

"Content-Type: application/json; charset=UTF-8", "Accept: application/json"

多参数需要使用

"Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Accept: application/json"

而第二种格式需要feign-form的支持

依赖:

    compile('io.github.openfeign.form:feign-form:3.3.0')
    compile('io.github.openfeign.form:feign-form-spring:3.3.0')
    compile('io.github.openfeign:feign-java8:9.6.0')
    compile('org.springframework.cloud:spring-cloud-openfeign-core')
    compile('org.springframework.cloud:spring-cloud-starter-openfeign')

feign:

import org.springframework.cloud.openfeign.FeignClient;

import feign.Headers;
import feign.Param;
import feign.RequestLine;

@FeignClient(value = "whale-service", configuration = EurekaConfiguration.class)
public interface xxxServiceClient {

    @Headers({ "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Accept: application/json" })
    @RequestLine("POST /deviceActionLog/save")
    String saveLog(@Param(value = "data") String data);

}
import org.springframework.cloud.openfeign.FeignClient;
import feign.Headers;
import feign.Param;
import feign.RequestLine;

@FeignClient(value = "xxx-service", configuration = EurekaConfiguration.class)
public interface xxxClient {

    @Headers({ "Content-Type: application/json; charset=UTF-8", "Accept: application/json" })
    @RequestLine("GET /xxx/obj?id={id}")
    String getById(@Param(value = "id") String deviceId);

}

注:若实现xxxclient的接口,则feign首先调用远程服务,远程服务不可用时,降级调用本地实现类

 

EurekaConfiguration:

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.HttpMessageConverter;

import feign.Contract;
import feign.auth.BasicAuthRequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.form.FormEncoder;
import feign.form.spring.converter.SpringManyMultipartFilesReader;

@Configuration
public class EurekaConfiguration {

    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("admin", "admin");//eureka 获取注册服务使用的账号密码
    }

    // 使用Feign自己的注解,使用springmvc的注解就会报错
    @Bean
    public Contract feignContract() {
        return new feign.Contract.Default();
    }

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean // spring使用的编码器
    @Primary
    Encoder feignEncoder() {
        // return new SpringEncoder(this.messageConverters);
        return new FormEncoder(new SpringEncoder(this.messageConverters));
    }

    @Bean // download使用的解码器
    @Qualifier("download")
    public Decoder feignDecoder() {
        final List<HttpMessageConverter<?>> springConverters = messageConverters.getObject().getConverters();
        final List<HttpMessageConverter<?>> decoderConverters = new ArrayList<HttpMessageConverter<?>>(
                springConverters.size() + 1);

        decoderConverters.addAll(springConverters);
        decoderConverters.add(new SpringManyMultipartFilesReader(4096));
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(decoderConverters);

        return new SpringDecoder(new ObjectFactory<HttpMessageConverters>() {
            @Override
            public HttpMessageConverters getObject() {
                return httpMessageConverters;
            }
        });
    }
}

 

参考:

https://github.com/OpenFeign/feign

http://sparkgis.com/java/2018/02/feign-method-has-too-many-body-parameters-%E5%8E%9F-feign-method-has-too-many-body-parameters-xixingzhe/

https://yezhwi.github.io/springcloud/2017/12/07/%E5%AE%9E%E8%B7%B5bug%E6%80%BB%E7%BB%93-Feign/

https://blog.csdn.net/liuchuanhong1/article/details/54728681

编码参考:

https://github.com/OpenFeign/feign-form

posted @ 2018-05-23 15:52  遗失的拂晓  阅读(1108)  评论(0编辑  收藏  举报