原因:我要收集所有来自前台请求的参数信息,无论在任何地方的。当前请求参数都是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

 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";
}
}

哈哈。。。。。。。。。。。

结果:

多次读取HttpServletRequest的inputstream方法 问题解决的更多相关文章

  1. jar包读取jar包内部和外部的配置文件,springboot读取外部配置文件的方法

    jar包读取jar包内部和外部的配置文件,springboot读取外部配置文件的方法 用系统属性System.getProperty("user.dir")获得执行命令的目录(网上 ...

  2. java读取Properties文件的方法

    resource.properties的内容: com.tsinkai.ettp.name=imooc com.tsinkai.ettp.website=www.imooc.com com.tsink ...

  3. Day16_93_IO_FileInputStream_读取文件字节流read()方法(一)

    读取文件字节流read()方法 * 文件字节输入流:按照字节方式读取文件 * java.io.* java.io.InputStream; java.io.FileInputStream; read( ...

  4. Javascript写入txt和读取txt文件的方法

    文章主要介绍了Javascript写入txt和读取txt文件的方法,需要的朋友可以参考下1. 写入 FileSystemObject可以将文件翻译成文件流. 第一步: 例: 复制代码 代码如下: Va ...

  5. C#读取ini文件的方法

    最近项目用到ini文件,读取ini文件,方法如下: using System; using System.Collections.Generic; using System.Linq; using S ...

  6. C#中常用的几种读取XML文件的方法

    1.C#中常用的几种读取XML文件的方法:http://blog.csdn.net/tiemufeng1122/article/details/6723764/

  7. Spark Scala 读取GBK文件的方法

    1. 在生产环境下,很多文件是GBK编码格式的,而SPARK 常用的textFile方法默认是写死了读UTF-8格式的文件,其他格式文件会显示乱码 用如下代码实现读取GBK文件的方法 import o ...

  8. 几种C#程序读取MAC地址的方法

    原文:几种C#程序读取MAC地址的方法 以下是收集的几种C#程序读取MAC地址的方法,示例中是读取所有网卡的MAC地址,如果仅需要读取其中一个,稍作修改即可. 1 通过IPConfig命令读取MAC地 ...

  9. [转载]C#读取Excel几种方法的体会

    C#读取Excel几种方法的体会 转载地址:http://developer.51cto.com/art/201302/380622.htm (1) OleDb: 用这种方法读取Excel速度还是非常 ...

随机推荐

  1. [转帖]超能课堂(199) 接口渐趋统一,USB4又如何能引领变革?

    https://www.expreview.com/70414.html 接口协议真复杂.. 9月3日,USB IF正式公布了USB4(你没看错,就是USB4,没有空格)的技术规格.USB-IF表示, ...

  2. java源码 -- LinkedHashMap

    一.概述 LinkedHashMap 继承自 HashMap,在 HashMap 基础上,通过维护一条双向链表,解决了 HashMap 不能随时保持遍历顺序和插入顺序一致的问题. 除此之外,Linke ...

  3. “无法改变的设计”——浅谈Java中的final关键字

    在Java中,final关键字可以用来修饰类.变量(包括成员变量和局部变量).方法,下面从这三个方面分别说明. final方法 当一个方法被final修饰时,表明这个方法不能被子类重写. 下面程序试图 ...

  4. (十二)Sun公司的Jstl标签库详细介绍

    JSP 本身提供的标签很少,不能满足我们日常开发需要,好在 Sun 公司自己提供了一套标签库: JSTL标签库快速入门(可点击) 目录 < c : out > 标签 < c : se ...

  5. vim入门一 常用指令

    以下为自己常用的vim指令总结 一.插入命令 a 在光标所在字符后进入插入模式 A 调到光标所在行行尾进入插入模式 i 在光标所在字符前插入模式 I 调到光标所在行行首进入插入模式 o 调到光标所在上 ...

  6. 模块 json 和 pickle

    目录 序列化 json 和 pickle 模块 序列化 序列:字符串 序列化:将其它数据类型转换成字符串的过程. 反序列化:字符串转成其它数据类型. 序列化的目的 1:以某种存储形式使用自定义对象持久 ...

  7. 第五章:标准I/O库

    本章用于解析C语言标准I/O库,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系. 标准I/O库相比于操作系统的I/O库,具有更高的效率和可移植性,前者是 ...

  8. windows通过gcc编译代码

    1.将gcc添加到环境变量 2.检查gcc是否安装成功 cmd下输入gcc –v 3.cd进入需要编译源文件的目录 4.dir查看当前目录下是否有需要编译的文件(linux下用ls) 5.编译文件(H ...

  9. Go学习路径--相关基础

    现在开始接触Go一段时间了,基本路径就是看基础学习材料,开始写项目,有问题找解决问题的方法.这里记录一下学习过程. go相关文章 Golang适合高并发场景的原因分析 go build 不同系统下的可 ...

  10. centos mysql数据库问题:ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'mysql'(转)

    问题描述: 安装好数据库MySQL,进入mysql,设置号密码后,退出的时候,利用密码无法进入,直接回车后可进入,无法看到数据库mysql,use mysql返回错误:ERROR 1044 (4200 ...