您的位置:首页 > 理论基础 > 计算机网络

多次读取HttpServletRequest的inputstream方法 问题解决

2016-12-07 15:17 801 查看
原因:我要收集所有来自前台请求的参数信息,无论在任何地方的。当前请求参数都是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";
}
}


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

结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: