zoukankan      html  css  js  c++  java
  • 将登录等信息保存到session中和退出session

    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;
    }

    <span class="hljs-keyword">public <span class="hljs-keyword">static HttpServletResponse <span class="hljs-title">getResponse(){</br>
        HttpServletResponse resp = ((ServletWebRequest)RequestContextHolder.getRequestAttributes()).getResponse();</br>
        <span class="hljs-keyword">return resp;</br>
    }</br></br>
    

    }

            在大部分的情况下,它都能很好地工作,但在商品管理编辑中,新增商品时,却出现了意外的问题:通过RequestHolder.getRequest().getParameter()得不到参数值,通过debug发现,
    通过spring mvc的method注入的request对象实际为MultipartHttpServletRequest,而通过RequestHolder.getRequest()获取到的request对象却是org.apache.catalina.connector.RequestFacade的实例。 

    public class RequestFacade implements 
    HttpServletRequest

    原来在商品新增时,由于使用了文件上传,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());
    ...... }
    <span class="hljs-keyword">protected HttpServletRequest <span class="hljs-title"><span style="color: #ff0000; font-size: 14pt;"><strong>checkMultipart</strong></span>(HttpServletRequest request) <span class="hljs-keyword">throws MultipartException {</br>
        <span class="hljs-keyword">if (<span class="hljs-keyword">this.multipartResolver != <span class="hljs-keyword">null &amp;&amp; <span class="hljs-keyword">this.multipartResolver.isMultipart(request)) {</br>
            <span class="hljs-keyword">if (request <span class="hljs-keyword"><span style="color: #ff0000; font-size: 14pt;"><strong>instanceof MultipartHttpServletRequest</strong></span>) {</br>
                logger.debug(<span class="hljs-string">"Request is already a MultipartHttpServletRequest - if <span style="color: #0000ff; font-size: 18pt;"><strong>not in a forward</strong></span>, " +</br>
                        <span class="hljs-string">"this typically results from an additional MultipartFilter in web.xml");</br>
            }</br>
            <span class="hljs-keyword">else {</br>
                <span class="hljs-keyword">return <span class="hljs-keyword">this.multipartResolver.<span style="color: #0000ff; font-size: 14pt;"><strong>resolveMultipart</strong></span>(request);</br>
            }</br>
        }</br>
        <span class="hljs-comment">// If not returned before: return original request.</br>
        <span class="hljs-keyword">return request;</br>
    }</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
    

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

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

    ......
        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();</br>
        ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);</br></br>
    
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);</br>
        asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), <span class="hljs-keyword">new RequestBindingInterceptor());</br></br>
    
        initContextHolders(request, localeContext, requestAttributes);</br></br>
    
        <span class="hljs-keyword">try {</br>
            doService(request, response);</br>
        }</br>
        ......</br>
    }</br>
    
    
    <span class="hljs-keyword">protected ServletRequestAttributes <span class="hljs-title"><span style="color: #ff0000; font-size: 14pt;"><strong>buildRequestAttributes</strong></span>(</br>
            HttpServletRequest request, HttpServletResponse response, RequestAttributes previousAttributes) {</br></br>
    
        <span class="hljs-keyword">if (previousAttributes == <span class="hljs-keyword">null || previousAttributes <span class="hljs-keyword"><span style="color: #ff0000; font-size: 14pt;"><strong>instanceof ServletRequestAttributes</strong></span>) {</br></br>
            <span class="hljs-keyword">return <span class="hljs-keyword">new ServletRequestAttributes(request);
        }</br>
        <span class="hljs-keyword">else {</br>
            <span class="hljs-keyword">return <span class="hljs-keyword">null;  <span class="hljs-comment">// preserve the pre-bound RequestAttributes instance</br>
        }</br>
    }</br></br>
    
    
    <span class="hljs-keyword">private <span class="hljs-keyword">void <span class="hljs-title">initContextHolders(</br>
            HttpServletRequest request, LocaleContext localeContext, RequestAttributes requestAttributes) {</br></br>
    
        <span class="hljs-keyword">if (localeContext != <span class="hljs-keyword">null) {</br>
            LocaleContextHolder.setLocaleContext(localeContext, <span class="hljs-keyword">this.threadContextInheritable);</br>
        }</br>
        <span class="hljs-keyword">if (requestAttributes != <span class="hljs-keyword">null) {</br>
            RequestContextHolder.setRequestAttributes(requestAttributes, <span class="hljs-keyword">this.threadContextInheritable);</br>
        }</br>
        <span class="hljs-keyword">if (logger.isTraceEnabled()) {</br>
            logger.trace(<span class="hljs-string">"Bound request context to thread: " + request);</br>
        }</br>
    }</br>
    

    从这里可以看到,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

    http://dinguangx.iteye.com/blog/2227049

  • 相关阅读:
    石子合并问题(直线版)
    Python_07-常用函数
    Python_06-函数与模块
    C++中的头文件和源文件
    sell 项目 商品表 设计 及 创建
    SpringBoot集成Mybatis
    SpringBoot集成jdbcTemplate/JPA
    SpringBoot使用JSP渲染页面
    SpringBoot引入freemaker前端模板
    使用SpringBoot创建Web项目
  • 原文地址:https://www.cnblogs.com/jpfss/p/9081769.html
Copyright © 2011-2022 走看看