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 邮件

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

Spring MVC AOP通过自定义注解方式拦截Controller等实现日志管理

之前一直写.net,没玩过spring,一直没用过aop(面向切面编程)这类功能,当然不是说.net里面没有这类框架,企业库就可以微软企业库官网开始上代码:注解定义package com.jianku...
  • xunzaosiyecao
  • xunzaosiyecao
  • 2016年08月18日 20:53
  • 7284

已经解决 spring boot 拦截器中注入bean

已经解决 spring boot 拦截器中如何注入bean的问题
  • qq_24443187
  • qq_24443187
  • 2017年04月03日 22:20
  • 1053

Spring框架注入注解与拦截器浅谈

依赖注入注解 1实现注入的注解:    (1)修饰属性、方法、构造函数      @Autowire:自动注入,自动去spring容器中寻找指定的bean来注入,require属性指定注入这个b...
  • qq_16485855
  • qq_16485855
  • 2016年01月24日 12:14
  • 2384

SpringMVC拦截器中通过反射得到Controller方法注解时ClassCastException解决方案

错误应用场在Controller中,我们自定义了一个@Auth注解来实现权限控制功能,如:@Auth(verifyLogin=false,verifyURL=false) @RequestMa...
  • tracker_w
  • tracker_w
  • 2015年06月11日 16:19
  • 7013

spring拦截器使用及拦截器中获取Controller实例

1,首先是配置,在spring-mvc的配置文件中加上 2,编写拦截器类 package cn.hydom.ztc.ztc_cp.controller.common...
  • u013614451
  • u013614451
  • 2014年11月02日 17:19
  • 5534

Spring MVC - 拦截器实现 和 用户登陆例子

1.拦截器   SpringMvc中的拦截器实现了HandlerInterceptor接口,通常使用与身份认证,授权和校验,模板视图,统一处理等;    public class HanderIn...
  • LABLENET
  • LABLENET
  • 2016年01月08日 16:09
  • 29520

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

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) t...
  • qq_27292113
  • qq_27292113
  • 2017年08月07日 14:39
  • 2568

自定义Spring的Aop切面类拦截业务请求,并获取到请求的参数名和参数值

1.问题引入 本次需求是涉及到审核操作,添加,修改,删除人员,商品时如果需要审核,则先向审核队列表中插入审核信息,不需要审核时直接操作业务表(用户表)。这里许多操作都需要判断是否需要审核,所以我就定...
  • u014532775
  • u014532775
  • 2017年07月06日 18:48
  • 4365

MVC页面不同控制器下的方法调用同一个后台函数

尤其是在多语言开发当中,切换语言的时候很有用。关键点就是要找到路径。 比如,我有个_LoginPartial.cshtml,这个页面是网页的公用部分,自己开发的网站,每个页面都会加载这一部分内容。 ...
  • liuxufeiyang000
  • liuxufeiyang000
  • 2015年11月24日 10:57
  • 2196

SpringAOP实现拦截Controller请求参数并输出到日志

一、实现的效果请求:http://localhost:8080/regist?username=king&age=12&password=123456Controller:@RestControlle...
  • KingBoyWorld
  • KingBoyWorld
  • 2017年07月25日 21:25
  • 1592
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring Mvc 公共Controller 使用拦截器注入请求信息
举报原因:
原因补充:

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