一,OpenFeign简介
1、Feign是什么??http请求
Feign是集成了负载均衡、熔断机制、Http请求管理等功能的框架,作用是做微服务通信。Feign目前已经停止维护了,被Spring的OpenFeign接替实现后续功能。
负载均衡:服务器承担的压力就是负载,压力越大负载越大;均衡就是降低服务器承担的压力。
熔断机制:微服务之间通信的时候,A微服务给B微服务发送请求来获得B微服务里的数据。如果B微服务处于宕机状态,这样当A给B发请 求的时候,A会一直处于等待状态,等待B给出响应。这样对客户来说就不友好了。 熔断机制就是A给B发请求,过了一会没有 响应,于是A就自动切断了这一次请求,马上给客户一个响应。【熔断后面会详细学习,今天不做过多解释。】
http请求管理:就是A 的Controller 给 B 的Controller 发送了一个Http请求。
2、OpenFeign是什么
OpenFeign是SpringCloud下的一个框架,用于做微服务通信的,采用RESTFull风格做服务直接通信。实现方式也是通过发送http请求进行通信的,但是OpenFeign是在Spring环境下实现的,天然支持Spring的思想和注解,让开发变得更简单。
3、Feign和openFeign有什么区别
Feign对HTTP进行了封装,实现的微服务通信,OpenFeign是在Spring环境下对Feign进行的二次升级,让OpenFeign框架更简单,更贴近Spring,开发者在使用时减少了很多障碍。
官方文档: Spring Cloud OpenFeign
达到的效果:A项目发送请求给B项目,B项目可以访问自己的也可以访问A的。
二,设置OpenFeign
1、 需要开启nacos 和redis
2、准备工作
【0.使用SpringSession共享例子】
【1.对sessiondemo1做改动】
#1.添加实体类 Score
package com.jr.entry;
@Data
public class Score {
private String name;
private Double score;
}
#2.添加实体类 UserDto
package com.jr.entry;
@Data
public class UserDto {
private String id;
private String name;
private String password;
private List<Score> scoreList;
}
#3.添加接口 IUserService
package com.jr.service;
public interface IUserService {
public UserDto info();
}
#4.添加接口实现类 UserServiceImpl
package com.jr.service.impl;
@Service
public class UserServiceImpl implements IUserService {
@Override
public UserDto info() {
return new UserDto();
}
}
#5.添加 UserController 类
package com.jr.controller;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@GetMapping
public Result info(){
UserDto userDto=userService.info();
return Result.ok().put("data",userDto);
}
}
#6.添加枚举 ResultCode
package com.jr.util;
public enum ResultCode {
SUCCESS(0, "请求成功"),
ERROR(1, "请求失败"),
;
private int code;
private String message;
ResultCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
#7.添加工具类 Result
package com.jr.util;
@Data
public class Result {
private Integer code;
private String message;
private Map<String, Object> map = new HashMap<>();
private Result() {
}
public static Result ok() {
Result r = new Result();
r.setCode(ResultCode.SUCCESS.getCode());
r.setMessage(ResultCode.SUCCESS.getMessage());
return r;
}
public static Result error() {
Result r = new Result();
r.setCode(ResultCode.ERROR.getCode());
r.setMessage(ResultCode.ERROR.getMessage());
return r;
}
public Result put(String key, Object value) {
map.put(key, value);
return this;
}
public Object get(String key) {
return map.get(key);
}
}
#8.修改application.properties文件中,项目注册名字:
spring.application.name=openfeignDemo1
#9.启动项目,访问:
【2.对sessiondemo2做改动】
#1.添加实体类 Score
package com.jr.entry;
@Data
public class Score {
private String name;
private Double score;
}
#2.添加实体类 UserDto
package com.jr.entry;
@Data
public class UserDto {
private String id;
private String name;
private String password;
private List<Score> scoreList;
}
#3.添加接口 IUserService
package com.jr.service;
public interface IScoreService {
public List<Score> info();
}
#4.添加接口实现类 UserServiceImpl
package com.jr.service.impl;
@Service
public class ScoreServiceImpl implements IScoreService {
@Override
public List<Score> info() {
List<Score> result = new ArrayList<>();
for (int i=0;i<3;i++){
Score score=new Score();
score.setName("name"+i);
score.setScore(Math.random()*10);
result.add(score);
}
return result;
}
}
#5.添加 UserController 类
package com.jr.controller;
@RestController
@RequestMapping("/score")
public class ScoreController {
@Autowired
private IScoreService scoreService;
@GetMapping("/info")
public Result info(){
List<Score> list=scoreService.info();
return Result.ok().put("list",list);
}
}
#6.添加枚举 ResultCode
package com.jr.util;
public enum ResultCode {
SUCCESS(0, "请求成功"),
ERROR(1, "请求失败"),
;
private int code;
private String message;
ResultCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
#7.添加工具类 Result
package com.jr.util;
@Data
public class Result {
private Integer code;
private String message;
private Map<String, Object> map = new HashMap<>();
private Result() {
}
public static Result ok() {
Result r = new Result();
r.setCode(ResultCode.SUCCESS.getCode());
r.setMessage(ResultCode.SUCCESS.getMessage());
return r;
}
public static Result error() {
Result r = new Result();
r.setCode(ResultCode.ERROR.getCode());
r.setMessage(ResultCode.ERROR.getMessage());
return r;
}
public Result put(String key, Object value) {
map.put(key, value);
return this;
}
public Object get(String key) {
return map.get(key);
}
}
#8.修改application.properties文件中,项目注册名字:
spring.application.name=openfeignDemo2
#9.启动项目,访问:
以上两个项目,自己单独访问都是好用的。
3、实现http请求管理 (不带参发送请求)
从此开始,准备工作完成,下面开始进行跨项目访问数据
【1.添加open Feign依赖】
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
【2.在 “用户项目” 里,添加一个接口】
用来链接另外的项目。
package com.jr.feign;
import com.jr.util.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("openfeignDemo2")
public interface ScoreFeign {
@GetMapping("/score/info")
public Result info(); //作为被访问的服务端的项目的controller中的对应内容7+
}
定义了Feign接口,接口中的方法和对应服务端Controller方法一样,两点不同
-
RequestMapping注解的值要求全路径,包括controller上和方法上的注解地址拼接到一起
-
添加FeignClient注解,参数是服务端微服务的名称(被访问项目的在nacos注册的名)
【3.改动UserServiceImpl实现类】
#原来:
@Service
public class UserServiceImpl implements IUserService {
@Override
public UserDto info() {
return new UserDto();
}
}
#现在:
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private ScoreFeign scoreFeign;
@Override
public UserDto info() {
UserDto userDto=new UserDto();
userDto.setId("10");
userDto.setName("zhangsan");
userDto.setPassword("123456");
Result result=scoreFeign.info();
if(result.getCode() == ResultCode.SUCCESS.getCode()){ //确定服务端项目运行是否成功
userDto.setScoreList((List<Score>) result.get("list"));
}
return userDto;
}
}
【4.启动类添加注解 @EnableFeignClients】
@SpringBootApplication
@EnableRedisHttpSession
@EnableFeignClients //开始OPenFeign
public class SpringBootMain {
public static void main(String[] args) {
SpringApplication.run(SpringBootMain.class,args);
}
}
【5启动两个项目】
成绩项目:不变,
用户项目:查看用户信息的同时,也可以获得到成绩项目的数据。
4、添加请求头
OpenFeign发送请求时,对方服务接收不到请求里的header信息,而header中的数据一般在其他微服务中也很重要,所以要添加进去。
1、验证一下
修改一下user项目控制器方法,添加了请求头的获得。
修改一下score项目控制器方法,添加了请求头的获得。
postman 发送请求,查看控制台结果:
结果:
2、实现一下 添加拦截器
将客户端传递的请求内容先到项目a,项目a通过拦截器将得到的请求内容重新处理传递给b项目。
在user项目里,添加com.jr.interceptor.RequestHeaderInterceptor过滤器:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Configuration
public class RequestHeaderInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return;
}
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String test = request.getHeader("test");
template.header("test", test);
}
}
重新启动user项目,postman重新访问,查看score项目的控制台信息:
5、参数传递
1、controller代码: 在user项目下的UserController里,添加如下代码。
@GetMapping("/{id}")
public Result id(@PathVariable String id) { //url拼接传值 @PathVariable
UserDto userDto = userService.id(id);
return Result.ok().put("data", userDto);
}
@PostMapping("/add")
public Result add(@RequestBody User user) { //对象传值
UserDto userDto = userService.add(user);
return Result.ok().put("data", userDto);
}
2、对应的接口,添加两个方法:
3、对应的接口实现类,重写两个方法:
4.controller代码: 在score项目下的UserController里,添加如下代码。
@GetMapping("/{id}")
public Result id(@PathVariable String id) {
return Result.ok().put("id", id);
}
@PostMapping("/add")
public Result add(@RequestBody UserDto user) {
return Result.ok().put("userDto", user);
}
5.feign接口, 在user项目下的ScoreFeign接口里,添加如下代码。
@GetMapping("/score/{id}")
Result id(@PathVariable String id);
@PostMapping("/score/add")
Result add(@RequestBody UserDto user);
6.为user项目里的UserServiceImpl 实现类,添加重写方法:
测试一下,查看结果: