In the previous article can be found when other API services we call by RestTemplate, the parameters needed to be spliced in the URL request, if the parameter less, then perhaps we can live with, if there is more argument, then request string will splicing efficiency is low, and seem silly.
So is there a better solution? The answer is determined there is, Netflix has provided a framework for us: Feign.
Feign Web Service client is a declarative, its aim is to make Web Service calls easier. Feign provides a template for HTTP requests, through a simple interface to write and insert annotations, you can define the parameters of good information HTTP request, format, address and so on.
The Feign will be full proxy HTTP requests, we only need to call it like to call the same method can be completed service requests and related processing. Feign integration Ribbon and Hystrix (About Hystrix we revisit later), you can let us no longer need to explicitly use these two components.
Collectively, Feign has the following characteristics:
- Pluggable annotation support, including Feign JAX-RS annotations and notes;
- HTTP support pluggable encoder and decoder;
- Support Hystrix and its Fallback;
- Support Ribbon load balancing;
- Support compression of HTTP requests and responses.
It looks a bit like RequestMapping mapping Controller layer of our springmvc mode. This model is our very favorite. Feign is @FeignClient to map services.
The first step, on the basis of the new original Feign a module, followed by the introduction of dependencies, dependence Feign introduction, will automatically introduce Hystrix dependent, as follows:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> <version>1.4.0.RELEASE</version> </dependency>
application.yml configuration is as follows:
server: port: 8083 spring: application: name: feign-consumer eureka: client: service-url: defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/
Then add in the previous article and the two provider1 provider2 two service modules several methods, as shown in the following code:
/** * Created by cong on 2018/5/8. */ @RestController public class HelloController { @RequestMapping("/hello") public String hello(){ System.out.println("访问来1了......"); return "hello1"; } @RequestMapping("/hjcs") public List<String> laowangs(String ids){ List<String> list = new ArrayList<>(); list.add("laowang1"); list.add("laowang2"); list.add("laowang3"); return list; } //新增的方法 @RequestMapping(value = "/hellol", method= RequestMethod.GET) public String hello(@RequestParam String name) { return "Hello " + name; } @RequestMapping(value = "/hello2", method= RequestMethod.GET) public User hello(@RequestHeader String name, @RequestHeader Integer age) { return new User(name, age); } @RequestMapping(value = "/hello3", method = RequestMethod.POST) public String hello (@RequestBody User user) { return "Hello "+ user. getName () + ", " + user. getAge (); } }
Then the code used above is required User class, as follows:
/ ** * 2017/12/2 the Created by Cong. * / Public class {the User Private String name; Private Age Integer; // serialized when transmitted constructor must be available, or be wrong public the User () { } the User public (String name, Integer Age) { this.name = name; this.age = Age; } public String getName () { return name; } public void the setName (String name) { this.name = name; } public Integer getAge () { return Age; } public void the setAge (Integer Age) { this.age = Age; } }
Then the mapping service calls using Feign of @FeignClient ( "Service Name"). code show as below:
HJC Package Penalty for; Import org.springframework.cloud.netflix.feign.FeignClient; Import org.springframework.web.bind.annotation *;. / ** * the Created by Cong ON 2018/5/17. * / // the Configuration = xxx .class class configuration Hystrix some precise attribute
// value = "service name you used"
@FeignClient (value = "the Hello-service", fallback = FeignFallBack.class) public interface FeignService { mapping service method // path @RequestMapping ( "/ Hello") String Hello (); @RequestMapping (value = "/ hellol", Method = RequestMethod.GET) String Hello (@RequestParam ( "name") String name); @RequestMapping (value = " / hello2 ", method = RequestMethod.GET) the User Hello (@RequestHeader ( "name") String name, @RequestHeader ( "age") Integer age); @RequestMapping(value = "/hello3", method= RequestMethod.POST) String hello(@RequestBody User user); }
Controller then injection layer FeiService this interface, remote service call, as follows:
/** * Created by cong on 2018/5/17. */ @RestController public class ConsumerController { @Autowired FeignService feignService; @RequestMapping("/consumer") public String helloConsumer(){ return feignService.hello(); } @RequestMapping("/consumer2") public String helloConsumer2(){ String r1 = feignService.hello("hjc"); String r2 = feignService.hello("hjc", 23).toString(); String r3 = feignService.hello(new User("hjc", 23)); return r1 + "-----" + r2 + "----" + r3; } }
Next, at startup class Feign module where Eureka client notes marked @EnableDiscoveryClient Feign client notes @EnableFeignClients, code is as follows:
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class FeignApplication { public static void main(String[] args) { SpringApplication.run(FeignApplication.class, args); } }
Next Start Start type, browser type localhost: 8083 / consumer results are as follows:
Load balancing can be seen polling appear hello1, hello2.
Then continues input in the browser localhost: 8083 / consumer2, results are as follows:
Next, we performed a service degradation under Feign use declarative call to service, then we must create a new class to inherit FeignFallBack FeiService, code is as follows:
package hjc; import org.springframework.stereotype.Component; /** * Created by cong on 2018/5/17. */ @Component public class FeignFallBack implements FeignService{
//实现的方法是服务调用的降级方法 @Override public String hello() { return "error"; } @Override public String hello(String name) { return "error"; } @Override public User hello(String name, Integer age) { return new User(); } @Override public String hello(User user) { return "error"; } }
接着我们再把那两个服务提供模块provider1,provider2模块进行停止,运行结果如下所示:
可以看到我们这几个调用,都进行了服务降级了。
那么如果我们想精确的控制一下Hystrix的参数也是可以的,比方说跟Hystrix结合的参数,那么可以在FeignClient注解里面配置一个Configuration=XXX类.class属性,在哪个类里面精确的指定一下属性。
或者在application.yml里面配置,如下:
hystrix: command: default: execution: isolation: thread: timeoutinMilliseconds: 5000 ribbon: connectTimeout: 500 #如果想对单独的某个服务进行详细配置,如下 hello-service: ribbon: connectTimeout: 500
这里满足了我们大部分场景的调用,但是有写精细场景,还是要用原生的Hystrix,跟我们之前的Hystrix用法一下,不要走Feign客户端调用就行了,如下:
/** * Created by cong on 2018/5/17. */ public class HjcCommand extends HystrixCommand { protected HjcCommand(HystrixCommandGroupKey group) { super(group); } @Override protected Object run() throws Exception { return null; } }
那么我们如果想用原声的HystrixCommand去搞一个异步请求怎么办?代码如下:
首先再引入一个依赖,feign客户端没有默认引入进来,需要我们自己引入:
<dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> <version>1.5.9</version> </dependency>
接着用HystrixCommand注解方式实现:
/** * Created by cong on 2018/5/17. */ @Service public class HjcCommand { @Autowired private FeignService feignService; //同步方式 @HystrixCommand public Future<String> getEmployeesAsync(){ return new AsyncResult<String>() { @Override public String invoke() { return feignService.hello("hjc"); } }; } //用同步方式还不如直接用Feign客户端 @HystrixCommand public String getEmployeesAsync1(){ return feignService.hello("laowang"); } }
This is not enough, we also need to declare a section, HystrixConfiguration, then, will be added to the spring HystrixConfiguration management, as follows:
@Configuration public class HystrixConfiguration { @Bean public HystrixCommandAspect hystrixAspect(){ return new HystrixCommandAspect(); } }
Transfer from https://www.cnblogs.com/huangjuncong/p/9053576.html