原因:我要收集所有来自前台请求的参数信息,无论在任何地方的。当前请求参数都是json格式,都写在httpservlet的body中。这个只能通过流进行获取。然后问题来了,HttpServletRequest的inputstream只能读取一次。。。。
解决:重写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
1 import javax.servlet.ServletInputStream; 2 import javax.servlet.http.HttpServletRequest; 3 import javax.servlet.http.HttpServletRequestWrapper; 4 5 import com.iafclub.baseTools.util.HttpUtil; 6 7 import java.io.BufferedReader; 8 import java.io.ByteArrayInputStream; 9 import java.io.IOException; 10 import java.io.InputStreamReader; 11 import java.nio.charset.Charset; 12 13 /**重写HttpServletRequestWrapper 14 * 15 * @author 陈惟鲜 16 * @date 2016年12月7日 下午3:06:52 17 * 18 */ 19 public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { 20 21 private final byte[] body; 22 23 public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { 24 super(request); 25 body = HttpUtil.getBodyString(request).getBytes(Charset.forName("UTF-8")); 26 } 27 28 @Override 29 public BufferedReader getReader() throws IOException { 30 return new BufferedReader(new InputStreamReader(getInputStream())); 31 } 32 33 @Override 34 public ServletInputStream getInputStream() throws IOException { 35 36 final ByteArrayInputStream bais = new ByteArrayInputStream(body); 37 38 return new ServletInputStream() { 39 40 @Override 41 public int read() throws IOException { 42 return bais.read(); 43 } 44 }; 45 } 46 }
3、过滤器中加上重写方法:AccessFilter
1 import java.io.IOException; 2 import java.util.regex.Pattern; 3 4 import javax.servlet.Filter; 5 import javax.servlet.FilterChain; 6 import javax.servlet.FilterConfig; 7 import javax.servlet.ServletContext; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest; 10 import javax.servlet.ServletResponse; 11 import javax.servlet.annotation.WebFilter; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 15 import org.apache.log4j.Logger; 16 17 import com.iafclub.baseTools.util.HttpUtil; 18 import com.iafclub.demo.aop.BodyReaderHttpServletRequestWrapper; 19 /**访问过滤器 20 * 21 * @author chenweixian 22 * 23 */ 24 @WebFilter(filterName="accessFilter", urlPatterns={ 25 "*.do", 26 // "*.jsp", 27 // "/*", 28 // "/layout/*", 29 // "/apply/*", 30 // "/audit/*", 31 // "/authority/*", 32 // "/commonWare/*", 33 // "/contract/*", 34 // "/marketing/*", 35 // "/product/*", 36 // "/project/*", 37 // "/system/*", 38 // "/user/*" 39 }) 40 public class AccessFilter implements Filter { 41 // 日志对象 42 private static Logger logger = Logger.getLogger(AccessFilter.class); 43 44 public void init(FilterConfig filterConfig) throws ServletException { 45 // ServletContext context = filterConfig.getServletContext(); 46 } 47 48 public void destroy() { 49 } 50 51 public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException { 52 HttpServletRequest request = (HttpServletRequest) req; 53 System.out.println("=====+" + req.hashCode()); 54 HttpServletResponse response = (HttpServletResponse) res; 55 if ("POST".equalsIgnoreCase(request.getMethod())) { 56 57 ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request); 58 System.out.println("===filter==+" + requestWrapper.hashCode()); 59 60 String body = HttpUtil.getBodyString(requestWrapper); 61 System.out.println("AccessFilter="+body); 62 chain.doFilter(requestWrapper, response); 63 return ; 64 } 65 66 chain.doFilter(req, res); 67 } 68 }
4、拦截器:ControllerAopInterceptor(其实我们这里根本用到这个东西,加载这里的目的是想说,过滤器访问在aop切面之前,过滤器修改request,其他访问的request都被修改)
1 import javax.servlet.http.HttpServletRequest; 2 3 import org.apache.log4j.Logger; 4 import org.aspectj.lang.ProceedingJoinPoint; 5 import org.aspectj.lang.annotation.After; 6 import org.aspectj.lang.annotation.AfterReturning; 7 import org.aspectj.lang.annotation.AfterThrowing; 8 import org.aspectj.lang.annotation.Around; 9 import org.aspectj.lang.annotation.Aspect; 10 import org.aspectj.lang.annotation.Before; 11 import org.aspectj.lang.annotation.Pointcut; 12 import org.springframework.stereotype.Service; 13 import org.springframework.web.context.request.RequestAttributes; 14 import org.springframework.web.context.request.RequestContextHolder; 15 import org.springframework.web.context.request.ServletRequestAttributes; 16 17 import com.iafclub.baseTools.util.HttpUtil; 18 import com.iafclub.baseTools.util.MyCollectionUtil; 19 20 /**切面 21 * 22 * @author chenweixian 23 * 24 */ 25 @Aspect 26 @Service 27 public class ControllerAopInterceptor { 28 29 private Logger logger = Logger.getLogger(ControllerAopInterceptor.class); 30 31 @Pointcut("execution(* com.iafclub.demo.web.controller..*(..))") 32 private void anyMethod(){}//定义一个切入点 33 34 @Before("anyMethod() && args(request)") 35 public void doAccessCheck(Object request){ 36 logger.info(request); 37 logger.info("前置通知"); 38 } 39 40 @AfterReturning("anyMethod() && args(request)") 41 public void doAfter(Object request){ 42 logger.info(request); 43 logger.info("后置通知"); 44 } 45 46 @Around("anyMethod()") 47 public Object doAround(ProceedingJoinPoint pjp) throws Throwable { 48 RequestAttributes ra = RequestContextHolder.getRequestAttributes(); 49 ServletRequestAttributes sra = (ServletRequestAttributes) ra; 50 HttpServletRequest request = sra.getRequest(); 51 52 String url = request.getRequestURL().toString(); 53 String method = request.getMethod(); 54 String uri = request.getRequestURI(); 55 String queryString = request.getQueryString(); 56 Object[] requestObject = pjp.getArgs(); 57 58 String body = HttpUtil.getBodyString(request); 59 System.out.println("====aop=+" + request.hashCode()); 60 61 System.out.println("ControllerAopInterceptor="+body); 62 logger.info("请求开始, 各个参数, url: {"+url+"}, method: {"+method+"}, uri: {"+uri+"}, params: {"+queryString+"},requestObject{"+requestObject+"}"); 63 // result的值就是被拦截方法的返回值 64 Object result = pjp.proceed(); 65 logger.info("请求结束,controller的返回值是 " + MyCollectionUtil.objectToMapAll(result)); 66 return result; 67 } 68 69 @After("anyMethod()") 70 public void after(){ 71 logger.info("最终通知"); 72 } 73 74 @AfterThrowing("anyMethod()") 75 public void doAfterThrow(){ 76 logger.info("例外通知"); 77 } 78 79 }
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"; } }
哈哈。。。。。。。。。。。
结果: