目录
1、什么是OpenFeign
1、Feign是什么??http请求
2、OpenFeign是什么
3、Feign和openFeign有什么区别
2、应用
1、 需要开启nacos 和redis
2、准备工作
【1.对springsession做改动】
【2.对springsession-1做改动】
3、实现http请求管理
4、添加请求头
1、验证一下
2、实现一下 添加拦截器
5、参数传递
1、什么是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
2、应用
1、 需要开启nacos 和redis

2、准备工作
【0.使用SpringSession共享例子】

下面图片是微服务SpringSession解析部署使用全流程-CSDN博客中创建出来的
在此基础上做改动。具体可了解此地址博客

改动后

【1.对springsession做改动】
#1.添加实体类 Score
package com.jr.entry;
import lombok.Data;
@Data
public class Score {
    private String name;
    private Double score;
} 
#2.添加实体类 UserDto
package com.jr.entry;
import lombok.Data;
import java.util.List;
@Data
public class UserDto {
    private String id;
    private String name;
    private String password;
    private List<Score> scoreList;
}
 
#3.添加接口 IUserService
package com.jr.servie;
import com.jr.entry.UserDto;
public interface IUserService {
    public UserDto info();
} 
#4.添加接口实现类 UserServiceImpl
package com.jr.servie.impl;
import com.jr.entry.UserDto;
import com.jr.servie.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
    @Override
    public UserDto info() {
        return new UserDto();
    }
}
 
#5.添加 UserController 类
报红等后面的工具类配置完在引包
package com.jr.controller;
import com.jr.entry.UserDto;
import com.jr.servie.IUserService;
import com.jr.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@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;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@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 
【2.对springsession-1做改动】
实体类是相同的,可以将上一个粘贴过来
#1.添加实体类 Score
package com.jr.entry;
import lombok.Data;
@Data
public class Score {
    private String name;
    private Double score;
} 
#2.添加实体类 UserDto
package com.jr.entry;
import lombok.Data;
import java.util.List;
@Data
public class UserDto {
    private String id;
    private String name;
    private String password;
    private List<Score> scoreList;
} 
#3.添加接口ScoreService
package com.jr.service;
import com.jr.entry.Score;
import java.util.List;
public interface ScoreService {
    public List<Score> info();
} 
#4.添加接口实现类 ScoreServiceImpl
package com.jr.service.impl;
import com.jr.entry.Score;
import com.jr.service.ScoreService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class ScoreServiceImpl implements ScoreService {
    @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.添加 ScoreController 类
报红等后面工具类配置完在引入包
package com.jr.controller;
import com.jr.entry.Score;
import com.jr.service.ScoreService;
import com.jr.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/score")
public class ScoreController {
    @Autowired
    private ScoreService 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;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@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.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
/**
 * openfeignDemo2是springsession-1在nacos注册的项目名()
 */
@FeignClient("openfeignDemo2")
@Component
public interface ScoreFeign {
    /**
     * @GetMapping("/score/info")里面是springsession-1的路由下面是方法
     * @return
     */
    @GetMapping("/score/info")
    public Result info();
}
 
定义了Feign接口,接口中的方法和对应服务端Controller方法一样,两点不同
-  
RequestMapping注解的值要求全路径,包括controller上和方法上的注解地址拼接到一起
 -  
添加FeignClient注解,参数是服务端微服务的名称
 
【3.改动UserServiceImpl实现类】
原来的代码
 
 package com.jr.servie.impl;
import com.jr.entry.UserDto;
import com.jr.servie.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
    @Override
    public UserDto info() {
        return new UserDto();
    }
} 
 
现在的代码
package com.jr.servie.impl;
import com.jr.entry.Score;
import com.jr.entry.UserDto;
import com.jr.feign.ScoreFeign;
import com.jr.servie.IUserService;
import com.jr.util.Result;
import com.jr.util.ResultCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@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】

启动项目



4、添加请求头
OpenFeign发送请求时,对方服务接收不到请求里的header信息,而header中的数据一般在其他微服务中也很重要,所以要添加进去。
1、验证一下
修改一下user项目控制器方法,添加了请求头的获得。
引入的包是这个 import org.apache.catalina.servlet4preview.http.HttpServletRequest;
 @GetMapping
    public Result info(HttpServletRequest request){
        String test = request.getHeader("test");
        System.out.println("user项目header"+test);
        UserDto userDto=userService.info();
        return Result.ok().put("data",userDto);
    } 

修改一下score项目控制器方法,添加了请求头的获得。
引入的包是这个
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
 @GetMapping("/info")
    public Result info(HttpServletRequest request){
        String test = request.getHeader("test");
        System.out.println("Score项目的head"+test);
        List<Score> list=scoreService.info();
        return Result.ok().put("list",list);
    } 

postman 发送请求,查看控制台结果:






2、实现一下 添加拦截器
在user项目里,添加com.jr.interceptor.RequestHeaderInterceptor过滤器:
package com.jr.interceptor;
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);
    }
}
 
5、参数传递
1、controller代码: 在user项目下的UserController里,添加如下代码。
   @GetMapping("/{id}")
    public Result id(@PathVariable String id) {  //url传值
        UserDto userDto = userService.id(id);
        return Result.ok().put("data", userDto);
    }
 
@PostMapping("/add")
    public Result add(@RequestBody UserDto user) { //对象传值
        UserDto userDto = userService.add(user);
        return Result.ok().put("data", userDto);
    } 

2、对应的接口,添加两个方法:

3、对应的接口实现类,重写两个方法:
 @Override
    public UserDto add(UserDto user) {
        UserDto userDto=new UserDto();
        Result result=scoreFeign.add(user);
        if(result.getCode() == ResultCode.SUCCESS.getCode()){
            UserDto resultUser= JSON.parseObject(JSON.toJSONString(result.get("data")),UserDto.class);
            System.out.println(resultUser);
            BeanUtils.copyProperties(resultUser,userDto);
        }
        return userDto;
    }
    @Override
    public UserDto id(String id) {
        UserDto userDto=new UserDto();
        Result result=scoreFeign.id(id);
        if(result.getCode() == ResultCode.SUCCESS.getCode()){
            userDto.setId((String)result.get("id"));
        }
        return userDto;
    } 

4.controller代码: 在score项目下的ScoreController里,添加如下代码。
 @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("data", user);
    } 

5.feign接口, 在user项目下的ScoreFeign接口里,添加如下代码。
 @GetMapping("/score/{id}")
    Result id(@PathVariable String id);
    @PostMapping("/score/add")
    Result add(@RequestBody UserDto user); 

6.测试一下,查看结果:





















