如何使用 Spring Cloud Feign POST 形成-url-编码数据
How to POST form-url-encoded data with Spring Cloud Feign
使用 spring-mvc
注释:
- 如何定义一个
@FeignClient
可以 POST
form-url-encoded
?
对 Feign 使用 FormEncoder:
你的 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)
}
完整的 Java 代码和简化版本的 kazuar 解决方案,适用于 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>
对于 POST 中的 url 格式编码数据,您必须在 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);
只是为了补充 ,也可以使用 POJO 代替 Map<String, ?>
以将表单参数传递给假客户端:
@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
@FormProperty
注释允许设置自定义字段名称;请注意,POJO 的静态或最终字段以及继承的字段,不会 序列化为表单内容。
对于 Feign.Builder,我的工作没有 JacksonEncoder,只有 Feign FormEncoder:
将 FormEncoder 添加到您的 Feign.Builder:
SomeFeign sample = Feign.builder()
.encoder(new FormEncoder()) <==difference here
.target(SomeFeign.class, "http://sample.test.org");
我添加的feign依赖pom.xml:
<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 给出的假接口:
@RequestLine("POST /submit/form")
@Headers("Content-Type: application/x-www-form-urlencoded")
void from (@Param("field1") String field1, @Param("field2") String field2);
使用 spring-mvc
注释:
- 如何定义一个
@FeignClient
可以POST
form-url-encoded
?
对 Feign 使用 FormEncoder:
你的 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)
}
完整的 Java 代码和简化版本的 kazuar 解决方案,适用于 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>
对于 POST 中的 url 格式编码数据,您必须在 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);
只是为了补充 Map<String, ?>
以将表单参数传递给假客户端:
@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
@FormProperty
注释允许设置自定义字段名称;请注意,POJO 的静态或最终字段以及继承的字段,不会 序列化为表单内容。
对于 Feign.Builder,我的工作没有 JacksonEncoder,只有 Feign FormEncoder:
将 FormEncoder 添加到您的 Feign.Builder:
SomeFeign sample = Feign.builder()
.encoder(new FormEncoder()) <==difference here
.target(SomeFeign.class, "http://sample.test.org");
我添加的feign依赖pom.xml:
<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 给出的假接口:
@RequestLine("POST /submit/form")
@Headers("Content-Type: application/x-www-form-urlencoded")
void from (@Param("field1") String field1, @Param("field2") String field2);