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

    介绍 1.malloc,free和new,delete区别. a.malloc,free是C/C++的标准库函数.new,delete是c++的操作符. b.malloc申请的是内存,严格意义不是&q ...

  2. day0~day13

    day0 day1 day2 day4 day5 day7 day9 day10 day12 day13

  3. 【数据结构 Python & C++】顺序表

    用C++ 和 Python实现顺序表的简单操作 C++代码 // Date:2019.7.31 // Author:Yushow Jue #include<iostream> using ...

  4. golang使用注意事项

    1.可以给类型取别名,但是该类型和别名是两个不同的类型: type myInt int 2.go支持可变参数:args... 0个或多个参数:func sum(args... int) sum int ...

  5. maven 依赖 无法下载到jar包,典型的json-lib包

    <dependency>            <groupId>net.sf.json-lib</groupId>            <artifact ...

  6. 利用sort对结构体进行排序

    我定义了一个学生类型的结构体来演示sort排序对结构体排序的用法 具体用法看代码 #include<iostream> #include<string> #include< ...

  7. Yii2.0 RESTful API 之速率限制

    Yii2.0 RESTFul API 之速率限制 什么是速率限制? 权威指南翻译过来为限流,为防止滥用,你应该考虑对您的 API 限流. 例如,您可以限制每个用户 10 分钟内最多调用 API 100 ...

  8. shell习题第23题:检测网卡流量

    [题目要求] 写一个脚本,检测网卡流量并记录到日志,需要按照如下格式并一分钟统计一次(只需统计外网网卡,网卡名称eth0) 2019-06-07 1:11 eth0 input: 1000bps et ...

  9. Java AmericanFlagSort

    Java AmericanFlagSort /** * <html> * <body> * <P> Copyright 1994-2018 JasonInterna ...

  10. 初试Maven

    1 [检查]确认已经安装jdk,已经环境变量中配置JAVA_HOME,已经修改Path 2 [下载]从http://maven.apache.org/download.cgi下载所需要的版本,笔者使用 ...