由SpringMVC中RequetContextListener說起
阿新 • • 發佈:2017-06-23
listener attribute 請求 bool 程序 div n) https 操作
零、引言
RequetContextListener從名字結尾Listener來看就知道屬於監聽器。 所謂監聽器就是監聽某種動作,在其開始(初始化)和結束(銷毀)的時候進行某些操作。 由此可以猜測:該類用於在RequetContext(請求上下文對象)創建和銷毀的時候進行某些操作(哪些操作?結尾總結!)一、web.xml配置
要使用該listener對象需要在web.xml中進行如下配置。<!-- 此監聽器是監聽HttpRequest對象,方便ContextHolderUtils程序調用HttpRequest對象 --> <listener> <description>request監聽器</description> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
二、三個重要類解讀
2.1 RequetContextListener
public class RequestContextListener implements ServletRequestListener { private static final String REQUEST_ATTRIBUTES_ATTRIBUTE = RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES"; // 在請求進入的時候,初始化變量放入ThreadLocal<T>中 @Override public void requestInitialized(ServletRequestEvent requestEvent) { //判定當前的requetEvent中獲取的ServletRequest()對象是否是HttpServletRequet對象 if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) { throw new IllegalArgumentException( "Request is not an HttpServletRequest: " + requestEvent.getServletRequest()); } //強制轉型為 HttpServletRequest HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest(); // ServletRequestAttributes 保存了HttpServletRequet、Response、Session等變量 ServletRequestAttributes attributes = new ServletRequestAttributes(request); request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes); LocaleContextHolder.setLocale(request.getLocale()); //RequestContextHolder裏面有一個ThreadLocal,當前線程共享 RequestContextHolder.setRequestAttributes(attributes); } //在請求被銷毀的時候,將在初始化時候的ThreadLocal變量清空。 @Override public void requestDestroyed(ServletRequestEvent requestEvent) { ... } }
2.2 RequetContextHolder
public abstract class RequestContextHolder { //ThreadLocal<T>變量用於保存當前線程的共享變量 private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal<RequestAttributes>("Request attributes"); private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal<RequestAttributes>("Request context"); /** * 將線程中的共享變量清除掉,會在RequetContextListner的destory()方法中調用。 */ public static void resetRequestAttributes() { //清空變量 requestAttributesHolder.remove(); inheritableRequestAttributesHolder.remove(); } //過渡方法 public static void setRequestAttributes(RequestAttributes attributes) { setRequestAttributes(attributes, false); } // 核心的方式:將RequetAttrubutes(Request/Response/Session)放入到ThreadLocal<T>中進行共享 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(); } } }
2.3 ServletRequestAttributes
public class ServletRequestAttributes extends AbstractRequestAttributes { private final HttpServletRequest request; private HttpServletResponse response; private volatile HttpSession session; private final Map<String, Object> sessionAttributesToUpdate = new ConcurrentHashMap<String, Object>(1); }
三、使用方法
從以上可以知道RuquetAttribute是放在了ThreadLocal中,則在該次請求中,可以在任意的代碼位置中獲取該該對象,由此拿到HttpServletRequet等對象。HttpServletRequest request =((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();利用該方法可以在任意位置獲取request對象.
四、總結
RequetContextListner主要作用就一個: 將本次請求的 ServletRequestAttributes 對象 保存在ThreadLocal中,方便在某一次請求的任意代碼位置獲取(包括直接在service層獲取)。http://www.cnblogs.com/LiuChunfu/p/7067828.html
由SpringMVC中RequetContextListener說起