Feign的使用
1、编码器
- 向服务发送请求的过程中,有些情况需要对请求的内容进行处理
- 例如:服务端发布的服务接收的是JSON格式参数,而客户端使用的是对象,这种情况下,就可以使用编码器,将对象转换成JSON对象
1.1、创建服务
package com.atm.cloud
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.ResponseBody
@Controller
public class MyController {
@PostMapping("/person/create")
@ResponseBody
public String createPerson(@RequestBody Person person) {
System.out.println(person.getName() + "---" + person.getAge())
return "创建成功:" + person.getId()
}
}
- 通过createPerson可以知道,需要请求的参数为JSON类型
1.2、客户端服务接口
package com.atm.cloud;
import feign.Headers;
import feign.Param;
import feign.RequestLine;
public interface PersonClient {
@RequestLine("GET /person/{personId}")
Person findPerson(@Param("personId") Integer personId);
@RequestLine("POST /person/create")
@Headers("Content-Type: application/json")
String createPerson(Person person);
class Person {
Integer id;
String name;
Integer age;
}
}
- 客户端服务接口中,使用了@Headers注解,声明请求的内容类型为JSON
1.3、运行类
package com.atm.cloud
import com.atm.cloud.PersonClient.Person
import feign.Feign
import feign.gson.GsonEncoder
public class EncoderMain {
public static void main(String[] args) {
// 获取服务接口
PersonClient personClient = Feign.builder().encoder(new GsonEncoder())
.target(PersonClient.class, "http://localhost:8080/")
// 创建参数的实例
Person person = new Person()
person.id = 1
person.name = "aitemi"
person.age = 18
String reponseStr = personClient.createPerson(person)
System.out.println(reponseStr)
}
}
- 在运行类中,在创建服务接口实例时,使用了encoder方法来指定编码器
- 使用(Feign提供的GsonEncoder类),该类会在发送请求过程中,将请求的对象转换为JSON字符串
- Feign支持插件式的编码器,如果Feign提供的编码器无法满足要求,可以使用自定义的编码器
2、解码器
- 编码器是对请求的内容进行处理,解码器则会对服务响应的内容进行处理
- 例如:解析响应的JSON或者XML字符串,转化为我们需要的对象
2.1、XML的编码和解码
- 除了支持JSON的处理外,Fegin还为XML的处理提供了编码器和解码器
- JAXBEncoder与JAXBDecoder
2.1.1、服务器端发布XML接口
package com.atm.cloud
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RestController
@RestController
public class MyRestController {
@RequestMapping(value = "/person/createXML", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_XML_VALUE)
public String createXMLPerson(@RequestBody Person person) {
System.out.println(person.getName() + "-" + person.getId())
return "<result><message>success</message></result>"
}
}
2.1.2、服务器端引入依赖
- 服务端使用的“spring-boot-starter-web”搭建,默认情况下不支持XML接口
- 所以需要引入以下依赖
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-xml-provider</artifactId>
<version>2.9.0</version>
</dependency>
2.1.3、客户端服务接口
package com.atm.cloud;
import feign.Headers;
import feign.Param;
import feign.RequestLine;
public interface PersonClient {
@RequestLine("GET /person/{personId}")
Person findPerson(@Param("personId") Integer personId);
@RequestLine("POST /person/create")
@Headers("Content-Type: application/json")
String createPerson(Person person);
@RequestLine("POST /person/createXML")
@Headers("Content-Type: application/xml")
Result createPersonXML(Person person);
@XmlRootElement
class Person {
@XmlElement
Integer id;
@XmlElement
String name;
@XmlElement
Integer age;
@XmlTransient
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@XmlTransient
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlTransient
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
@XmlRootElement
class Result {
@XmlElement
String message;
@XmlTransient
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
}
2.1.4、客户端引入依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxb</artifactId>
<version>9.5.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.8</version>
</dependency>
2.1.5、客户端运行类
package com.atm.cloud
import feign.Feign
import feign.jaxb.JAXBContextFactory
import feign.jaxb.JAXBDecoder
import feign.jaxb.JAXBEncoder
public class XmlMain {
public static void main(String[] args) {
JAXBContextFactory jaxbFactory = new JAXBContextFactory.Builder()
.build()
// 获取服务接口
PersonClient personClient = Feign.builder()
.encoder(new JAXBEncoder(jaxbFactory))
.decoder(new JAXBDecoder(jaxbFactory))
.target(PersonClient.class, "http://localhost:8080/")
// 构建参数
Person person = new Person()
person.id = 1
person.name = "aitemi"
person.age = 18
// 调用接口并返回结果
Result result = personClient.createPersonXML(person)
System.out.println(result.message)
}
}
- 请求服务时传入参数为 XML、返回的结果也是 XML
2.2、自定义编码和解码
- Feign的插件式编码与解码器,可以对请求以及处理结果进行处理
- 如果是特殊要求,可以使用自定义编码和解码
- 实现自定义编码器,需要实现Encoder接口的encode方法
- 实现自定义编码器,需要实现Decoder接口的decode方法
package com.atm.cloud;
import java.lang.reflect.Type;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
public class MyEncoder implements Encoder{
public void encode(Object arg0, Type arg1, RequestTemplate arg2)
throws EncodeException {
}
}