在filter中使用包裝類包裝request、response分別修改請求引數和修改響應結果
阿新 • • 發佈:2019-01-31
工作需要,要將請求和響應做一些處理,使得瀏覽器展示結果可控。
首先是在filter中攔截一些請求,請求到達過濾器的時候,可以通過request獲取請求中的一些引數。這時候,你可以修改資料中的一部分,然後,讓過濾器放行。但是,執行中就發現問題了,整個請求直接400了。剛開始,不知道原因,以為是資料修改的不對,後來經過排查,終於找到了原因,這些資料讀取一次之後,就相當於已經從資料流中取出過了,當伺服器端再次讀取引數的時候,此時已經沒有任何東西了,所以請求就出問題了。
解決方案:給request新增一個包裝類ParameterRequestWrapper,繼承HttpServletRequestWrapper,先從request中取輸入流,讀取流中的資料,然後重寫getInputStream()和getReader()方法。
filterChain.doFilter(reqWrapper,responseWrapper);//此處的response要寫包裝類
public class ParameterRequestWrapper extends HttpServletRequestWrapper { private byte[] buffer; public ParameterRequestWrapper(HttpServletRequest request) throws IOException { super(request); InputStream is = request.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; int read = 0; while ((read = is.read(buff)) > 0) baos.write(buff, 0, read); this.buffer = baos.toByteArray(); } public BufferedReader getReader() throws IOException{ return new BufferedReader(new InputStreamReader(getInputStream())); } public ServletInputStream getInputStream() throws IOException { String buf = new String(buffer); System.out.println("request的包裝類中的內容:"+buf); ParamUtil paramUtil = new ParamUtil(); boolean offlineLicense = paramUtil.isOfflineLicense(buf); if (offlineLicense) { String offlineToken = paramUtil.getOfflineToken(buf); HttpClientUtil httpClientUtil = new HttpClientUtil(); String user = httpClientUtil.getUserByToken(offlineToken); String endTime = httpClientUtil.getDisconnectUtil(user); String resetParamsOffline = paramUtil.resetParamsOffline(buf, endTime); if (resetParamsOffline==null) {//不修改 return new BufferedServletInputStream(this.buffer); }else {//修改 byte[] bufs = new byte[1024]; bufs = resetParamsOffline.getBytes(); return new BufferedServletInputStream(bufs); } } return new BufferedServletInputStream(this.buffer); } }
上面是修改請求引數的,還有,有時候需要對返回的結果進行修改,這時候也需要使用包裝類。寫一個ParameterResponseWrapper,繼承HttpServletResponseWrapper,主要是重寫getOutputStream()和getWriter()方法。
public class ParameterResponseWrapper extends HttpServletResponseWrapper{ private MyWriter myWriter; private MyOutputStream myOutputStream; public ParameterResponseWrapper(HttpServletResponse response) throws IOException{ super(response); } public ServletOutputStream getOutputStream() throws IOException{ myOutputStream = new MyOutputStream(super.getOutputStream()); return myOutputStream; } public PrintWriter getWriter() throws IOException{ myWriter = new MyWriter(super.getWriter()); return myWriter; } public MyWriter getMyWriter() { return myWriter; } public MyOutputStream getMyOutputStream(){ return myOutputStream; } }
public class MyOutputStream extends ServletOutputStream{
private ServletOutputStream outputStream;
private byte[] bytes;
public MyOutputStream(ServletOutputStream outputStream){
this.outputStream = outputStream;
}
public void write(int b) throws IOException {
outputStream.write(b);
}
public void write(byte[] b, int off, int len) {
try {
gzipJson(b);
outputStream.write(bytes, off,bytes.length);
} catch (Exception e) {
// TODO: handle exception
System.out.println("輸出流的輸出錯誤是:"+e);
}
}
public void write(byte[] b) throws IOException {
super.write(b);
}
//解壓json
public String getResponseJson(byte[] b) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ByteArrayInputStream bis = new ByteArrayInputStream(b);
GZIPInputStream gis =new GZIPInputStream(bis);
int length = -1;
byte [] b1 =new byte[1024];
while((length = gis.read(b1)) != -1){
bos.write(b1, 0, length);
}
bos.close();
String responseJson = bos.toString();
return responseJson;
}
//處理json
public String filterUser(byte[] b) throws IOException {
String username = "abc";
String responseJson = getResponseJson(b);
JSONObject jsonObject = JSONObject.fromObject(responseJson);
JSONArray jsonArray = jsonObject.getJSONArray("users");
if (jsonArray.size()>0) {
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject userObject = jsonArray.getJSONObject(i);
if (userObject.get("username").equals(username)) {
jsonArray.discard(i);
}
}
}
return jsonObject.toString();
}
//壓縮處理後的json
public void gzipJson(byte[] b){
GZIPOutputStream gzipOutputStream ;
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
try {
String filterUser = filterUser(b);
gzipOutputStream = new GZIPOutputStream(byteout);
gzipOutputStream.write(filterUser.getBytes("utf-8"));
gzipOutputStream.close();
bytes = byteout.toByteArray();
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}
}
public byte[] getBytes(){
return bytes;
}
}
然後,就可以在filter中使用包裝後的request和response了。
filterChain.doFilter(reqWrapper,responseWrapper);//此處的request和response要寫包裝類
最後,需要注意的是,你修改了response響應的內容,那麼響應的,就要根據你響應的資料流的大小修改Content-Length。