Feign是一个声明式的Web Service客户端,比Ribbon好用,默认也是轮巡。我们只需要使用Feign创建一个接口,并用注解就好了。如果你基于spring cloud发布一个接口,实际上就是支持http协议的,对外发布的就是一个最普通的mvc的http接口。我们使用feign注解,实际上它会对这个接口生成动态代理,从eureka的readonly中拿到其他服务信息、进行http请求调用。
feign案例编写:
1. 导包
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> </parent> <!-- springcloud依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- eureka客户端依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!-- feign客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> </dependencies>
2. 配置application.yml文件
# 项目访问路径前缀
server:
context-path: /feign
port: 8085
# 设置服务名称,服务会以这个名字注册到eureka服务器上
spring:
application:
name: feign
# 设置eureka服务器的注册地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
#ribbon的超时时间, 防止feign调用超时
ribbon:
ReadTimeout: 15000
ConnectTimeout: 15000
MaxAutoRetries: 1 #同一台实例最大重试次数,不包括首次调用
MaxAutoRetriesNextServer: 1 #重试负载均衡其他的实例最大重试次数,不包括首次调用
OkToRetryOnAllOperations: false #是否所有操作都重试
3. 主函数入口开启eureka和feign客户端
@SpringBootApplication @EnableEurekaClient//开启eureka @EnableFeignClients//开启feign public class FeignMain { public static void main(String[] args) { new SpringApplicationBuilder(FeignMain.class).web(true).run(args); } }
4. 调用接口
@RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/test") public Map test() { return userService.test("张三"); } @RequestMapping("/testObj") public User testObj() { return userService.testObj(new User()); } }
5. 编写feign调用的服务层。
import java.util.Map; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import com.model.User; //name 目标的服务名 目标的url前缀 @FeignClient(name ="demo",path="/demo") public interface UserService { // 调用police服务的testOut接口 @RequestMapping("/testOut") public Map test(@RequestParam("name") String name); // 调用police服务的testOutObj接口 @RequestMapping("/testOutObj") public User testObj(@RequestBody User user); }
feign客户端就开发完成了; 我们来看看提供服务的另一个项目的接口。
@RestController public class MyController { @RequestMapping("/testOut") public Map test(@RequestParam("name") String name,HttpServletRequest req) { Map m = new HashMap<>(); m.put("url", req.getRequestURL().toString()); m.put("name", name); try { Thread.sleep(16000); } catch (InterruptedException e) { } return m; } @RequestMapping("/testOutObj") public User testObj(@RequestBody() User user,HttpServletRequest req) { user.setUrl(req.getRequestURL().toString()); try { Thread.sleep(14000); } catch (InterruptedException e) { } return user; } }
测试: 由于超时时间设置的15s, 而两个接口分别阻塞14s ,16s ,所以第二个接口会超时报错。