Spring Cloud应用(三)---feign使用

feign相对于httpclient与ribbon,在使用风格上更加倾向于面向对象,使用如下:

使用feign需要引入的jar包,使用pom:

		<dependency>
			<groupId>com.netflix.feign</groupId>
			<artifactId>feign-core</artifactId>
			<version>8.18.0</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.netflix.feign</groupId>
			<artifactId>feign-gson</artifactId>
			<version>8.18.0</version>
			<scope>runtime</scope>
		</dependency>

feign-gson模块是为了以json的形式与服务器交互,使用其中的编码器与解码器。

当请求参数为普通字符串时:

		PersonClient target = Feign.builder()
		.decoder(new GsonDecoder())
		.encoder(new GsonEncoder())
		.target(PersonClient.class, "http://localhost:8000");
		
//		参数为字符串
		Person personById = target.getPersonById(12);
		System.out.println(personById);

请求参数为对象时,用json编码后传输:

//		参数为对象,会由解码器与Headers注解完成将对象以json格式传递给服务器
		Person person = new Person();
		person.setId(22);
		person.setName("hu");
		person.setDesc("desc");
		Person personByEntity = target.getPersonByEntity(person);
		System.out.println(personByEntity);

对应的PersonClient为:

package com.hurricane.learn.feign.client;

import com.hurricane.learn.feign.entity.Person;

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

public interface PersonClient {
	
	/**
	 * 将服务器返回的json转成对象,需要解码器GsonDecoder
	 * 从客户端向服务器传递普通参数,格式如下
	 * @param id
	 * @return
	 */
	@RequestLine("GET /person/{id}")
	Person getPersonById(@Param("id") int id);
	
	
	/**
	 * 从客户端向服务器传递对象参数,需要编码器GsonEncoder
	 * 并且要注意添加header注解,如下,
	 * 对应的服务器端的服务接口处定义应为
	 * public Person getPersonByEntity(@RequestBody Person p,HttpServletRequest request)
	 * 注意使用RequestBody注解
	 * @param p
	 * @return
	 */
	@RequestLine("GET /person/entity")
	@Headers("Content-Type: application/json")
	Person getPersonByEntity(Person p);
	
	//Headers标签不可省略
	@RequestLine("GET /person/entity/xml")
	@Headers("Content-Type: application/xml")
	Person getPersonByEntityXml(Person p);

}

在服务器端,接收参数为简单类型,使用@PathVariable或@RequestParam即可进行获取,对于接收的是json时,应使用@RequestBody,这样spring会自动将json转换为对象(当然,接收json类型参数时,使用@RequestParam也是可以接收到的)。

feign客户端使用的服务器端的接口为:

	@RequestMapping("/{id}")
	public Person getPerson(@PathVariable("id") int id,HttpServletRequest request) {
		Person person = new Person();
		person.setId(id);
		person.setName("hurricane");
		person.setDesc(request.getRequestURI().toString());
		return person;
	}
	
	@RequestMapping("/entity")
	public Person getPersonByEntity(@RequestBody Person p,HttpServletRequest request) {
		p.setName(p.getName()+"---from server");
		return p;
	}

除了使用json作为数据传输的格式,feign还支持xml(不止json、xml,因为feign提供了编码器与解码器,可以任意自定义传输格式,只要与服务器端的接收匹配即可)。

在使用xml作为传输格式时,应注意引入类似于feign-gson的模块feign-jaxb,

		<dependency>
			<groupId>com.netflix.feign</groupId>
			<artifactId>feign-jaxb</artifactId>
			<version>8.18.0</version>
			<scope>runtime</scope>
		</dependency>

feign-jaxb中包含了对xml的编码器与解码器,feign的客户端的定义为:

		JAXBContextFactory jaxbFactory = new JAXBContextFactory.Builder().build();
		PersonClient target = Feign.builder()
		.encoder(new JAXBEncoder(jaxbFactory))
		.decoder(new JAXBDecoder(jaxbFactory))
		.target(PersonClient.class, "http://localhost:8000");
		
		Person person = new Person();
		person.setId(22);
		person.setName("hurricane");
		person.setDesc("desc");
		Person personByEntityXml = target.getPersonByEntityXml(person);
		System.out.println(personByEntityXml);

对应的PersonClient为:

	//Headers标签不可省略
	@RequestLine("GET /person/entity/xml")
	@Headers("Content-Type: application/xml")
	Person getPersonByEntityXml(Person p);

为了配合xml的编码器应该再Person的实体类上加入@XmlRootElement注解,如下:

@XmlRootElement
public class Person {

还有一个注解@XmlElement,可以选择性使用,对于Person的每个属性,要么应有getter方法,要么应在属性上加入@XmlElement注解,才能让编码器将该属性传递到服务器端,此外@XmlElement(属性上的)注解不应与getter方法同时存在,同时存在会抛异常说存在重复的属性(@XmlElement放在getter方法上没问题,但是没必要)。若Person的一个属性既没有@XmlElement注解又没有getter方法,则该属性值无法被传递到服务器端。

在服务器端,为了能让springboot的应用能够接受xml形式的参数,应该加入依赖的jar包,pom为:

		<dependency>
			<groupId>com.fasterxml.jackson.jaxrs</groupId>
			<artifactId>jackson-jaxrs-xml-provider</artifactId>
			<version>2.9.5</version>
		</dependency>

对应的服务端接口为:

	@RequestMapping(value="/entity/xml",consumes = MediaType.APPLICATION_XML_VALUE, 
			produces = MediaType.APPLICATION_XML_VALUE)
	public String getPersonByEntityXml(@RequestBody Person p,HttpServletRequest request) throws IOException {
		System.out.println("xml请求成功");
		System.out.println(p);
		p.setName(p.getName()+"---from server");
		return "<person><id>22</id><name>hurricane---from server</name><desc>descc</desc></person>";
	}

consumes参数即使不指定,也能够正常接收到值,但是为了服务器的稳定性,应该对请求参数的格式做相应的限定,produces属性必须指定,来让springboot将Person实体类转换为xml,返回给客户端。

可以看到上面的服务器接口中返回的是一个字符串,这是因为spring默认转换成的相应的xml是:

<Person><id>22</id><name>hurricane---from server</name><desc>descc</desc></Person>

注意Person标签被大写了,这使得feign客户端解析失败,为了能够正常的接收服务器端的xml格式的数据,才返回的字符串,在实际使用中可以通过自定义的解码器来解析,但是常规操作应该也存在,暂时还不清楚。

feign的设计使得feign使用具有很大的灵活性,客户端、注解解析器、编码器、解码器都支持可插拔,如下:

		PersonMyClient target = Feign.builder()
				.client(new MyFeignClient())	//客户端自定义
				.contract(new MyContract())		//注解解析器自定义
				.decoder(new GsonDecoder())		//解码器自定义
				.encoder(new GsonEncoder())		//编码器自定义
				.target(PersonMyClient.class, "http://localhost:8000");

 

具体可以参考杨恩雄的博客:https://my.oschina.net/JavaLaw/blog?sort=time&p=5&temp=1525411026413

 

 

 

参考:

 

  • 杨恩雄的视频教程

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值