Spring Mvc 公共Controller 使用拦截器注入请求信息

原创 2017年07月13日 14:25:16

在Spring Mvc 中我们在Controller 中要想使用 HttpServletRequest HttpSession HttpServletResponse 等请求信息,这些信息有多种方式,这里就重点说下我使用的拦截器注入方式

方式一:(使用注解)

/**
     * 每一个Control 被执行时
     * 
     * @author jiangzeyin
     * @date 2016-8-11
     * 
     * @param request
     * @param response
     * @param session
     * @throws IOException
     */
    @ModelAttribute
    public void setReqAndRes(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
        this.request = request;
        this.response = response;
        this.session = session;
        this.referer = StringUtil.convertNULL(this.request.getHeader("Referer"));
        this.ip = RequestUtil.getIpAddress(this.request);
        this.response.setCharacterEncoding("UTF-8");
    }

使用@ModelAttribute 注解实现。这个注解有几个作用,如果不了解并且感兴趣的可以去多了解。

方式二(拦截器注入):
第一步:我们需要一个公共拦截器

 @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Class controlClass = ((HandlerMethod) handler).getBean().getClass();
            Object object = handlerMethod.getBean();
            if (AbstractBaseControl.class.isAssignableFrom(controlClass)) {
                abstractBaseControl = (AbstractBaseControl) object;
                abstractBaseControl.setReqAndRes(this.request, this.session, this.response);
            }
        }
        return true;
    }

在拦截器中我们主要判断拦截到的是否是我们的对应Controller 然后调用对应赋值方法。

public void setReqAndRes(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
        this.request = request;
        this.response = response;
        this.session = session;
        this.referer = StringUtil.convertNULL(this.request.getHeader("Referer"));
        this.ip = RequestUtil.getIpAddress(this.request);
        this.response.setCharacterEncoding("UTF-8");
    }

setReqAndRes 方法和使用注解方法里面的内容基本相似。

这样我们就基本的对Controller 里面的请求信息可以完全的控制了。在使用这个方法去赋值的时候,在实际业务中我们发现了一个问题。

偶尔request 对象 或者session 对象会报错,因为这两的对象是使用频率最高的。报错最高的对象是request ,这里由于没有记录这个错误现在也无法贴出错误信息。后期看能遇到不,遇到就补上错误信息。

大致情况是这样的。如果使用这样的方式赋值,那么在我们的Controller 的 scope 使用request 时候,这样是完全没有问题的。因为 Controller 的scope 作用域是request 时,那么就代表每一个请求 都会创建一个Controller 对象这样 对象里面的变量就是独立的。
如果我们将Controller 的scope 改变不是request 时候,那么可能出现多个请求使用的同一个Controller 对象 这里对象里面的变量可能在后一个请求把request 对象给覆盖了 这样如果前一个请求的响应耗时大于后一个请求,就意味着前一个请求使用request 对象的时候 就使用到了后一个请求的request 那么这样就出现异常了。

这里写图片描述
大致是这样的情况。一天我突然想到 因为我们都知道web 程序都是一个线程处理一个请求,我们先在同一个对象中区分不同线程的变量,java 中还存在这个类 那就是 ThreadLocal 这个类就是可以实现在区分不同线程中的不同值。

那么进过改后的BaseControl 去掉以前的那些req res session 等成员变量 改为

 private static ThreadLocal<HttpServletRequest> request_local = new ThreadLocal<>();
 private static ThreadLocal<HttpSession> session_local = new ThreadLocal<>();
 private static ThreadLocal<HttpServletResponse> response_local = new ThreadLocal<>();

同时把 setReqAndRes 方法也得改造 下

 /**
     * 拦截器注入
     *
     * @param request
     * @param session
     * @param response
     */
    public void setReqAndRes(HttpServletRequest request, HttpSession session, HttpServletResponse response) {
        request_local.set(request);
        session_local.set(session);
        response_local.set(response);
        this.ip = RequestUtil.getIpAddress(this.getRequest());
        this.getResponse().setCharacterEncoding("UTF-8");
    }

然后在我们需要对用对应变量时候,就得重新写方法来获取了

    public HttpServletRequest getRequest() {
        return request_local.get();
    }

    public HttpSession getSession() {
        return session_local.get();
    }

    public HttpServletResponse getResponse() {
        return response_local.get();
    }

这样就可以完美的解决了,就可以保证使用的request 等对象都是属于自己的了。

对这个思路欢迎提出质疑和建议:

QQ群: 136715345 加入

邮 件: bwcx_jzy@qq.com 邮件

版权声明:本文为博主原创文章,请珍惜博主的劳动成果。

相关文章推荐

springboot拦截器@Autowired为null解决

今天遇见一个问题,在自定义拦截器中,使用了@Autowaire注解注入了jpa的dao,结果发现无法注入,注入的dao为空,查阅资料之后解决,解决方案如下 问题原因拦截器加载的时间点在springco...
  • slgxmh
  • slgxmh
  • 2016年07月08日 13:41
  • 4903

Spring MVC配置及拦截器的实现

如题所示,这里主要是介绍拦截器的使用了但是为了更贴合实际的项目所以我们先导入spring mvc框架。为了使用spring mvc我们要导入相关的包,它依赖于spring-web 和spring -w...

springmvc 拦截器拦截静态资源

springmvc拦截器interceptors   springmvc拦截器能够对请求的资源路径进行拦截,极大的简化了拦截器的书写。但是,千万千万要注意一点:静态资源的放行。  上代码: ....

Spring 初探(五)(Spring Bean 自动装配与自定义监听事件)

现在通行的使用bean的方法是不通过xml进行配置,而仅仅采用java 内置的类指明bean及相应的依赖关系,下面展开叙述。 @Configuration可以声明某个类是作为配置类,在这样的类中 ...

MYSQL创建一个 “将一个字符串以某个分隔符分隔得到多个值” 的函数,并为多个值加上序号

1:首先创建一个自定义函数实现分隔的功能:思路: (1、获取分隔符在源字符串中第一次出现的位置,把获取的位置之前的子字符串赋值给表的一列 (2、把第一步获取的位置之后的子字符串赋值为新的源字符串 ...

spring mvc 拦截器打印详细的请求参数信息

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) t...

spring mvc inteceptor 拦截器实现计算controller 的执行时间

什么是 spring inteceptor , SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Inter...

spring mvc框架的aop拦截器验证controller层的注解值

功能是,验证用户是否用controller方法上注解内的权限码,没有则不能进入方法 注解定义代码: package com.jd.las.goods.attribute.permission; im...

使用ProceedingJoinPoint获取当前请求的方法等参数——spring mvc拦截器

在项目中常常需要顾虑请求参数中的特殊字符,比如+,等 解决方案是可以使用spring mvc 的拦截器,配合aspectJ使用 package com.cpic.core.web; import...

spring MVC(新增拦截器demo)

  • 2015年02月08日 19:08
  • 18.68MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring Mvc 公共Controller 使用拦截器注入请求信息
举报原因:
原因补充:

(最多只允许输入30个字)