SpringCloud微服务间参数的传递( threadLocal+Feign的RequestInterceptor方式)
我们在开发过程中,常有这样的需求,要将当前的微服务参数传递到下一个微服务,比如userId或者token之类,如果我们使用SpringCloud,把参数放到Header里就可以轻松实现了参数的传递。下面是一个利用Feign的RequestInterceptor实现的例子这里使用ThreadLocal来保持参数,这样在当前的环境中就可以随时使用了package app.gatew...
我们在开发过程中,常有这样的需求,要将当前的微服务参数传递到下一个微服务,比如userId或者token之类,如果我们使用SpringCloud,把参数放到Header里就可以轻松实现了参数的传递。
下面是一个利用Feign的RequestInterceptor实现的例子
这里使用ThreadLocal来保持参数,这样在当前的环境中就可以随时使用了
package app.gateway.threadLocal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.alibaba.fastjson.JSON;
public class PassParameters {
private static final Logger log = LoggerFactory.getLogger(PassParameters.class);
private static final ThreadLocal localParameters = new ThreadLocal();
public static <T> T get(){
T t = (T) localParameters.get();
log.info("ThreadID:{}, threadLocal {}", Thread.currentThread().getId(), JSON.toJSONString(t));
return t;
}public static <T> void set(T t){
log.info("ThreadID:{}, threadLocal set {}", Thread.currentThread().getId(), JSON.toJSONString(t));
localParameters.set(t);
}
}
设计一个切面,这里是gateway的切面,存放相关的参数,我这里放到map中,页可以自定义一个对象,放对象中
package app.gateway.aop;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import app.gateway.threadLocal.PassParameters;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
/**
* @author hsn
*/
@Aspect
@Component
public class ApiRequestAspect {
private static Logger logger = LoggerFactory.getLogger(ApiRequestAspect.class);
@Pointcut("execution (* app.gateway.controller.ApiController.*(..)) ")
private void anyMethod() {
}
/**
* 方法调用之前调用
*/
@Before("anyMethod()")
public void doBefore(){
logger.info("开始处理请求信息!");
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
Map<String,String> map = new HashMap<>();
String username = request.getParameter("username");
String token = request.getParameter("token");
map.put("username", username);
map.put("token", token);
//将map放到threadLocal中
PassParameters.set(map);
}
/**
* 方法之后调用
*/
@AfterReturning(pointcut = "anyMethod()")
public void doAfterReturning(){
}
}
自定义 RequestInterceptor
package app.gateway.config;
import feign.Feign;
import feign.RequestInterceptor;
import feign.RequestTemplate;import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;import app.gateway.threadLocal.PassParameters;
@Configuration
@ConditionalOnClass(Feign.class)
public class DefaultFeignConfig implements RequestInterceptor {
@Value("${spring.application.name}")
private String appName;
@Override
public void apply(RequestTemplate requestTemplate)
{
Map<String,String> map = PassParameters.get();
String username = map.get("username");
if(StringUtils.isNotEmpty(username)){
requestTemplate.header("username", username);
}
String token = map.get("token");
if(StringUtils.isNotEmpty(token)){
requestTemplate.header("token", token);
}
}
}
在后端的service,用切面取出保存在head中的参数
package app.service.aop;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import app.service.threadLocal.PassParameters;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
/**
* @author hsn
*/
@Aspect
@Component
public class ApiRequestAspect {
private static Logger logger = LoggerFactory.getLogger(ApiRequestAspect.class);
@Pointcut("execution (* app.service.controller.AppServiceController.*(..)) ")
private void anyMethod() {
}
/**
* 方法调用之前调用
*/
@Before(value= "anyMethod()")
public void doBefore(JoinPoint jp){
logger.info("开始处理请求信息!");
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
Map<String,String> map = new HashMap<>();
String username = request.getHeader("username");
String token = request.getHeader("token");
map.put("username", username);
map.put("token", token);
//将map放到threadLocal中
PassParameters.set(map);
}
/**
* 方法之后调用
*/
@AfterReturning(pointcut = "anyMethod()")
public void doAfterReturning(){
}
}
详细代码请参考:https://github.com/hsn999/springCloud/tree/master/springCloud-feign-pass-parameters
更多推荐
所有评论(0)