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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • spring-AOP 及 AOP获取request各项参数操作

    spring-AOP 及 AOP获取request各项参数 AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待. 一.AOP的基本概念 Aspect(切面):通常是一个类,里面可以定义切入点和通知 JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用 Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around Pointcut(切入点

  • 详解利用SpringMVC拦截器控制Controller返回值

    背景:需求是在Controller中方法没有实现时,返回模拟结果.主要用于项目初期前台跟后台的交互,Web项目就是在前台发出请求然后后台响应并返回结果.本示例利用拦截器和注解实现跳过执行方法直接返回定义结构的功能. 通过定义一个StringResult注解,在访问方法的时候返回StringResult中的内容.通过Debug注解来定义方法是否要返回StringResult中的内容. Debug默认为TRUE package com.tiamaes.dep.annotation; import j

  • SpringBoot拦截器如何获取http请求参数

    1.1.获取http请求参数是一种刚需 我想有的小伙伴肯定有过获取http请求的需要,比如想 前置获取参数,统计请求数据 做服务的接口签名校验 敏感接口监控日志 敏感接口防重复提交 等等各式各样的场景,这时你就需要获取 HTTP 请求的参数或者请求body,一般思路有两种,一种就是自定义个AOP去拦截目标方法,第二种就是使用拦截器.整体比较来说,使用拦截器更灵活些,因为每个接口的请求参数定义不同,使用AOP很难细粒度的获取到变量参数,本文主线是采用拦截器来获取HTTP请求. 1.2.定义拦截器获

  • 教你用Springboot实现拦截器获取header内容

    分析 既然需要动态获取那么只有两种方式:要么每次下游请求过来时从请求头中获取,要么定义统一的拦截器自动获取. 实现 那么我们就先来实现一下吧. 第一种比较简单,直接使用springboot获取请求头的方式,从controller方法入口处使用: @RequestHeader(value = "xxxx",required = false) String appUser的方式获取请求头 代码如下: @RequestMapping(name = "获取用户详情信息",v

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

    目录 拦截器获取request的值之后,Controller拿不到值 原因 解决方法 使用拦截器获取Controller方法名和注解信息 方法一:通过request获得用户的URL 方法二:通过用户要访问的方法来判断是否有权限 方法三:自定义注解 拦截器获取request的值之后,Controller拿不到值 原因 在Spring中request的值只能被获取一次,拦截器获取之后就会导致Controller拿不到值 解决方法 将request的值进行备份,请求到达Controller的时候就会拿

  • SpringBoot项目拦截器获取Post方法的请求body实现

    1). 存在问题流只能读取一次 2). 目标多次读取流 3). 解决方法创建包装类 4). RequestWrapper package com.mazaiting.redeye.wrapper;   import com.mazaiting.redeye.utils.StreamUtil; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory;   import jav

  • 解决struts2 拦截器修改request的parameters参数失败的问题

    目录 struts2拦截器修改request的parameters参数失败 修改指定拦截器的参数(Struts2) struts2 拦截器修改request的parameters参数失败 为了解决struts2的xss(跨站脚本攻击)问题,我打算用struts2自带的拦截器来过滤所有由request传递来的参数. <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC &quo

  • springboot HandlerIntercepter拦截器修改request body数据的操作

    实际工作中学习技术是最快.最深刻的.当然,自身的持续学习意识是必须的 技术栈版本: spring boot 2.0.2 遇到事儿了 近来做业务需求,前端同学fe将userId和userName放到request header中了. 后端api接口要想使用userId和userName,每个接口都要从header中获取. 试想一下,如果你有十个接口,那么每个接口都要写一遍 Object.setUserId(request.getHeader("userId")) 正如下面代码段 @Res

  • Springboot拦截器如何获取@RequestBody参数

    Springboot拦截器获取@RequestBody参数 HttpContextUtils import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader;

  • Spring MVC实现的登录拦截器代码分享

    之前接触过struts拦截器,但是没有使用过Spring MVC拦截器,今天花了一天时间好好研究了一下. 本文首先介绍了拦截器的基本概念,然后向大家阐述拦截器与过滤器的简要区别,通过HandlerInterceptor 接口中定义的三个方法实现拦截器功能,最后介绍了配置相关的代码,接下来看看具体内容. 定义拦截器 SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的.在SpringMVC 中定义一个Interceptor 非常简单,主要有两

  • SpringMVC拦截器超详细解读

    目录 1.什么是拦截器 2.拦截器和过滤器有哪些区别 3.拦截器方法 4.多个拦截器的执行流程 1.什么是拦截器 ​ SpringMVC提供了Intercepter拦截器机制,类似于Servlet当中的Filter过滤器,用于拦截用户的请求并作出相应的处理,比如通过拦截器来进行用户权限验证或者用来判断用户是否登录.SpringMVC拦截器是可插拔式的设计,需要某一功能拦截器,就需要在配置文件中应用拦截器即可:如果不需要这个功能拦截器,只需要在配置文件中取消该拦截器即可. 2.拦截器和过滤器有哪些

  • SpringMVC拦截器快速掌握下篇

    目录 拦截器参数 前置处理方法 后置处理方法 完成处理方法 拦截器链配置 配置多个拦截器 创建拦截器类 配置拦截器类 拦截器参数 前置处理方法 原始方法之前运行preHandle public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); retu

随机推荐