解决SpringMVC拦截器中Request数据只能读取一次的问题


开发项目中,经常会直接在request中取数据,如Json数据,也经常用到@RequestBody注解,也可以直接通过request.getParameter()从Request中取数据。

但是有时候我们要在请求到具体的业务之前做一些操作比如日志记录、数据校验、统一的处理等等,可以在拦截器中处理。

由于 request中getReader()和getInputStream()只能调用一次,我们在拦截器中获取Request中数据后,后面就没法在继续获取数据了,那么可以重写HttpServletRequestWrapper方法来解决。

1. 重写HttpServletRequestWrapper方法:

package com.centit.server.common.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; /**
* <p>request包装类<p>
* @version 1.0
* @author li_hao
* @date 2019年3月3日
*/
public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
} @Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public boolean isFinished() {
return false;
}
public boolean isReady() {
return false;
}
public void setReadListener(ReadListener readListener) {}
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream; }
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
} }

2. 拦截器

package com.centit.server.common.interceptor;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.centit.server.common.utils.RequestWrapper; /**
* <p>拦截器<p>
* @version 1.0
* @author li_hao
* @date 2019年3月3日
*/
public class HandlerInterceptor extends HandlerInterceptorAdapter{ public static Set<HttpSession> sessions; static{
if(sessions==null){
sessions = Collections.synchronizedSet(new HashSet<HttpSession>());
}
} @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8"); String uri = request.getRequestURI(); //获取请求方法:格式为:/meetingserv_xa/smDept/queryAllSmDeptTreeList
String contextpath = request.getContextPath(); System.out.println(uri);
System.out.println(contextpath); String ipAddr = getIpAddr(request); //获取客户端ip
System.out.println(ipAddr); RequestWrapper myRequestWrapper = new RequestWrapper((HttpServletRequest) request);
String body = myRequestWrapper.getBody();
System.out.println(body); //请求数据 return super.preHandle(request, response, handler);
} /**
* 获取客户端请求的当前网络ip
* @param request
* @return
*/
public String getIpAddr(HttpServletRequest request){
String ipAddress = request.getHeader("x-forwarded-for");
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
//根据网卡取本机配置的IP
InetAddress inet=null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress= inet.getHostAddress();
}
}
//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15
if(ipAddress.indexOf(",")>0){
ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
}
}
return ipAddress;
}
}

3. 配置拦截器(spring-mvc.xml):

<!-- 拦截器 -->
<mvc:interceptors>
<bean class="com.centit.server.common.interceptor.HandlerInterceptor" />
</mvc:interceptors>

4. 过滤器:

package com.centit.server.common.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import com.centit.server.common.utils.RequestWrapper; /**
* <p>过滤器<p>
* @version 1.0
* @author li_hao
* @date 2019年3月3日
*/
public class HttpServletFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(request instanceof HttpServletRequest) {
requestWrapper = new RequestWrapper((HttpServletRequest) request);
}
if(requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
public void destroy() { }
}

5. 配置过滤器(web.xml):

  <filter>
<filter-name>requestFilter</filter-name>
<filter-class>com.centit.server.common.filter.HttpServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

解决SpringMVC拦截器中Request数据只能读取一次的问题的更多相关文章

  1. 解决SpringMVC拦截器拦截静态资源的问题。

    在使用SpringMVC进行开发的时候,遇到了以下代码不能执行的情况.而且我已经正确导入了JQuery框架. <script type="text/javascript"&g ...

  2. 解决springmvc拦截器拦截静态资源的两种方式

    1.是采用<mvc:default-servlet-handler />,(一般Web应用服务器默认的Servlet名称是"default",所以这里我们激活Tomca ...

  3. SpringMVC之八:基于SpringMVC拦截器和注解实现controller中访问权限控制

    SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法. preHandle在业务处理器 ...

  4. spring boot拦截器中获取request post请求中的参数

    最近有一个需要从拦截器中获取post请求的参数的需求,这里记录一下处理过程中出现的问题. 首先想到的就是request.getParameter(String )方法,但是这个方法只能在get请求中取 ...

  5. CSS样式表、JS脚本加载顺序与SpringMVC在URL路径中传参数与SpringMVC 拦截器

    CSS样式表和JS脚本加载顺序 Css样式表文件要在<head>中先加载,这样网页显示时可以第一次就渲染出正确的布局和样式,网页就不会闪烁,或跳变 JS脚本尽可能放在<body> ...

  6. 在SpringBoot项目中添加SpringMVC拦截器

    1.认识拦截器 SpringMVC的拦截器(Interceptor)不是Filer,同样可以实现请求的预处理.后处理.使用拦截器仅需要两个步骤 实现拦截器 注册拦截器 1.1实现拦截器 实现拦截器可以 ...

  7. Spring拦截器中通过request获取到该请求对应Controller中的method对象

    背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...

  8. 基于SpringMVC拦截器和注解实现controller中访问权限控制

    SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法. preHandle在业务处理器 ...

  9. Springboot中SpringMvc拦截器配置与应用(实战)

    一.什么是拦截器,及其作用 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对 ...

随机推荐

  1. MSDE2008安装备忘

    MSDE2008安装备忘(适用于WIN7 8 10) 1.系统中必须要VC8.0,即VC2005运行库.2.系统中必须要有.net framework2.0.3.5.4.6运行库.3.windows防 ...

  2. javaAgent介绍

    JavaAgent(转载) http://www.cnblogs.com/diyunpeng/archive/2011/05/26/2057932.html 一文带你了解Java Agent http ...

  3. node vue

    官网 ECMAScript 6 Node.Js WebPack Vue.js Vuex Vue-loader (类比css-loader,是webpack中用于处理.vue文件的) vue-route ...

  4. python初识,变量,条件判断语句,基本数据类型,while循环语句

    python文件后缀可以是任意,但是导入模块时不用.py后缀时会报错 python文件的两种执行方式: python解释器 python文件路径 进入python解释权,事实获取执行结果 在Linux ...

  5. DCDC电源 TPS54525

    电路图: 输入电压12V,输出电压5V.不接负载可以获得5V输出,接入负载后只有4mV,且PG为低. 预计原因:可能是上电瞬间电流过大,芯片过流保护. 解决方案:SS软启动引脚的电容C331加大至1u ...

  6. hyper-v下的ubuntu虚拟机分辨率修改

    修改/etc/default/grub sudo vim /etc/default/grub 改变前: GRUB_CMDLINE_LINUX_DEFAULT="quiet splash&qu ...

  7. Web漏洞扫描工具(批量脱壳、反序列化、CMS)

    一.什么是Web漏洞扫描工具 即是指“扫描Web应用以查找安全漏洞(如跨站脚本,SQL注入,命令执行,目录遍历和不安全服务器配置)的自动化工具”,其中许多可能是由不安全或不正确的编码和设计.另一方面, ...

  8. Configuring SSL for SAP Host Agent on UNIX

    https://help.sap.com/viewer/141cbf7f183242b0ad0964a5195b24e7/114/en-US/8d12f7b9244b44219bd14d619d3a2 ...

  9. html5自带表单验证

    起因:今天无意中发现chrome的input框自带表单验证!于是就去试试firefox,惊奇的发现也有自带的验证提示,只不过两者的样式不一样 chrome中的样子: firefox中的样子: 发散:具 ...

  10. 解决由于服务器调用删除或添加字段后CXF客户端未更新导致异常问题org.apache.cxf.interceptor.Fault: Unmarshalling Error: Unexpected element

    采用CXF客户端调用Webservice服务,由于服务端时不时会对Webservice服务删除或添加一些字段,而CXF未及时更新客户端代码导致再次调用服务时报异常错误: Interceptor for ...