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 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 tableUser-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.