多次读取HttpServletRequest的inputstream方法 问题解决
2016-12-07 15:17
801 查看
原因:我要收集所有来自前台请求的参数信息,无论在任何地方的。当前请求参数都是json格式,都写在httpservlet的body中。这个只能通过流进行获取。然后问题来了,HttpServletRequest的inputstream只能读取一次。。。。
![](https://images2015.cnblogs.com/blog/333678/201612/333678-20161207145956366-1353763036.png)
解决:重写request的inputstream方法。。然后在需要部署应用中加上过滤器,在过滤器中加上这个重写的request的方法,问题解决。
1、读取流信息的工具类:HttpUtil.java
2、重写httpservlet的inputstream类:BodyReaderHttpServletRequestWrapper
3、过滤器中加上重写方法:AccessFilter
4、拦截器:ControllerAopInterceptor(其实我们这里根本用到这个东西,加载这里的目的是想说,过滤器访问在aop切面之前,过滤器修改request,其他访问的request都被修改)
5、真正处理的类也不会受到影响:
哈哈。。。。。。。。。。。
结果:
![](https://images2015.cnblogs.com/blog/333678/201612/333678-20161207145956366-1353763036.png)
解决:重写request的inputstream方法。。然后在需要部署应用中加上过滤器,在过滤器中加上这个重写的request的方法,问题解决。
1、读取流信息的工具类:HttpUtil.java
/**获取请求Body * * @param request * @return * @author : chewneixian 陈惟鲜 * @create_date 2016年12月6日 下午12:54:07 */ 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(); }
2、重写httpservlet的inputstream类:BodyReaderHttpServletRequestWrapper
import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import com.iafclub.baseTools.util.HttpUtil; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; /**重写HttpServletRequestWrapper * * @author 陈惟鲜 * @date 2016年12月7日 下午3:06:52 * */ public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); body = HttpUtil.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(); } }; } }
3、过滤器中加上重写方法:AccessFilter
import java.io.IOException; import java.util.regex.Pattern; 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.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import com.iafclub.baseTools.util.HttpUtil; import com.iafclub.demo.aop.BodyReaderHttpServletRequestWrapper; /**访问过滤器 * * @author chenweixian * */ @WebFilter(filterName="accessFilter", urlPatterns={ "*.do", // "*.jsp", // "/*", // "/layout/*", // "/apply/*", // "/audit/*", // "/authority/*", // "/commonWare/*", // "/contract/*", // "/marketing/*", // "/product/*", // "/project/*", // "/system/*", // "/user/*" }) public class AccessFilter implements Filter { // 日志对象 private static Logger logger = Logger.getLogger(AccessFilter.class); public void init(FilterConfig filterConfig) throws ServletException { // ServletContext context = filterConfig.getServletContext(); } public void destroy() { } public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; System.out.println("=====+" + req.hashCode()); HttpServletResponse response = (HttpServletResponse) res; if ("POST".equalsIgnoreCase(request.getMethod())) { ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request); System.out.println("===filter==+" + requestWrapper.hashCode()); String body = HttpUtil.getBodyString(requestWrapper); System.out.println("AccessFilter="+body); chain.doFilter(requestWrapper, response); return ; } chain.doFilter(req, res); } }
4、拦截器:ControllerAopInterceptor(其实我们这里根本用到这个东西,加载这里的目的是想说,过滤器访问在aop切面之前,过滤器修改request,其他访问的request都被修改)
import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import com.iafclub.baseTools.util.HttpUtil; import com.iafclub.baseTools.util.MyCollectionUtil; /**切面 * * @author chenweixian * */ @Aspect @Service public class ControllerAopInterceptor { private Logger logger = Logger.getLogger(ControllerAopInterceptor.class); @Pointcut("execution(* com.iafclub.demo.web.controller..*(..))") private void anyMethod(){}//定义一个切入点 @Before("anyMethod() && args(request)") public void doAccessCheck(Object request){ logger.info(request); logger.info("前置通知"); } @AfterReturning("anyMethod() && args(request)") public void doAfter(Object request){ logger.info(request); logger.info("后置通知"); } @Around("anyMethod()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; HttpServletRequest request = sra.getRequest(); String url = request.getRequestURL().toString(); String method = request.getMethod(); String uri = request.getRequestURI(); String queryString = request.getQueryString(); Object[] requestObject = pjp.getArgs(); String body = HttpUtil.getBodyString(request); System.out.println("====aop=+" + request.hashCode()); System.out.println("ControllerAopInterceptor="+body); logger.info("请求开始, 各个参数, url: {"+url+"}, method: {"+method+"}, uri: {"+uri+"}, params: {"+queryString+"},requestObject{"+requestObject+"}"); // result的值就是被拦截方法的返回值 Object result = pjp.proceed(); logger.info("请求结束,controller的返回值是 " + MyCollectionUtil.objectToMapAll(result)); return result; } @After("anyMethod()") public void after(){ logger.info("最终通知"); } @AfterThrowing("anyMethod()") public void doAfterThrow(){ logger.info("例外通知"); } }
5、真正处理的类也不会受到影响:
/**测试首页 * * @author chenweixian * */ @Controller public class IndexController { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private DictionaryService dictionaryService; /** * 首页 * @throws IOException * */ @RequestMapping("index.do") public String index(Model model, HttpServletRequest request) throws IOException{ String body = HttpUtil.getBodyString(request); System.out.println("==index===+" + request.hashCode()); System.out.println("IndexController="+body); return "index"; } }
哈哈。。。。。。。。。。。
结果:
![](https://images2015.cnblogs.com/blog/333678/201612/333678-20161207151608585-1378344157.png)
相关文章推荐
- spring boot 学习笔记(5) 解决HttpServletRequest inputStream只能读取一次的问题
- HttpServletRequest.getInputStream可读取多次解决方案之一,使用HttpServletRequestWrapper
- 采用Filter的方法解决HttpServletRequest.getParameter乱码的问题
- WEB上调用HttpWebRequest奇怪问题的解决方法
- 关于Servlet报错:405 HTTP method GET is not supported by this URL问题解决方法
- 升级到iOS5后ASIHttpRequest库问题及解决方法
- Servlet的Request.getInputStream()只能读取一次问题
- XMLHttpRequest乱码问题在Firefox与IE下的不同解决方法
- 升级到iOS5后ASIHttpRequest库问题及解决方法
- ASIHTTPRequest开源类项目导入问题及解决方法
- The type javax.http.HttpServletRequest cannot be resolved.It is indirectly……问题之解决
- The method getDispatcherType() is undefined for the type HttpServletRequest的解决方法
- Servlet的Request.getInputStream()只能读取一次问题
- WEB上调用HttpWebRequest奇怪问题的解决方法
- Nginx出现The plain HTTP request was sent to HTTPS port问题解决方法
- 升级到iOS5后ASIHttpRequest库问题及解决方法
- XMLHttpRequest 乱码问题 在firefox IE的不同解决方法
- 升级到iOS5后ASIHttpRequest库问题及解决方法
- (转)升级到iOS5后ASIHttpRequest库问题及解决方法
- Servlet的Request.getInputStream()只能读取一次问题