好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

拦截器获取request的值之后,Controller拿不到值的解决

拦截器获取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

查看更多关于拦截器获取request的值之后,Controller拿不到值的解决的详细内容...

  阅读:49次