After the interceptor gets the value of request Controller can't get the solution of the value

  • 2021-12-04 18:29:47
  • OfStack

After the directory interceptor gets the value of request, Controller can't get the value. The solution is to use the interceptor to get the method name and annotation information of Controller. Method 1: Get the user's URL through request. Method 2: Judge whether there is permission through the method that the user wants to access. Method 3: Custom annotation

After the interceptor gets the value of request, Controller can't get the value

Cause

In Spring, the value of request can only be obtained once, and the interceptor will not get the value of Controller after obtaining it

Solution

Backup the value of request, and get this value when the request arrives at Controller

Create an HttpServletRequestWrapper of your own and an HttpServletRequestWrapper that inherits servlet in order to back up the values in request.


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()));
    }
}
 

Create 1 Filter and configure the filter in the project to invoke the backup HttpServletRequestWrapper


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() { 
    }
}

Create a tool class to get the value of request in the interceptor


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();
    } 
}

Using interceptors to get Controller method names and annotation information

Permission authentication is used when using SpringMVC for projects.

The table is divided into:

User table Role table Resource table

User-role-resource is a many-to-many relationship, verification is nothing more than receiving the request, in the interceptor cycle to determine whether the user has the authority to perform operations.

Method 1: Obtain the user's URL through request

Then cycle by 1 to determine whether it can be operated

It's just that this method is very uncomfortable.

Method 2: Determine whether there is permission by the method that the user wants to access

In the preHandle method, handler is actually HandlerMethod (see what is said on the Internet sometimes not HandlerMethod), add an instanceof to verify it

You can get the method name: h. getMethod (). getName () You can get the value in the RequestMapping annotation: h. getMethodAnnotation (RequestMapping. class) This method is still inconvenient

Method 3: Customize annotations

Custom annotation code:


@Retention(RUNTIME)
@Target(METHOD)
public @interface MyOperation {
    String value() default "";// The default is empty because the name is value In actual operation, you can not write "value="
}

Controller code:


@Controller("testController")
public class TestController {
    @MyOperation(" User modification ")// Look mainly here 
    @RequestMapping("test")
    @ResponseBody
    public String test(String id) {
        return "Hello,2018!"+id;
    }
}

Code for the interceptor:


@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    System.out.println(" Enter the interceptor ");
    if(handler instanceof HandlerMethod) {
        HandlerMethod h = (HandlerMethod)handler;
        System.out.println(" The action the user wants to perform is :"+h.getMethodAnnotation(MyOperation.class).value());
        // Execute the operation after judgment ...
    }
    return HandlerInterceptor.super.preHandle(request, response, handler);
}

Supplement

It's too much trouble to annotate each method, so you can annotate the class


@Retention(RUNTIME)
@Target(TYPE)
public @interface MyOperation {
    String value() default "";
}
// This is obtained in the interceptor 
h.getMethod().getDeclaringClass().getAnnotation(MyOperation.class);

I can get requestMapping without creating custom annotations. It is worth noting that instead of using GetMapping and so on, use requestMapping.


Related articles: