问题: 使用springMVC,一些请求前的校验,都可以在拦截器或者过滤器里做处理,处理完后到Controller层再根据喜好做相关操作,但是遇到content-type是application/json等放在body体里的就尴尬了,读完body,在Controller就无法再获取一次了,或许你可以把request的inputStream读出来缓存两份。但这要动根基了,不划算。另外,如果需要改变某个参数再由@RequestBody注入,又是一个尴尬的问题,可以把配置的Json处理写成自己的逻辑。但所有请求都经过这个也显得累赘。
键值形式的传参处理
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 | package com.sq580.mall.order.web; 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 javax.servlet.http.HttpServletResponse; public class XxxInterceptor implements Filter {     @Override      public void destroy() {}     @Override     public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException,             ServletException {         HttpServletRequest req = (HttpServletRequest) arg0;         ServletRequest requestWrapper = new ParameterRequestWrapper(req);         String body = HttpHelper.getBodyString(requestWrapper);         System.out.println(body);                  arg2.doFilter(requestWrapper, (HttpServletResponse) arg1);     }     @Override     public void init(FilterConfig arg0) throws ServletException {} }
 | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
 | package com.xxx; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.Enumeration; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class ParameterRequestWrapper extends HttpServletRequestWrapper { 	private final byte[] body;     public ParameterRequestWrapper(HttpServletRequest request) throws IOException {         super(request);         body = HttpHelper.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();             }         };     }     @Override     public String getHeader(String name) {         return super.getHeader(name);     }     @Override     public Enumeration<String> getHeaderNames() {         return super.getHeaderNames();     }     @Override     public Enumeration<String> getHeaders(String name) {         return super.getHeaders(name);     } }
 | 
HttpHelper工具类
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
 | package com.xxx; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import javax.servlet.ServletRequest; public class HttpHelper {           * 获取请求Body      * @param request      * @return      */     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();     } }
 | 
web.xml
| 1 2 3 4 5 6 7 8
 | <filter> 	<filter-name>requestFilter</filter-name> 	<filter-class>com.xxx.XxxInterceptor</filter-class> </filter> <filter-mapping> 	<filter-name>requestFilter</filter-name> 	<url-pattern>/*</url-pattern> </filter-mapping>
 | 
body传参处理 使用aop来切Controller中的方法,这时参数已经注入了,不存在重复读request流的问题
注意: 这里开启aop的配置需要写在springmvc中,不能写在spring的applicationContext.xml中,两者有所区别
| 1 2
 | <aop:aspectj-autoproxy proxy-target-class="true" /> <context:component-scan base-package="com.xxx" />
 | 
切面的使用,注意要扫包
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 | @Aspect @Component public class PariseAspect { 	 	@Pointcut("execution(* com.xxx.*.*Controller.*(..))")         public  void controllerAspect() {} 	 	 		// before 		// 你可以让它继续执行,也可以返回,是这么一种环绕意义,有点类似过滤器 		// after 	}*/ 	@Around("controllerAspect()") 	public Object checkToken(ProceedingJoinPoint point) { 		 		Object[] args = point.getArgs(); 		Class clazz = args[0].getClass(); 		Method m = clazz.getDeclaredMethod("setUserId", Long.class); 		if (null != m) { 			m.invoke(arg, 1L); 			args[1] = arg; 		} else { 			 			return "error.jsp"; 		} 		return point.proceed(args); 	} }
 |