`
dinguangx
  • 浏览: 245641 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[JShop]Spring MVC的RequestContextHolder使用误区

阅读更多

JShop简介:jshop是一套使用Java语言开发的B2C网店系统,致力于为个人和中小企业提供免费、好用的网店系统。

项目主页:http://git.oschina.net/dinguangx/jshop

在线演示:

    在spring mvc中,为了随时都能取到当前请求的request对象,可以通过RequestContextHolder的静态方法getRequestAttributes()获取Request相关的变量,如request, response等。 
        在jshop中,对RequestContextHolder的使用进一步封装,简化为RequestHolder类,如下:

public class RequestHolder {
    public static HttpServletRequest getRequest(){
        HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return req;
    }

    public static HttpServletResponse getResponse(){
        HttpServletResponse resp = ((ServletWebRequest)RequestContextHolder.getRequestAttributes()).getResponse();
        return resp;
    }
}

        在大部分的情况下,它都能很好地工作,但在商品管理编辑中,新增商品时,却出现了意外的问题:通过RequestHolder.getRequest().getParameter()得不到参数值,通过debug发现,通过spring mvc的method注入的request对象实际为MultipartHttpServletRequest,而通过RequestHolder.getRequest()获取到的request对象却是RequestFacfade的实例。 
        原来在商品新增时,由于使用了文件上传,form表单的enctype类型为”multipart/form-data”,spring mvc对文件上传的处理类实际却为spring-mvc.xml文件中配置的CommonsMultipartResolver, 该类先判断当前请求是否为multipart类型,如果是的话,将request对象转为MultipartHttpServletRequet,相关的源码见DisptcherServlet


    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        ......
                processedRequest = checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
        ......
                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
        ......
    }

    protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
        if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
            if (request instanceof MultipartHttpServletRequest) {
                logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
                        "this typically results from an additional MultipartFilter in web.xml");
            }
            else {
                return this.multipartResolver.resolveMultipart(request);
            }
        }
        // If not returned before: return original request.
        return request;
    }

        那么,RequestContextHolder中的request又是从哪来的呢? 
继续翻看DispatcherServlet的源码,从其父类FrameworkServlet中找到的processRequest()以相关方法源码:


    protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ......

        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());

        initContextHolders(request, localeContext, requestAttributes);

        try {
            doService(request, response);
        }
        ......
    }


    protected ServletRequestAttributes buildRequestAttributes(
            HttpServletRequest request, HttpServletResponse response, RequestAttributes previousAttributes) {

        if (previousAttributes == null || previousAttributes instanceof ServletRequestAttributes) {
            return new ServletRequestAttributes(request);
        }
        else {
            return null;  // preserve the pre-bound RequestAttributes instance
        }
    }


    private void initContextHolders(
            HttpServletRequest request, LocaleContext localeContext, RequestAttributes requestAttributes) {

        if (localeContext != null) {
            LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
        }
        if (requestAttributes != null) {
            RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Bound request context to thread: " + request);
        }
    }

        从这里可以看到,initContextHolder()方法中完成了RequestContextHolder的requestAttributes设置,而doService()在这之后调用,DispatcherServlet中的processRequest()方法即在doService()之中,所以从RequestContextHolder中获取到的就是原来的RequestFacade对象,而不是经过spring mvc处理之后的MultipartHttpServletRequest对象,其后果就是,从RequestContextHolder获取request后,无法直接通过getParameter()获取参数值。

        最便捷的解决办法: 
直接将HttpServletRequest作为spring mvc的方法入参,即可以正确获取参数值。

Jshop简介:http://git.oschina.net/dinguangx/jshop

1
0
分享到:
评论

相关推荐

    jshop2任务规划

    JSHOP2设计文档的阅读对于理解和使用该系统至关重要,尤其对于那些对规划系统或HTN规划方法感兴趣的开发者而言。 JSHOP2的设计和实现文档介绍了基于层次任务分解的JSHOP2规划系统的技术细节,强调了其Java实现的...

    jshop3完美的界面

    这表明jshop3可能使用了Spring Boot、Struts或Spring MVC等常见的Java Web开发框架,这些框架能帮助快速构建复杂的应用,并提供了良好的可扩展性和维护性。 3. **用户界面设计**:"完美的界面"意味着jshop3在UI/UX...

    JSHOP2.tar.gz

    2. **操作库**:JSHOP2使用一个操作库来存储可以执行的动作和子任务。这些操作定义了任务执行的前置条件和效果,是规划的基础。 3. **域独立性**:JSHOP2设计时考虑了域独立性,这意味着它可以在不同领域中复用,只...

    jshop2-master.zip

    JShop2项目可能采用MVC(Model-View-Controller)架构模式,使用Spring Boot作为基础框架,集成了MyBatis或Hibernate作为ORM工具来操作数据库,可能还采用了Thymeleaf或FreeMarker作为模板引擎渲染视图。此外,它...

    JSHOP2.zip

    `JSHOP2.pdf`很可能是JSHOP2的官方文档或者相关的技术论文,提供了关于JSHOP2的详细原理、使用方法以及实现细节。阅读这份文档对深入理解JSHOP2的运作机制至关重要。 **README** `README`文件通常包含项目的简要...

    JSHOP2规划器下载

    **JSHOP2规划器详解** JSHOP2,全称为Java SHOP2(Situation, Operator, and State Hierarchy Planner 2),是一种基于结构化规划...对于希望解决复杂规划问题的开发者或研究者,JSHOP2是一个值得学习和使用的框架。

    Jshop B2C商城系统

    《Jshop B2C商城系统:深度解析与实践指南》 在互联网技术日新月异的今天,电子商务已经成为商业活动的重要组成部分。其中,B2C(Business-to-Consumer)电商平台以其便捷、高效的特性深受消费者喜爱。Jshop B2C...

    (源码)基于Spring Boot和Vue的Jshop商城系统.zip

    # 基于Spring Boot和Vue的Jshop商城系统 ## 项目简介 Jshop商城系统是一个基于当前流行技术组合的前后端分离商城系统,采用Spring Boot 2、Mybatis Plus、Spring Security、JWT、Redis、Vue等技术栈。该系统包含...

    JShop:【原始代码】java在线商城,包含前原始代码

    #JShop JShop是Jeeshop的分支版本,与Jeeshop最大的区别在于技术选型上的差异:使用spring mvc替换strutus2使用freemarker替换jsp使用maven替换传统的项目结构管理将免费进行得更彻底:使用 ()替换easyui(因为...

    JSHOP2资源,可以直接运行的版本。

    JSHOP2是一个基于Java开发的 SHOP2 扩展版本,专门用于解决多智能体系统中的分布式规划问题。这个资源包提供了完整的JSHOP2源代码,让开发者能够深入了解其内部工作原理,并进行定制化开发。在描述中提到,该压缩包...

    Jshop小程序商城基于Thinkphp5.1框架开发

    前台使用uni-app开发,适配性多,在页面的打开和渲染效率上更快,下单流程流畅自然,可大大增加用户体验,提升订单量。 强大的促销引擎,多种促销方式自由搭配,满足各种场景的促销方式需求,做活动更灵活简单,...

    JSHOP2GUI_1.0.1.zip

    在JSHOP2GUI_1.0.1中,“GUI”代表“图形用户界面”,这意味着开发者为JSHOP2添加了一个直观的交互界面,使得非专业用户也能方便地使用这个强大的规划工具。通过这个界面,用户可以输入任务描述,系统会自动产生满足...

    京东JSHOP右侧悬浮

    ### 京东JSHOP右侧悬浮知识点解析 #### 一、悬浮技术概述 悬浮技术是指网页元素在用户滚动页面时保持相对固定位置的一种前端技术。通过CSS样式中的`position`属性配合`fixed`值来实现,使得特定元素能够在浏览器...

    sdywcd-ostocy-jshop(在线商城程序)

    - "jshop"可能指的是该应用使用的特定框架或组件,可能是开发者自定义的名字,也可能是某个开源电商项目。 - 如果是开源框架,它可能基于MVC(Model-View-Controller)或MVVM(Model-View-ViewModel)架构,提供...

    Jshop短信插件_小程序商城短信接口开发_B2B商城短信发送设置

    在IT行业中,尤其是在电商系统...对于开发者而言,理解并熟练掌握插件的使用和开发,将有助于构建更加智能化、用户体验优良的电商系统。而对于商家来说,合理设置和利用短信插件,无疑能提升客户满意度,促进业务增长。

    开源商城Jshop的后台多页签功能

    这份文档可能详细解释了如何正确安装、配置和使用Jshop的多页签功能,包括备份数据库、更新系统、设置权限等步骤。在进行任何修改前,都应先备份相关数据,以免因误操作导致数据丢失。 总的来说,Jshop的后台多页签...

    Jshop小程序商城,是一款开源的支持可视化布局的电商系统

    Jshop小程序商城,是一款开源的支持可视化布局的电商系统,包含微信小程序、支付宝小程序、APP、公众号、H5端、PC端、抖音小程序、今日头条小程序、皮皮虾小程序、西瓜视频小程序,为大中小企业提供移动电子商务优秀...

    jshop源码jshop源码

    在Jeeshop中,Spring可能被用作依赖注入(DI)容器,用于管理对象的生命周期和相互依赖关系,同时也可能利用Spring的MVC(Model-View-Controller)框架实现Web层的控制。 2. **Mybatis**:Mybatis是一个持久层框架...

    关于ostocy-jshop系统的商品体系结构说明文档

    文件"ostocyjshop商品管理体系功能说明.xls"中,详细列出了各个功能模块的具体操作步骤和注意事项,包括商品添加、分类管理、库存控制、订单处理等流程,对于系统使用者来说,是一份非常实用的参考指南。 总的来说...

    Jshop开源小程序商城系统 v3.0.0.zip

    Jshop开源小程序商城系统 v3.0.0 是一个专为电商行业设计的全面解决方案,旨在帮助企业或个人快速搭建自己的在线购物平台。该系统的核心特性包括但不限于:微信小程序支持、多用户管理、商品分类与展示、订单处理、...

Global site tag (gtag.js) - Google Analytics