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
遗失的拂晓