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

相关文章
|
18天前
|
开发框架 前端开发 网络协议
Spring Boot结合Netty和WebSocket,实现后台向前端实时推送信息
【10月更文挑战第18天】 在现代互联网应用中,实时通信变得越来越重要。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为客户端和服务器之间的实时数据传输提供了一种高效的解决方案。Netty作为一个高性能、事件驱动的NIO框架,它基于Java NIO实现了异步和事件驱动的网络应用程序。Spring Boot是一个基于Spring框架的微服务开发框架,它提供了许多开箱即用的功能和简化配置的机制。本文将详细介绍如何使用Spring Boot集成Netty和WebSocket,实现后台向前端推送信息的功能。
199 1
|
15天前
|
前端开发 Java 测试技术
深入剖析:Spring Boot Controller中请求处理方法的访问修饰符
【10月更文挑战第21天】 在Spring Boot应用中,Controller类中的请求处理方法通常用于处理HTTP请求。这些方法的访问修饰符(private或public)对方法的行为和可访问性有着重要影响。本文将深入探讨在Controller中使用private和public修饰符的区别,以及它们对Spring MVC框架的影响。
21 8
|
28天前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
28天前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
19 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
1月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
52 2
|
2月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
1月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
97 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
2月前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
3月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
3月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
下一篇
无影云桌面