攔截器獲取request的值之后,Controller拿不到值
原因
在Spring中request的值只能被獲取一次,攔截器獲取之后就會導致Controller拿不到值
解決方法
將request的值進行備份,請求到達Controller的時候就會拿到這個值
創建一個自己的HttpServletRequestWrapper并繼承servlet的HttpServletRequestWrapper,為了備份request中的值。
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
|
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte [] buff; public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super (request); InputStream is = request.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte [] b = new byte [ 1024 ]; int len; while ((len = is.read(b)) != - 1 ) { baos.write(b, 0 , len); } buff = baos.toByteArray(); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(buff); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } }; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader( new InputStreamReader(getInputStream())); } } |
創建一個Filter,將該過濾器配置在項目中,為了調用備份的HttpServletRequestWrapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class MyRequestBodyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; servletRequest = new MyHttpServletRequestWrapper(httpServletRequest); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } |
創建一個工具類,在攔截器中獲取request的值
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class RequestUtils { public static String getRequestValue(HttpServletRequest request) throws IOException { StringBuffer sb = new StringBuffer(); MyHttpServletRequestWrapper myHttpServletRequestWrapper = new MyHttpServletRequestWrapper(request); InputStream is = myHttpServletRequestWrapper.getInputStream(); BufferedReader br = new BufferedReader( new InputStreamReader(is)); String str; while ((str = br.readLine()) != null ) { sb.append(str); } return sb.toString(); } } |
使用攔截器獲取Controller方法名和注解信息
在使用SpringMVC進行項目的時候用到了權限驗證。
表分為:
- 用戶表
- 角色表
- 資源表
用戶-角色-資源都是多對多的關系,驗證無非就是收到請求后,在攔截器循環判斷用戶是否有權限執行操作。
方法一:通過request獲得用戶的URL
再逐一循環判斷是否可以操作
只是這種方法很讓人難受。
方法二:通過用戶要訪問的方法來判斷是否有權限
preHandle方法中handler實際為HandlerMethod,(看網上說的有時候不是HandlerMethod),加個instanceof驗證吧
- 可以得到方法名:h.getMethod().getName()
- 可以得到RequestMapping注解中的值:h.getMethodAnnotation(RequestMapping.class)
- 這種方法還是不太方便
方法三:自定義注解
自定義注解代碼:
1
2
3
4
5
|
@Retention (RUNTIME) @Target (METHOD) public @interface MyOperation { String value() default "" ; //默認為空,因為名字是value,實際操作中可以不寫"value=" } |
Controller代碼:
1
2
3
4
5
6
7
8
9
|
@Controller ( "testController" ) public class TestController { @MyOperation ( "用戶修改" ) //主要看這里 @RequestMapping ( "test" ) @ResponseBody public String test(String id) { return "Hello,2018!" +id; } } |
攔截器的代碼:
1
2
3
4
5
6
7
8
9
10
11
|
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println( "進入攔截器" ); if (handler instanceof HandlerMethod) { HandlerMethod h = (HandlerMethod)handler; System.out.println( "用戶想執行的操作是:" +h.getMethodAnnotation(MyOperation. class ).value()); //判斷后執行操作... } return HandlerInterceptor. super .preHandle(request, response, handler); } |
補充
在每個方法上面加注解太麻煩啦,可以在類上加注解
1
2
3
4
5
6
7
|
@Retention (RUNTIME) @Target (TYPE) public @interface MyOperation { String value() default "" ; } //攔截器中這樣獲得 h.getMethod().getDeclaringClass().getAnnotation(MyOperation. class ); |
我可以獲取requestMapping,不用創建自定義注解啊,值得注意的是,不要使用GetMapping等,要使用requestMapping。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/xj19940904/article/details/103167496