JAVA数据流再传递
有一个filter类,在请求进入的时候读取了URL信息,并且读取了requestBod中的参数信息,那么在请求到达实际的控制层时,入参信息是拿不到的,对这种情况就需要数据流做再传递处理。
处理原理:使用HttpServletRequestWrapper装饰类,重新定义获取流数据的方式。
自定义filter的实现:
package com.quyiyuan.openplatform.filter; import java.io.IOException; import java.util.UUID; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.springframework.web.context.WebApplicationContext; import com.quyiyuan.openplatform.service.MonitorService; /** * <pre> * 任务: * 描述:(存储用户请求信息,过滤器类) * 作者: * 时间:2015年11月5日下午12:03:33 * 类名: SaveRequestInfoFilter * </pre> */ public class SaveRequestInfoFilter implements Filter{ private ServletContext servletContext; @Override public void destroy() { } @Override public void doFilter(ServletRequest sreq, ServletResponse srsp, FilterChain fc) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) sreq; String method = request.getMethod(); StringBuffer URL = request.getRequestURL(); if(URL.toString().contains("ROPcloudtest.html") || URL.toString().contains("ROPtest.html") || URL.toString().contains("ROP/css") || URL.toString().contains("ROP/js") || URL.toString().contains("YYSK.html")){ fc.doFilter(sreq, srsp); }else{ String URI = ""; String urlParame = ""; String jsonParame = ""; String token = request.getParameter("token"); String userSource = request.getParameter("userSource"); String publicServiceType = request.getParameter("publicServiceType"); //request 作用域中添加UUID,标记当前请求 String uuid = UUID.randomUUID().toString().replaceAll("-", ""); request.setAttribute("UUID", uuid); if (method.equals("POST")) { URI = request.getRequestURI(); urlParame = request.getQueryString(); // 获取自定义装饰类对象 BodyReaderHttpServletRequestWrapper bodyWrapper = new BodyReaderHttpServletRequestWrapper(request); jsonParame = HttpHelper.getBodyString(bodyWrapper); saveReqInfo(URI, urlParame, jsonParame, token, userSource, publicServiceType, uuid); // 使用自定义装饰类对象执行下一个过滤器 fc.doFilter(bodyWrapper, srsp); } else { URI = request.getRequestURI(); urlParame = request.getQueryString(); saveReqInfo(URI, urlParame, jsonParame, token, userSource, publicServiceType, uuid); fc.doFilter(request, srsp); } } } @Override public void init(FilterConfig config) throws ServletException { servletContext =config.getServletContext(); } /** * <pre> * 任务: * 描述: 调用业务类保存请求信息 * 作者: * 时间:2015年11月5日下午12:04:09 * @param URI * @param urlParame * @param jsonParame * returnType:void * </pre> * @param publicServiceType * @param userSource * @param token * @param uuid */ private void saveReqInfo(final String URI, final String urlParame, final String jsonParame, final String token, final String userSource, final String publicServiceType, final String uuid) { Thread saveReqInfo = new Thread() { public void run() { //获取容器对象 WebApplicationContext context = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); //获取MonitorService对象 MonitorService monitorService = (MonitorService) context.getBean("monitorService"); monitorService.saveRequestInfo(URI, urlParame, jsonParame, token, userSource, publicServiceType, uuid); } }; saveReqInfo.start(); } }
自定义装饰类的实现BodyReaderHttpServletRequestWrapper:
package com.quyiyuan.openplatform.filter; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import net.sf.json.JSONObject; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; /** * * <pre> * 任务: * 描述:(实现IO流再传递) * 作者: * 时间:2015年11月5日下午5:34:04 * 类名: BodyReaderHttpServletRequestWrapper * </pre> */ public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8")); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } }; } }
读取ServletRequest的body信息工具类:
package com.quyiyuan.openplatform.filter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import javax.servlet.ServletRequest; /** * * <pre> * 任务: * 描述:(读取ServletRequest的body信息) * 作者: * 时间:2015年11月5日下午5:34:58 * 类名: HttpHelper * </pre> */ public class HttpHelper { public static String getBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }