在前面的文章中可以发现当我们通过resttemplate调用其它服务的api时,所需要的参数须在请求的url中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。
那么有没有更好的解决方案呢?答案是确定的有,netflix已经为我们提供了一个框架:feign。
feign是一个声明式的web service客户端,它的目的就是让web service调用更加简单。feign提供了http请求的模板,通过编写简单的接口和插入注解,就可以定义好http请求的参数、格式、地址等信息。
而feign则会完全代理http请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。feign整合了ribbon和hystrix(关于hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。
总起来说,feign具有如下特性:
- 可插拔的注解支持,包括feign注解和jax-rs注解;
- 支持可插拔的http编码器和解码器;
- 支持hystrix和它的fallback;
- 支持ribbon的负载均衡;
- 支持http请求和响应的压缩。
这看起来有点像我们springmvc模式的controller层的requestmapping映射。这种模式是我们非常喜欢的。feign是用@feignclient来映射服务的。
首先第一步,在原来的基础上新建一个feign模块,接着引入相关依赖,引入feign依赖,会自动引入hystrix依赖的,如下:
1
2
3
4
5
6
7
8
9
10
11
|
<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配置如下:
1
2
3
4
5
6
7
8
9
|
server: port: 8083 spring: application: name: feign-consumer eureka: client: service-url: defaultzone: http: //localhost:8888/eureka/,http://localhost:8889/eureka/ |
接着在前面文章中的的的两个provider1和provider2两个模块的服务新增几个方法,如下代码所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/** * 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 (); } } |
接着是上面代码所需用到的user类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/** * created by cong 2017/12/2. */ public class user { private string name; private integer age; //序列化传输的时候必须要有空构造方法,不然会出错 public user() { } public user(string name, integer age) { this .name = name; this .age = age; } public string getname() { return name; } public void setname(string name) { this .name = name; } public integer getage() { return age; } public void setage(integer age) { this .age = age; } } |
接下来用feign的@feignclient(“服务名称”)映射服务调用。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package hjc; import org.springframework.cloud.netflix.feign.feignclient; import org.springframework.web.bind.annotation.*; /** * created by cong on 2018/5/17. */ //configuration = xxx.class 这个类配置hystrix的一些精确属性 //value=“你用到的服务名称” @feignclient (value = "hello-service" ,fallback = feignfallback. class ) public interface feignservice { //服务中方法的映射路径 @requestmapping ( "/hello" ) string hello(); @requestmapping (value = "/hellol" , method= requestmethod.get) string hello( @requestparam ( "name" ) string name) ; @requestmapping (value = "/hello2" , method= requestmethod.get) user hello( @requestheader ( "name" ) string name, @requestheader ( "age" ) integer age); @requestmapping (value = "/hello3" , method= requestmethod.post) string hello( @requestbody user user); } |
接着在controller层注入feiservice这个接口,进行远程服务调用,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/** * 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; } } |
接着在feign模块的启动类哪里打上eureka客户端的注解@enablediscoveryclient feign客户端的注解
1
2
3
4
5
6
7
8
9
10
11
|
@enablefeignclients ,代码如下: @springbootapplication @enablediscoveryclient @enablefeignclients public class feignapplication { public static void main(string[] args) { springapplication.run(feignapplication. class , args); } } |
接着启动启动类,浏览器上输入localhost:8083/consumer 运行结果如下:
可以看到负载均衡轮询出现hello1,hello2。
接着继续在浏览器上输入localhost:8083/consumer2,运行结果如下:
接下来我们进行feign声明式调用服务下的,服务降级的使用,那么我们就必须新建一个feignfallback类来继承feiservice,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
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里面配置,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
hystrix: command: default : execution: isolation: thread: timeoutinmilliseconds: 5000 ribbon: connecttimeout: 500 #如果想对单独的某个服务进行详细配置,如下 hello-service: ribbon: connecttimeout: 500 |
这里满足了我们大部分场景的调用,但是有写精细场景,还是要用原生的hystrix,跟我们之前的hystrix用法一下,不要走feign客户端调用就行了,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * 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 ; } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/huangjuncong/p/9053576.html