Spring容器トースターのHttpServletRequestオブジェクトを取得して再取得します.

9949 ワード

目次
コンテキストフィルタでHttpServletRequestを持って行ってください.
Request Contactext HolderはHttpServlet Requestを取得します.
HttpServletRequestオブジェクトは一回取得した後、再び動作します.なぜなら、HttpServletRequestは直接にそのストリームの読み取りを二回アクセスすることができません.もしアクセスするなら、元のHttpServletRequestまたはSpringによって管理されたローカル化されたスレッドのHttpSerpServrequestオブジェクトを取得しなければなりません.Request Contactext Holderは私達を助けてくれます.
コンテキストフィルタでHttpServletRequestを持って行ってください.
以下はフィルタ逆コンパイルコードです.
/*     */ package com.xxx.core.filter;
/*     */ 
/*     */ import java.io.IOException;
/*     */ import javax.servlet.Filter;
/*     */ import javax.servlet.FilterChain;
/*     */ import javax.servlet.FilterConfig;
/*     */ import javax.servlet.ServletContext;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.ServletRequest;
/*     */ import javax.servlet.ServletResponse;
/*     */ import javax.servlet.annotation.WebFilter;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ import javax.servlet.http.HttpSession;
/*     */ import org.apache.log4j.Logger;

/*     */ @WebFilter(filterName="context_Filter", urlPatterns={"/*"})
/*     */ public class ContextFilter
/*     */   implements Filter
/*     */ {
/*  34 */   static Logger logger = Logger.getLogger(ContextFilter.class);
/*     */   
/*     */ 
/*  37 */   private static ThreadLocal threadLocalRequest = new ThreadLocal();
/*  38 */   private static ThreadLocal threadLocalResponse = new ThreadLocal();
/*     */   
/*  40 */   private static ThreadLocal threadLocalObject = new ThreadLocal();
/*     */   
/*     */ 
/*     */ 
/*     */   public void destroy() {}
/*     */   
/*     */ 
/*     */   public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
/*     */     throws IOException, ServletException
/*     */   {
/*  50 */     threadLocalRequest.set((HttpServletRequest)arg0);
/*  51 */     threadLocalResponse.set((HttpServletResponse)arg1);
/*  52 */     arg2.doFilter(arg0, arg1);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void init(FilterConfig arg0)
/*     */     throws ServletException
/*     */   {}
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public static HttpServletRequest getRequest()
/*     */   {
/*  68 */     HttpServletRequest req = (HttpServletRequest)threadLocalRequest.get();
/*  69 */     return req;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static HttpSession getSession()
/*     */   {
/*  81 */     HttpServletRequest req = (HttpServletRequest)threadLocalRequest.get();
/*  82 */     if (req == null) {
/*  83 */       return null;
/*     */     }
/*  85 */     return req.getSession();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public ServletContext getServletContext()
/*     */   {
/*  97 */     if (null == getSession()) {
/*  98 */       return null;
/*     */     }
/* 100 */     return getSession().getServletContext();
/*     */   }
/*     */   
/*     */   public static void setSchema(String value)
/*     */   {
/* 105 */     if (null == getRequest()) {
/* 106 */       threadLocalObject.set(value);
/*     */     } else {
/* 108 */       getRequest().setAttribute("_schema_", value);
/*     */     }
/* 110 */     logger.debug(" setSchema >> id=" + Thread.currentThread().getId() + ",name " + Thread.currentThread().getName() + "," + value);
/*     */   }
/*     */   
/*     */   public static String getSchema() {
/* 114 */     if (null == getRequest()) {
/* 115 */       return (String)threadLocalObject.get();
/*     */     }
/* 117 */     return (String)getRequest().getAttribute("_schema_");
/*     */   }
/*     */ }

/* Location:           D:\DEVELOPEWORKS\dataissue\WebRoot\WEB-INF\lib\forestar-core-3.6.4-SNAPSHOT.jar
 * Qualified Name:     com.forestar.core.filter.ContextFilter
 * Java Class Version: 7 (51.0)
 * JD-Core Version:    0.7.1
 */
上記の処理では、HttpServletRequestオブジェクトを正規化スレッドとして保存しました.他のところでは、パラメータ伝達としてHttpServletRequestを使用しなくてもいいです.
HttpServletRequest  request = ContextFilter.getRequest();
しかし、流れを読み取る必要があると、問題が発生します.この時はSpringで管理されているHttpServletRequestを持つ必要があります.
Request Contactext HolderはHttpServlet Requestを取得します.
HttpServletRequestを取得:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
        .getRequestAttributes()).getRequest();
Request Contactext Holderソース:
public abstract class RequestContextHolder  {

    private static final ThreadLocal requestAttributesHolder =
            new NamedThreadLocal("Request attributes");

    private static final ThreadLocal inheritableRequestAttributesHolder =
            new NamedInheritableThreadLocal("Request context");


    public static void resetRequestAttributes() {
        requestAttributesHolder.remove();
        inheritableRequestAttributesHolder.remove();
    }


    public static void setRequestAttributes(RequestAttributes attributes) {
        setRequestAttributes(attributes, false);
    }

    // RequestAttributes     ThreadLocal , HttpServletRequest HttpServletResponse     RequestAttributes   ,      RequestAttributes     。              RequestAttributes  ,    RequestAttributes            HttpServletRequest  
    public static void setRequestAttributes(RequestAttributes attributes, boolean inheritable) {
        if (attributes == null) {
            resetRequestAttributes();
        }
        else {
            if (inheritable) {
                inheritableRequestAttributesHolder.set(attributes);
                requestAttributesHolder.remove();
            }
            else {
                requestAttributesHolder.set(attributes);
                inheritableRequestAttributesHolder.remove();
            }
        }
    }

    public static RequestAttributes getRequestAttributes() {
        RequestAttributes attributes = requestAttributesHolder.get();
        if (attributes == null) {
            attributes = inheritableRequestAttributesHolder.get();
        }
        return attributes;
    }

}
では、spring-mvcではどうやって実現されますか?簡単に分析します.具体的なメカニズムを知りたいなら、spring-mvcのソースコードを見てみてもいいです.
私たちはFraamewark Servletという種類を見ました.つまりDispactch Servletの父の種類です.中にはprocessRequestの方法があります.方法名によってはこの方法が要求を処理するためのものだということが大体分かります.
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        long startTime = System.currentTimeMillis();
        Throwable failureCause = null;

        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
        LocaleContext localeContext = buildLocaleContext(request);

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

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

        // RequestAttributes   RequestContextHolder
        initContextHolders(request, localeContext, requestAttributes);

        try {
            //       
            doService(request, response);
        }
        catch (ServletException ex) {
            failureCause = ex;
            throw ex;
        }
        catch (IOException ex) {
            failureCause = ex;
            throw ex;
        }
        catch (Throwable ex) {
            failureCause = ex;
            throw new NestedServletException("Request processing failed", ex);
        }

        finally {
            //  RequestContextHolder    RequestAttributes
            resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
                requestAttributes.requestCompleted();
            }

            if (logger.isDebugEnabled()) {
                if (failureCause != null) {
                    this.logger.debug("Could not complete request", failureCause);
                }
                else {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        logger.debug("Leaving response open for concurrent processing");
                    }
                    else {
                        this.logger.debug("Successfully completed request");
                    }
                }
            }

            publishRequestHandledEvent(request, response, startTime, failureCause);
        }
    }
    
    
    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);
        }
    }
HttpServletRequestは、doService方法を実行する前に、すなわち具体的な業務ロジックの前に設定され、その後、業務ロジックを実行したり、異常を投げたりした時に、Request Contect Holderをリセットして、現在のHttpServletRequestを除去することができます.
もっと読む:
【Spring】Request Contactext Holderダイジェスト
SprigMVC学習記録(9)--Request Contactext Holder分析