一. 为什么要用到这个
在基于 springcloud 构建的微服务系统中,通常使用网关zuul来进行一些用户验证等过滤的操作,比如 用户在 header 或者 url 参数中存放了 token ,网关层需要 用该 token 查出用户 的 userId ,并存放于 request 中,以便后续微服务可以直接使用而避免再去用 token 查询。
二.基础知识
在 zuul 中最大的用法的除了路由之外,就是过滤器了,自定义过滤器需实现接口 ZuulFilter ,在 run() 方法中,可以用
RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest();
获取到 request,但是在 request 中只有 getParameter() 而没有 setParameter() 方法,所以直接修改 url 参数不可行,另外在 reqeust 中可以虽然可以使用 setAttribute() ,但是可能由于作用域的不同,在这里设置的 attribute 在后续的微服务中是获取不到的,因此必须考虑另外的方式。
三.具体做法
最后确定的可行的方法是,用
ctx.setRequest(new HttpServletRequestWrapper(request) {})
的方式,重新构造上下文中的 request ,代码如下:
-
import javax.servlet.http.HttpServletRequestWrapper;
-
-
// 在json参数中添加 userId
-
try {
-
InputStream in = ctx.getRequest().getInputStream();
-
String body = StreamUtils.copyToString(in, Charset.forName(
"UTF-8"));
-
System.out.println(
"body:" + body);
-
JSONObject json = JSONObject.fromObject(body);
-
json.put(
"userId", userId);
-
String newBody = json.toString();
-
System.out.println(
"newBody:" + newBody);
-
final
byte[] reqBodyBytes = newBody.getBytes();
-
ctx.setRequest(
new HttpServletRequestWrapper(request){
-
@Override
-
public ServletInputStream getInputStream() throws IOException {
-
return
new ServletInputStreamWrapper(reqBodyBytes);
-
}
-
@Override
-
public int getContentLength() {
-
return reqBodyBytes.length;
-
}
-
@Override
-
public long getContentLengthLong() {
-
return reqBodyBytes.length;
-
}
-
});
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
思路就是,获取请求的输入流,并重写,即重写json参数。
在后续的微服务的 controller 中,可以用 形似
-
@RequestBody Map
<String,Object> body
-
=======
-
body.get("userId");
这样的方式,去获取在 zuulFilter 传入的 userId
四.一些尝试
在重写 HttpServletRequestWrapper 的时候,我尝试过 重写 getParameterNames() 和 getParameterMap() 方法,希望重写 url 参数,但是并没有生效。具体原因不太清楚,如果有大神知道怎么办,欢迎指教。
=================================
以上尝试 已经找到可行方法:
-
request.getParameterMap();
// 关键步骤,一定要get一下,下面这行代码才能取到值
-
Map<String, List<String>> requestQueryParams = ctx.getRequestQueryParams();
-
-
if (requestQueryParams ==
null) {
-
requestQueryParams =
new HashMap<>();
-
}
-
-
// 添加userId
-
ArrayList<String> arrayList2 =
new ArrayList<>();
-
arrayList.add(userId +
"");
-
requestQueryParams.put(
"userId", arrayList2);
-
-
ctx.setRequestQueryParams(requestQueryParams);