1.声明
当前内容用于本人学习和复习之用,当前内容包括配置Feign和使用,使用Feign优化前面的Demo
前面的Demo:添加了Hystrix的Demo
2.pom依赖和基本的配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>SpringCloud-Feign-Demo</groupId>
<artifactId>SpringCloud-Feign-Demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringCloud-Feign-Demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Brixton.SR5</spring-cloud.version>
<!-- <springboot.version>1.3.7.RELEASE</springboot.version> -->
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version> <type>pom</type> <scope>import</scope>
</dependency> -->
</dependencies>
</dependencyManagement>
<dependencies>
<!-- spring cloud 的基本配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<!-- <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> -->
</dependency>
<!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope>
</dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId>
</dependency> -->
<!-- 为其注入负载均衡,主要使用DiscoveryClient和RestTemplate -->
<!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency> -->
<!-- 注入熔断器 -->
<!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency> -->
<!-- 注入feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- spring boot 的基本配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
注释掉hystrix和ribbon,因为当前的feign中已经封装好了
3.使用Feign的基本方式(类似Ribbon的使用)
- 为需要的SpringBoot程序的
入口类添加@EnableFeignClients
- 创建一个访问接口并为其
添加@FeignClient指定访问的服务名称
- 然后添加和需要访问服务中方法一致的方法签名,返回值也保持一致
- 如果需要
传递参数则需要使用@RequestParam、@RequestHeader、@RequestBody方式获取参数
4.使用上面的方式实现修改AppDemo中的内容
修改AppDemo上面的注解为
@EnableFeignClients// 开启feign
@EnableHystrixDashboard //开启熔断器仪表盘
/* @EnableCircuitBreaker */// 启动熔断器
@EnableDiscoveryClient
@SpringBootApplication
public class AppDemo {
/*
* @Bean
*
* @LoadBalanced // 开启负载均衡 public RestTemplate restTemplate() { return new
* RestTemplate(); }
*/
public static void main(String[] args) {
SpringApplication.run(AppDemo.class, args);
}
}
PayService接口,对应pay-service-provider这个服务名称
@FeignClient(value = "pay-service-provider")
public interface PayService {
@RequestMapping("/pay")
String pay(@RequestParam("name") String name, @RequestParam("money") Integer money);
}
PermissService接口,对应permiss-service-provider这个服务名称
@FeignClient(value = "permiss-service-provider")
public interface PermissService {
@RequestMapping("/getPermissByRoleName")
String getPermissByRoleName(@RequestParam("roleName") String roleName);
}
UserInfoService接口,对应userinfo-service-provider这个服务名称
@FeignClient(value = "userinfo-service-provider")
public interface UserInfoService {
@RequestMapping("/getUserInfoByName")
String getUserInfoByName(@RequestParam("name") String name);
@RequestMapping("/login")
String login(@RequestParam("name") String name);
@RequestMapping("/registerUserInfo")
String registerUserInfo(@RequestParam("name") String name);
}
接下来优化AppController中的内容
@RestController
public class AppController {
@Autowired
PermissService permissService;
@Autowired
UserInfoService userInfoService;
// 为该方法采用熔断器
/*
* @HystrixCommand(fallbackMethod = "timeOut", commandProperties = {
*
* @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
* value = "8000") })
*/
@RequestMapping("/getPermiss")
public String getPermiss(String roleName) {
System.out.println("访问App门面中通过角色名称获取用户权限");
return permissService.getPermissByRoleName(roleName);
}
/*
* public String timeOut(String roleName) { System.out.println("访问超时-->" +
* roleName); return "当前访问权限操作,超时了,请过一段时间访问!"; }
*/
@RequestMapping("/getUserInfo")
// 用户信息模块
public String getUserInfo(String name) {
System.out.println("访问App门面中通过用户名称获取用户信息");
return userInfoService.getUserInfoByName(name);
}
@RequestMapping("/login")
public String login(String username) {
System.out.println("访问App门面中通过用户名称来检查登录");
return userInfoService.login(username);
}
@RequestMapping("/register")
public String register(String name) {
System.out.println("访问App门面中注册用户信息");
return userInfoService.registerUserInfo(name);
}
@Autowired
PayService payService;
@RequestMapping("/pay")
public String pay(String name, Integer money) {
System.out.println("访问App门面中支付服务");
return payService.pay(name, money);
}
}
此时发现当前的AppController中的内容非常简单,又回到了原来的SpringBoot中的程序了
5.测试4中的操作
1.启动服务注册中心,随后启动AppDemo,PayServiceApp以及PermissServiceApp(这里就测试这些服务,主要通过AppDemo测试)
2.开始访问
这里可以发现测试成功了,但是访问http://localhost:2008/getUserInfo?name=admin
出现错误,这是因为我们的UserInfoServiceApp并没有启动(是因为我们需要测试feign熔断器
)
6.使用feign实现熔断器的基本操作
1.通过上面创建的访问接口方式创建对应的实现类
,如PayService的实现类PayServiceImpl,并为服务实现类添加@Component注解以注册到Spring容器中
2.这里的实现类中的方法前面必须和PayService中的方法签名完全一致,包括注解
3.为当前的@FeignClient中指定当前的fallback=实现类
,然后当服务出现熔断或者无法访问的时候,就会默认调用fallback类中对应的方法并返回
7.根据6的熔断器的操作进行修改AppDemo中的内容
1.创建默认的服务熔断实现类
PayService的熔断类
/**
* @description PayService服务熔断的默认调用实现类
* @author hy
* @date 2020-05-02
*/
@Component
public class PayServiceImpl implements PayService {
@Override
public String pay(@RequestParam("name") String name, @RequestParam("money") Integer money) {
return "当前支付服务出现问题,请稍后重试!";
}
}
PermissService服务熔断的实现类
/**
* @description PermissService服务熔断的默认调用实现类
* @author hy
* @date 2020-05-02
*/
@Component
public class PermissServiceImpl implements PermissService {
@Override
public String getPermissByRoleName(@RequestParam("roleName") String roleName) {
return "无法访问权限服务,请稍后重试!";
}
}
UserInfoService服务熔断的实现类
/**
* @description UserInfoService服务熔断的默认调用实现类
* @author hy
* @date 2020-05-02
*/
@Component
public class UserInfoServiceImpl implements UserInfoService {
private static final String MSG_STRING = "当前用户信息服务无法访问,请稍后重试!";
@Override
public String getUserInfoByName(@RequestParam("name") String name) {
return MSG_STRING;
}
@Override
public String login(@RequestParam("name") String name) {
return MSG_STRING;
}
@Override
public String registerUserInfo(@RequestParam("name") String name) {
return MSG_STRING;
}
}
2.修改各个@FeignClient中的内容,为其添加fallback类
@FeignClient(value = "pay-service-provider", fallback = PayServiceImpl.class)
@FeignClient(value = "permiss-service-provider", fallback = PermissServiceImpl.class)
@FeignClient(value = "userinfo-service-provider", fallback = UserInfoServiceImpl.class)
8.测试使用Feign方式实现的熔断器
未启动的时候
启动UserInfoServiceApp(这里需要等待一下,多次尝试,因为服务拉取需要时间更新)
测试成功!
9.总结
1.通过使用Feign优化前面的Demo,发现使用了Feign之后controller中的代码少了一半左右,让controller又变成了SpringBoot的controller
2.通过步步操作方式我们发现,Feign优化了RestTemplate的访问方式,优化了Ribbon,而且将熔断器迁移到了外面的实体类中,优化了Hystrix的编写
3.体验完这个Feign发现,使用这个很简单,并且代码也写的很少了
以上纯属个人见解,如有问题请联系本人!