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

    对应于服务选项的 Windows 10 当前版本 https://docs.microsoft.com/zh-cn/windows/release-information/ 所有的日期都按照 ISO ...

  2. NationalInstruments project

    //using NationalInstruments.NI4882; //请将项目文件中的"AutoGenerateBindingRedirects"属性设置为true //ht ...

  3. 【Docker】:docker安装ELK(logstash,elasticsearch,kibana)

    一:安装logstash 1.拉取镜像 docker pull logstash:5.6.11 2.创建目录 mkdir /docker/logstash cd /docker/logstash 3. ...

  4. windows MinGW gcc 编译乱码问题

    问题描述 一般很多编辑器默认都是保存成utf-8文件,然而在输出中文的时候出现了乱码?另外试了其他方法,有的乱码,有的不乱? MinGW gcc 编译 utf-8 文件的时候乱码 MinGW gcc ...

  5. setting中executable for debug session对话框

  6. Fabric中的节点类型

    在Fabric中,尽管所有对等节点/peer都是相同的,但它们可以根据网络的配置方式承担多个角色:(①②是主要的节点类型) ①提交节点: 通道中的每个对等节点都是一个提交节点.它们接收生成的交易区块, ...

  7. spring cloud 停止服务

    shutdown的默认url为host:port/shutdown,当需要停止服务时,向服务器post该请求即可,如:curl -X POST host:port/shutdown将得到形如{&quo ...

  8. MySQL 使用tee记录语句和输出日志

    在mysql命令行中,使用tee命令,可以记录语句和输出到指定文件.在debugging时会很有用.每执行一条语句,mysql都会讲执行结果刷新到指定文件.Tee功能只在交互模式生效. mysql&g ...

  9. (十六)Hibernate中的延迟加载

    一.什么是延迟加载 为了节省Hibernate加载对象的性能节销,在Hibernate中真正需要用到这个对象时,才会发出        SQL语句来抓取这个对象.这一个过程称为延迟加载. 二.延迟加载 ...

  10. svn之合并分支

    学习连接 svn的merge使用例子