如何使用 Spring Cloud Feign 发布表单 URL 编码的数据
Posted
技术标签:
【中文标题】如何使用 Spring Cloud Feign 发布表单 URL 编码的数据【英文标题】:How to POST form-url-encoded data with Spring Cloud Feign 【发布时间】:2016-06-18 14:29:42 【问题描述】:使用spring-mvc
注解:
@FeignClient
可以POST
form-url-encoded
?
【问题讨论】:
【参考方案1】:对 Feign 使用 FormEncoder:
https://github.com/OpenFeign/feign-form你的 Feign 配置可能如下所示:
class CoreFeignConfiguration
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters
@Bean
@Primary
@Scope(SCOPE_PROTOTYPE)
Encoder feignFormEncoder()
new FormEncoder(new SpringEncoder(this.messageConverters))
然后,客户端可以这样映射:
@FeignClient(name = 'client', url = 'localhost:9080', path ='/rest',
configuration = CoreFeignConfiguration)
interface CoreClient
@RequestMapping(value = '/business', method = POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED)
@Headers('Content-Type: application/x-www-form-urlencoded')
void activate(Map<String, ?> formParams)
【讨论】:
注意这一行Map<String, ?> formParams
,问号是必填项。
对于那些不认识 groovy 的人 - 这是在 groovy 中,因此不是“return”,“;”等:)
不是很有用,它要求我的 pojo 有 @FormProperty 但不检查超类,我不能在客户端调用中单独提供 20 个表单属性。
你不需要额外的 headers 注释,feign 自动将其放置在消耗配置中。【参考方案2】:
带有简化版 kazuar 解决方案的完整 Java 代码,可与 Spring Boot 配合使用:
import java.util.Map;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
@FeignClient(name = "srv", url = "http://s.com")
public interface Client
@PostMapping(value = "/form", consumes = APPLICATION_FORM_URLENCODED_VALUE)
void login(@RequestBody Map<String, ?> form);
class Configuration
@Bean
Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> converters)
return new SpringFormEncoder(new SpringEncoder(converters));
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
【讨论】:
可能无关但值得一提。如果您期待 JSON 响应。您可能需要为Decoder
配置@Bean
return new GsonDecoder();
不,spring boot中已经配置了Jackson解码器。
是的,没错。默认的 JSONDecoder 已经配置好了。但是,我已启用 gson 作为默认转换器并使用自定义版本 @Bean Gson upbeatGson() return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();
- 因此我提到了。否则,如果 JSONDecoder - 默认版本有效,则不需要。
在您的 @FeignClient 注释中只是错过了 configuration = yourClass.Configuration.class
正如@HenriqueSchmitt 所说,我必须设置@FeignClient(configuration = Client.Configuration.class)
才能使其工作。答案应该被编辑【参考方案3】:
对于 POST 中的 url-form-encoded 数据,您必须在 Feign 编码器中使用 FormEncoder
。
将依赖项添加到您的应用中:
马文:
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
像这样将 FormEncoder 添加到 Feign.Builder 中:
SomeFeign sample = Feign.builder()
.encoder(new FormEncoder(new JacksonEncoder()))
.target(SomeFeign.class, "http://sample.test.org");
在 Feign 界面中
@RequestLine("POST /submit/form")
@Headers("Content-Type: application/x-www-form-urlencoded")
void from (@Param("field1") String field1, @Param("field2") String field2);
更多信息请参考: https://github.com/OpenFeign/feign-form
【讨论】:
此方法会导致“Java.lang.NoSuchMethodError”。【参考方案4】:为了补充accepted answer,也可以使用POJO代替Map<String, ?>
来传递表单参数给feign客户端:
@FeignClient(configuration = CustomConfig.class)
interface Client
@PostMapping(
path = "/some/path",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
void postComment(CommentFormDto formDto);
...
...
class CustomConfig
@Bean
Encoder formEncoder()
return new feign.form.FormEncoder();
...
class CommentFormDto
private static String willNotBeSerialized;
private final Integer alsoWillNotBeSerialized;
@feign.form.FormProperty("author_id")
private Long authorId;
private String message;
@feign.form.FormProperty("ids[]")
private List<Long> ids;
/* getters and setters omitted for brevity */
这将导致请求的正文如下所示:
author_id=42&message=somemessage&ids[]=1&ids[]=2
@FeignProperty
注解允许设置自定义字段名称;请注意 POJO 的 static 或 final 字段以及继承的字段,不会被序列化为表单内容。
【讨论】:
【参考方案5】:对于 Feign.Builder,我的工作没有 JacksonEncoder,只有 Feign FormEncoder:
将 FormEncoder 添加到您的 Feign.Builder:
SomeFeign sample = Feign.builder()
.encoder(new FormEncoder()) <==difference here
.target(SomeFeign.class, "http://sample.test.org");
我在 pom.xml 中添加的 feign 依赖:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>11.8</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>11.8</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
pom.xml 中的父级是:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
Ramanan 给出的 feign 界面:
@RequestLine("POST /submit/form")
@Headers("Content-Type: application/x-www-form-urlencoded")
void from (@Param("field1") String field1, @Param("field2") String field2);
【讨论】:
以上是关于如何使用 Spring Cloud Feign 发布表单 URL 编码的数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spring Cloud Feign 发布表单 URL 编码的数据
spring cloud中如何通过feign调整负载均衡规则