Feign的目标
feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。
Feign原理简述
- 启动时,程序会进行包扫描,扫描所有包下所有@FeignClient注解的类,并将这些类注入到spring的IOC容器中。当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate
- RequestTemplate中包含请求的所有信息,如请求参数,请求URL等。
- RequestTemplate声场Request,然后将Request交给client处理,这个client默认是JDK的HTTPUrlConnection,也可以是OKhttp、Apache的HTTPClient等。
- 最后client封装成LoadBaLanceClient,结合ribbon负载均衡地发起调用。
引入Feign
1 2 3 4 5 6 7 8
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
|
- 当然,前提是已经有了注册中心Eureka(贴上 Eureka )
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId> spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
|
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 39 40 41 42 43 44
| server: port: 9000
eureka: client: serviceUrl: defaultZone: http://127.0.0.1:9999/eureka instance: prefer-ip-address: true
spring: application: name: armstype
datasource: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://---------:10007/arms?characterEncoding=utf-8&useSSL=true
username: ------ password: ------
thymeleaf: cache: false prefix: classpath:/templates/ suffix: .html encoding: UTF-8 mode: HTML5
jpa: database-platform: org.hibernate.dialect.MySQL5InnoDBDialect database: MySQL generate-ddl: true show-sql: true
hibernate: ddl-auto: update
|
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 39 40 41 42 43 44 45 46
| server: port: 9001
eureka: client: serviceUrl: defaultZone: http://127.0.0.1:9999/eureka instance: prefer-ip-address: true
spring: application: name: userinfo
datasource: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://---------:10007/arms?characterEncoding=utf-8&useSSL=true
username: ------ password: ------
thymeleaf: cache: false prefix: classpath:/templates/ suffix: .html encoding: UTF-8 mode: HTML5
jpa: database-platform: org.hibernate.dialect.MySQL5InnoDBDialect database: MySQL generate-ddl: true show-sql: true
hibernate: ddl-auto: update
jwt: config: key: zby expire: 120000
|
实例目的: 在userinfo的微服务中调取armstype中的test()方法
上面我们已经引入了相关依赖,这里我们声明哪些服务作为Eureka
的客户端存在、有哪些服务可以在Eureka中可以被发现,两个注解搞定
1 2
| @EnableDiscoveryClient @EnableFeignClients
|
发现服务和被发现服务都开启这两个注释
armstype中被调用的方法:
1 2 3 4 5
| @ResponseBody @GetMapping("test") public String test(){ return "12345"; }
|
- 在userinfo服务中创建接口文件里链接到 armstype 服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.zby.client;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@Component @FeignClient(name = "armstype") public interface client { @GetMapping(value = "arsenal/view") ModelAndView view(HttpServletRequest request);
@GetMapping("arsenal/test") String test();
}
|
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
| package com.zby.controller;
import com.zby.client.client; import com.zby.entity.Result;
import com.zby.entity.User; import com.zby.service.UserService;
import com.zby.util.IdWorker; import com.zby.util.JwtUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
@RequestMapping("user") public class UserController {
@Autowired private client client;
@ResponseBody @GetMapping(value = "test") public String test(){ return client.test(); } }
|
可以看到访问地址中的端口是 userinfo
服务的端口,但是依然通过Feign来执行了 armstype
中的test()
方法