springcloud 中用feignclient调用服务遇到的问题
一、首先搭建环境:注册中心,服务demob(客户端),服务democ(服务端)
二、简单实现:
1、客户端代码:
application.properties配置项追加:feign.hystrix.enabled=true
demob服务接口:
package com.cn.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.JSONObject;
@RestController
public class BusinessController {
@Autowired
private DemoFeignClient demoFeignClient;;
@RequestMapping("/hello/{username}")
@ResponseBody
public String hello(@PathVariable("username") String username) {
String token = "";
// 通过feign 调用democ服务远程接口
return demoFeignClient.democ(token);
}
}
feign调用实现:
package com.cn.demo.controller;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.cn.demo.config.FeignInterceptor;
@FeignClient(name = "democ",fallback=DemoServiceHystrix.class)
public interface DemoFeignClient {
@RequestMapping("/democ/service/v1/user/{username}")
public String hello(@RequestHeader("Authorization") String auth,@RequestParam("username") String username);
@RequestMapping("/democ/test")
public String democ(@RequestHeader("Authorization") String token);
}
熔断处理:
package com.cn.demo.controller;
import org.springframework.stereotype.Component;
@Component
public class DemoServiceHystrix implements DemoFeignClient {
@Override
public String hello(String auth, String username) {
return "调用demo接口超时";
}
@Override
public String democ(String token) {
return "调用demo接口超时";
}
}
2、服务端代码:
package com.cn.demo.controller;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MainController {
private static Logger logger = LoggerFactory.getLogger(MainController.class);
@GetMapping("/test")
@ResponseBody
public String test(HttpServletRequest request, Model model) {
// String header = request.getHeader("Authorization");
// try {
// Thread.sleep(10000);
// } catch (Exception e) {
// e.printStackTrace();
// }
return "democ服务接口返回数据";
}
}
遇到的问题:想在在客户端发起的请求中注入自己想要的header信息
解决:
(1).
(2).实现RequestInterceptor 接口,会在每个feign调用中存入header,注意注解@Component。
问题1.在该类中不能取到HttpServletRequest 。
解决办法:在application.properties文件中加入配置项hystrix.command.default.execution.isolation.strategy=SEMAPHORE
问题2.接口中 @RequestHeader 传参,优先于 RequestInterceptor 拦截器
问题3.想要请求中的参数透传,需要手工赋值。fegin不会请求转发
package com.cn.demo.config;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Component
public class FeignInterceptor implements RequestInterceptor {
/**
* Feign调用的时候添加请求头
*/
@Override
public void apply(RequestTemplate requestTemplate) {
// 针对整个请求链中的request
HttpServletRequest attributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
String msaRequestId = attributes.getHeader("X-Request-Id");
if (StringUtils.isBlank(msaRequestId)) {
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
requestTemplate.header("X-Request-Id", uuid);
} else {
requestTemplate.header("X-Request-Id", msaRequestId);
}
// 针对客户端发起的请求
Request request = requestTemplate.request();
Map<String, Collection<String>> headers = request.headers();
if (!headers.containsKey("Authorization")) {
// 通过网关访问 生成全局JWT
String createJWT = "*************";
requestTemplate.header("Authorization", createJWT);
}
}
}
学一点,记一旦,漫漫学习路