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

简介: 在Spring Mvc 中我们在Controller 中要想使用 HttpServletRequest HttpSession HttpServletResponse 等请求信息,这些信息有多种方式,这里就重点说下我使用的拦截器注入方式方式一:(使用注解)/** * 每一个Control 被执行时 * * @author jiangz

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

相关文章
|
1月前
|
缓存 安全 Java
《深入理解Spring》过滤器(Filter)——Web请求的第一道防线
Servlet过滤器是Java Web核心组件,可在请求进入容器时进行预处理与响应后处理,适用于日志、认证、安全、跨域等全局性功能,具有比Spring拦截器更早的执行时机和更广的覆盖范围。
|
1月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
1月前
|
缓存 监控 Java
《深入理解Spring》拦截器(Interceptor)——请求处理的艺术
Spring拦截器是Web开发中实现横切关注点的核心组件,基于AOP思想,可在请求处理前后执行日志记录、身份验证、权限控制等通用逻辑。相比Servlet过滤器,拦截器更贴近Spring容器,能访问Bean和上下文,适用于Controller级精细控制。通过实现`HandlerInterceptor`接口的`preHandle`、`postHandle`和`afterCompletion`方法,可灵活控制请求流程。结合配置类注册并设置路径匹配与执行顺序,实现高效复用与维护。常用于认证鉴权、性能监控、统一异常处理等场景,提升应用安全性与可维护性。
|
8月前
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
483 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
3月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
981 10
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
735 0
|
8月前
|
前端开发 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@PathVariable
`@PathVariable` 是 Spring Boot 中用于从 URL 中提取参数的注解,支持 RESTful 风格接口开发。例如,通过 `@GetMapping(&quot;/user/{id}&quot;)` 可以将 URL 中的 `{id}` 参数自动映射到方法参数中。若参数名不一致,可通过 `@PathVariable(&quot;自定义名&quot;)` 指定绑定关系。此外,还支持多参数占位符,如 `/user/{id}/{name}`,分别映射到方法中的多个参数。运行项目后,访问指定 URL 即可验证参数是否正确接收。
475 0
|
4月前
|
人工智能 安全 Java
Spring Boot yml 配置敏感信息加密
本文介绍了如何在 Spring Boot 项目中使用 Jasypt 实现配置文件加密,包含添加依赖、配置密钥、生成加密值、在配置中使用加密值及验证步骤,并提供了注意事项,确保敏感信息的安全管理。
1130 1
|
4月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
331 0
|
4月前
|
JSON 前端开发 Java
Spring MVC 核心组件与请求处理机制详解
本文解析了 Spring MVC 的核心组件及请求流程,核心组件包括 DispatcherServlet(中央调度)、HandlerMapping(URL 匹配处理器)、HandlerAdapter(执行处理器)、Handler(业务方法)、ViewResolver(视图解析),其中仅 Handler 需开发者实现。 详细描述了请求执行的 7 步流程:请求到达 DispatcherServlet 后,经映射器、适配器找到并执行处理器,再通过视图解析器渲染视图(前后端分离下视图解析可省略)。 介绍了拦截器的使用(实现 HandlerInterceptor 接口 + 配置类)及与过滤器的区别
396 0