Spring Cloud 之Feign(三)
八、Feign的通信
Feign是在ribbon的基础上进行的一次封装。需要通过接口层来定义下游的接口和上游的调用。
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.编写配置文件
server:
port: 8764
spring:
application:
name: product-feign-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
3.在启动类上打上注解@EnableFeignClients
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class MyProductFeignServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MyProductFeignServiceApplication.class, args);
}
}
4.创建接口(通讯接口) 定义了上下游之间通信的标准
- @FeignClient("USER-SERVICE"):找到服务提供者的名称
- 在接口中,把需要用到的服务提供者的controller中的接口全部复制到该接口中,并去掉方法体,成为抽象方法。
- 所有的@RequestParam需要带上name属性
package com.qf.my.product.feign.service.api;
import com.qf.common.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Objects;
@FeignClient("USER-SERVICE")
public interface ProductFeignAPI {
@RequestMapping("/user/show")
public String userShow();
@PostMapping("/addUser")
public String addUser(@RequestBody User user);
@GetMapping("/getUserByMap")
public User getUserByMap(@RequestParam(name = "id") Long id,@RequestParam(name = "name") String name);
@PostMapping("/addUserWithHeader")
public String addUserWithHeader(@RequestBody User user,
@CookieValue(name = "login_token") String login_token,
@CookieValue(name="cart_token") String cart_token);
}
5.在业务代码中,使用注入该接口,来进行下游的调用
controller:
package com.qf.my.product.feign.service.controller;
import com.qf.common.entity.User;
import com.qf.my.product.feign.service.api.ProductFeignAPI;
import com.qf.my.product.feign.service.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class ProductController {
@Autowired
private IProductService productService;
@RequestMapping("/user/show")
public String userShow(){
return productService.userShow();
}
@PostMapping("/addUser")
public String addUser(@RequestBody User user){
return productService.addUser(user);
}
@GetMapping("/getUserByMap")
public User getUserByMap(@RequestParam(name = "id") Long id,@RequestParam(name = "name") String name){
return productService.getUserByMap(id,name);
}
}
Service:
package com.qf.my.product.feign.service.service.impl;
import com.qf.common.entity.User;
import com.qf.my.product.feign.service.api.ProductFeignAPI;
import com.qf.my.product.feign.service.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductServiceImpl implements IProductService {
@Autowired
private ProductFeignAPI productFeignAPI;
@Override
public String addUser(User user) {
//执行自己的业务逻辑
//调用下游服务
return productFeignAPI.addUser(user);
}
@Override
public User getUserByMap(Long id, String name) {
return productFeignAPI.getUserByMap(id,name);
}
@Override
public String userShow(){
return productFeignAPI.userShow();
}
}
6.feign通过拦截器携带Cookie进行远程调用
1)通过创建拦截器
package com.qf.my.product.feign.service.interceptor;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.apache.http.HttpEntity;
import org.apache.http.protocol.RequestContent;
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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.HttpHeaders;
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
//1.获取当前的request对象
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
//2.从request对象中获取cookie
Cookie[] cookies = request.getCookies();
String cart_token = "";
String login_token = "";
if(cookies!=null&&cookies.length!=0)
for (Cookie cookie : cookies) {
if("cart_token".equals(cookie.getName())){
cart_token = cookie.getValue();
continue;
}
if("login_token".equals(cookie.getName())){
login_token = cookie.getValue();
continue;
}
}
//3.封装成请求头里的cookie的格式
String cookie = "cart_token="+cart_token+";"+"login_token="+login_token;
//4.设置cookie键值对放到请求头
requestTemplate.header(HttpHeaders.COOKIE,cookie);
}
}
2)在Feign注解中配置该拦截器
package com.qf.my.product.feign.service.api;
import com.qf.common.entity.User;
import com.qf.my.product.feign.service.interceptor.FeignInterceptor;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Objects;
//配置拦截器,让每次请求都先经过拦截器
@FeignClient(value="USER-SERVICE",configuration = FeignInterceptor.class)
public interface ProductFeignAPI {
@RequestMapping("/user/show")
public String userShow();
@PostMapping("/addUser")
public String addUser(@RequestBody User user);
@GetMapping("/getUserByMap")
public User getUserByMap(@RequestParam(name = "id") Long id,@RequestParam(name = "name") String name);
@PostMapping("/addUserWithHeader")
public String addUserWithHeader(@RequestBody User user);
}