Spring Cloud-Feign 客户端

1.Feign是什么?

在Spring Cloud Netflix栈中,每个微服务都以HTTP接口的形式暴露自身服务,因此在调用远程服务时就必须使用到HTTP客户端。我们可以使用JDK原生的URLConnection、Apache的Http Client、Netty的异步HTTP Client,还有之前我们使用到Spring的RestTemplate,这些都可以实现远程调用。

2.Feign的基本使用

首先需要引入依赖

pom.xml

  org.springframework.cloud spring-cloud-starter-openfeign 1.4.3.RELEASE 

application.yml

server: port: 8900spring: application: name: consumer-order-feignuser: url: http://localhost:7900/user/eureka: client: service-url: defaultZone: http://user:user@localhost:8888/eureka/然后我们来看下其他项目中提供服务这块提供的接口,和之前一样

UserController.java

package com.ithzk.spring.cloud.controller;import com.ithzk.spring.cloud.entity.User;import com.netflix.discovery.EurekaClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RestController;/** * @author hzk * @date 2018/5/13 */@RestController("/")public class UserController { @Autowired private EurekaClient eurekaClient; @Value("${server.port}") private String port; @GetMapping("/user/{id}") public User getUser(@PathVariable Integer id){ return new User(id,"zs",20); } @GetMapping("/eureka/info") public String info(){ //InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("PROVIDER-USER", false); //return instanceInfo.getHomePageUrl()+ ":" +instanceInfo.getPort(); return port; } @PostMapping("/get_user") public User getUser(User user){ user.setName("provider_user_get_user"); return user; }}根据提供者接口编写Feign客户端

CustomFeignClient.java

package com.ithzk.spring.cloud.feign;import com.ithzk.spring.cloud.entity.User;import org.springframework.cloud.netflix.feign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping;/** * @author hzk * @date 2018/5/20 */@FeignClient("PROVIDER-USER")public interface CustomFeignClient { //C版本的 spring 是不能写 GETMAPPING 的必须用RequestMapping @GetMapping("/user/{id}") User getOrder(@PathVariable("id") Integer id); /** * 如果传递复杂参数,feign默认都会以方式去请求 * 无法访问,提供者必须为post方式消费者才可使用,如果非要使用get传递多个数据,只能以普通方式传递 * @param user * @return */ @PostMapping("/get_user") User getUser(User user);}

OrderController.java

package com.ithzk.spring.cloud.controller;import com.ithzk.spring.cloud.entity.User;import com.ithzk.spring.cloud.feign.CustomFeignClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;/** * @author hzk * @date 2018/5/13 */@RestControllerpublic class OrderController { @Autowired private CustomFeignClient customFeignClient; @GetMapping("/order/{id}") public User getOrder(@PathVariable Integer id){ User user = customFeignClient.getOrder(id); return user; } @GetMapping("/get_user") public User getUser(User user){ User feignUser = customFeignClient.getUser(user); return feignUser; }}加上@EnableFeignClients就可以使用feign客户端,启动后成功请求获取数据,这就是feign的基本使用了

OrderApp.java

package com.ithzk.spring.cloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.netflix.feign.EnableFeignClients;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;/** * Hello world! * */@SpringBootApplication@EnableFeignClientspublic class OrderApp { //相当于xml中的bean标签 用于调用当前方法获取到指定的对象 @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } public static void main( String[] args ) { SpringApplication.run(OrderApp.class); }}

3.Feign自定义配置

Feign客户端本身有自己默认的配置,之前学习Ribbon的时候,未指定配置时会选择Ribbon自身默认的配置,这里也一样,Feign也可以自定义配置。编写配置类,这里和Ribbon一样,要确保不能被主类扫描到,否则未知错误,最简单的方法依然是不放在和主类同包或子包下

MyFeignClientConfig.java

package com.ithzk.spring.config;import feign.Contract;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author hzk * @date 2018/5/20 */@Configurationpublic class MyFeignClientConfig { /** * 将契约改为feign原生的默认契约。这样就可以使用feign自带的注解 * @return */ @Bean public Contract feignContract() { return new feign.Contract.Default(); }}自定义客户端时指定使用配置类

CustomFeignClient.java

package com.ithzk.spring.cloud.feign;import com.ithzk.spring.cloud.entity.User;import com.ithzk.spring.config.MyFeignClientConfig;import feign.Param;import feign.RequestLine;import org.springframework.cloud.netflix.feign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping;/** * @author hzk * @date 2018/5/20 */@FeignClient(name = "PROVIDER-USER",configuration = MyFeignClientConfig.class)public interface CustomFeignClient { /** * 组合注解,第一个是请求方式,第二个是参数 用空格分割 * 注意使用RequestLine的时候必须使用 Param 注解 * 这里的RequestLine是feign自带注解,修改为feign默认契约后可以使用 * @param id * @return */ @RequestLine("GET /user/{id}") User getOrder(@Param("id") Integer id); /** * 如果传递复杂参数,feign默认都会以方式去请求 * 无法访问,提供者必须为post方式消费者才可使用,如果非要使用get传递多个数据,只能以普通方式传递 * @param user * @return */ @RequestLine("GET /get_user") User getUser(User user);}这里通过配置自定义配置,从而达成可以使用一些Feign提供的注解

4.Feign客户端URL指定方式

上面我们通过name指定服务Feign客户端,还有一种方式可以通过指定URL去注入Feign客户端首先我们来看一下,Eureka服务的一些信息http://localhost:8888/eureka/apps http://localhost:8888/eureka/apps/CONSUMER-ORDER-FEIGN 
Spring Cloud-Feign 客户端

Spring Cloud-Feign 客户端

可以看出来这里面包含了注册在Eureka server上的服务的一些相关信息我们利用Feign客户端去访问试试

CustomFeignClientTwo.java

package com.ithzk.spring.cloud.feign;import com.ithzk.spring.config.MyFeignClientConfigTwo;import org.springframework.cloud.netflix.feign.FeignClient;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;/** * @author hzk * @date 2018/5/20 */@FeignClient(name = "customfeign",url = "http://localhost:8888/",configuration = MyFeignClientConfigTwo.class)public interface CustomFeignClientTwo { @RequestMapping("/eureka/apps/{servicename}") String getServicesName(@PathVariable("servicename") String servicename);}

MyFeignClientConfigTwo .java

package com.ithzk.spring.config;import feign.Contract;import feign.Logger;import feign.auth.BasicAuthRequestInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author hzk * @date 2018/5/20 */@Configurationpublic class MyFeignClientConfigTwo { /** * 用于创建用户名和密码的对象 * @return */ @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){ return new BasicAuthRequestInterceptor("user","user"); }}如果CustomFeignClientTwo 不加上这个自定义配置,并且里面未配有用户名密码信息,则会出现权限问题无法获取数据
Spring Cloud-Feign 客户端

启动成功访问http://localhost:8900/service/info/CONSUMER-ORDER-FEIGN
Spring Cloud-Feign 客户端

5.输出日志配置

Feign本身也提供了日志输出功能,只需配置文件加一些参数,对应自定义配置中设置级别即可

application.yml

server: port: 8900spring: application: name: consumer-order-feignuser: url: http://localhost:7900/user/eureka: client: service-url: defaultZone: http://user:user@localhost:8888/eureka/logging: level: com.ithzk.spring.cloud.feign.CustomFeignClientTwo: debug #给指定的 feign 设置日志输出级别,只有在 debug 的情况下才会打印日志

MyFeignClientConfigTwo .java

package com.ithzk.spring.config;import feign.Logger;import feign.auth.BasicAuthRequestInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author hzk * @date 2018/5/20 */@Configurationpublic class MyFeignClientConfigTwo { /** * 用于创建用户名和密码的对象 * @return */ @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){ return new BasicAuthRequestInterceptor("user","user"); } /** * 配置要输出的日志是哪些,必须在debug 模式下才可以输出 * */ @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; }}
Spring Cloud-Feign 客户端

这样很简单就配置好了日志输出


分享到:


相關文章: