直奔主題
實現方法:
SpringMVC是通過前端控制器(DispatcherServlet)接收請求進行請求轉發的,所以可以從這里入手把request對象替換為自定義的request對象,從而解決request的輸入流只能讀取一次的問題.
步驟:
1..重寫service方法,實現替換request操作
package org.XXX.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.XXX.request.CustomRequest; public class DispatcherServlet extends org.springframework.web.servlet.DispatcherServlet { private static final long serialVersionUID = 6781076086037842254L; @Override protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { // 全局替換request對象 super.service(new CustomRequest(request), response); } }
將我們自己的前端控制器配置到web.xml中
<servlet> <servlet-name>springmvc</servlet-name> <!-- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> --> <servlet-class>org.XXX.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
至此request替換操作已經完成,下面進入重點.
2.實現自己的HttpServletRequest
package org.XXX.request; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import org.apache.commons.io.IOUtils; /** * 自定義Request * */ public class CustomRequest extends HttpServletRequestWrapper { private byte[] postBody; public CustomRequest(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { if (postBody == null) { postBody = IOUtils.toByteArray(super.getInputStream()); } return new CustomServletInputStream(postBody); } /** * 自定義ServletInputStream * */ private static class CustomServletInputStream extends ServletInputStream { private final InputStream is; CustomServletInputStream(byte[] postBody) { if (postBody == null) { postBody = new byte[0]; } this.is = new ByteArrayInputStream(postBody); } @Override public int read() throws IOException { return is.read(); } } }
大功告成!!
最后附上AOP方法中讀取post內容的部分代碼
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String requestBody = null; if ("POST".equals(request.getMethod())) { // 讀取requestBody byte[] bytes = IOUtils.toByteArray(request.getInputStream()); requestBody = new String(bytes,request.getCharacterEncoding()); }else{ Map<String,String[]> parameterMap = request.getParameterMap(); if(parameterMap != null && !parameterMap.isEmpty()){ requestBody = gson.toJson(parameterMap); } } if (requestBody != null && !requestBody.isEmpty()) { logger.info("requestBody: " + requestBody); }