您的当前位置:首页正文

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

2021-11-30 来源:钮旅网
拦截器获取request的值之后,Controller拿不到值的解决

⽬录

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

原因

解决⽅法

使⽤拦截器获取Controller⽅法名和注解信息⽅法⼀:通过request获得⽤户的URL⽅法⼆:通过⽤户要访问的⽅法来判断是否有权限⽅法三:⾃定义注解拦截器获取request的值之后,Controller拿不到值

原因

在Spring中request的值只能被获取⼀次,拦截器获取之后就会导致Controller拿不到值

解决⽅法

将request的值进⾏备份,请求到达Controller的时候就会拿到这个值

创建⼀个⾃⼰的HttpServletRequestWrapper并继承servlet的HttpServletRequestWrapper,为了备份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())); }}

创建⼀个Filter,将该过滤器配置在项⽬中,为了调⽤备份的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() { }}

创建⼀个⼯具类,在拦截器中获取request的值

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)这种⽅法还是不太⽅便

⽅法三:⾃定义注解

⾃定义注解代码:

@Retention(RUNTIME)@Target(METHOD)

public @interface MyOperation {

String value() default \"\";//默认为空,因为名字是value,实际操作中可以不写\"value=\"}

Controller代码:

@Controller(\"testController\")public class TestController {

@MyOperation(\"⽤户修改\")//主要看这⾥ @RequestMapping(\"test\") @ResponseBody

public String test(String id) { return \"Hello,2018!\"+id; }}

拦截器的代码:

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

补充

在每个⽅法上⾯加注解太⿇烦啦,可以在类上加注解

@Retention(RUNTIME)@Target(TYPE)

public @interface MyOperation { String value() default \"\";}

//拦截器中这样获得

h.getMethod().getDeclaringClass().getAnnotation(MyOperation.class);

我可以获取requestMapping,不⽤创建⾃定义注解啊,值得注意的是,不要使⽤GetMapping等,要使⽤requestMapping。以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。

因篇幅问题不能全部显示,请点此查看更多更全内容