springcloud 中 zuul 如何修改請求引數
阿新 • • 發佈:2018-12-19
一. 為什麼要用到這個
在基於 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);