魯春利的工做筆記,好記性不如爛筆頭html
web.xmljava
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Invicme</display-name> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <context-param> <param-name>shiroEnvironmentClass</param-name> <param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value> </context-param> <context-param> <param-name>shiroConfigLocations</param-name> <param-value>classpath:shiro/shiro-form-filter.ini</param-value> </context-param> <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
web.xml的配置中<context-param>的做用
1. 啓動一個WEB項目的時候,容器(如:Tomcat)會去讀它的配置文件web.xml
讀兩個節點: <listener></listener> 和 <context-param></context-param>
2. 緊接着,容器建立一個ServletContext(上下文),這個WEB項目全部部分都將共享這個上下文
3. 容器將<context-param></context-param>轉化爲鍵值對,並交給ServletContext
4. 容器建立<listener></listener>中的類實例,即建立監聽
5. 在監聽中會有contextInitialized(ServletContextEvent args)初始化方法
在這個方法中得到ServletContext = ServletContextEvent.getServletContext();
context-param的值 = ServletContext.getInitParameter("context-param的鍵");
6. 獲得這個context-param的值以後,能夠作一些其餘操做了web
ShiroFilterapache
package org.apache.shiro.web.servlet; import org.apache.shiro.web.env.WebEnvironment; import org.apache.shiro.web.filter.mgt.FilterChainResolver; import org.apache.shiro.web.util.WebUtils; /** * @see org.apache.shiro.web.env.EnvironmentLoader EnvironmentLoader * @see org.apache.shiro.web.env.EnvironmentLoaderListener EnvironmentLoaderListener * @see <a href="http://shiro.apache.org/web.html">Apache Shiro Web Documentation</a> * @since 1.2 */ public class ShiroFilter extends AbstractShiroFilter { /** * @see org.apache.shiro.web.env.EnvironmentLoaderListener * @since 1.2 */ @Override public void init() throws Exception { // WebEnvironment env = WebUtils.getRequiredWebEnvironment(getServletContext()); setSecurityManager(env.getWebSecurityManager()); FilterChainResolver resolver = env.getFilterChainResolver(); if (resolver != null) { setFilterChainResolver(resolver); } } }
輔助工具類WebUtilssession
package org.apache.shiro.web.util; public class WebUtils { public static WebEnvironment getRequiredWebEnvironment(ServletContext sc) throws IllegalStateException { WebEnvironment we = getWebEnvironment(sc); if (we == null) { throw new IllegalStateException("No WebEnvironment found: no EnvironmentLoaderListener registered?"); } return we; } public static WebEnvironment getWebEnvironment(ServletContext sc) { return getWebEnvironment(sc, EnvironmentLoader.ENVIRONMENT_ATTRIBUTE_KEY); } public static WebEnvironment getWebEnvironment(ServletContext sc, String attrName) { if (sc == null) { // 異常 } Object attr = sc.getAttribute(attrName); if (attr == null) { // 返回null(ServletContext中無該屬性) return null; } if (attr instanceof RuntimeException) { // 異常 } if (attr instanceof Error) { // 異常 } if (attr instanceof Exception) { // 異常 } if (!(attr instanceof WebEnvironment)) { // 異常 } // 獲取到實際的值 return (WebEnvironment) attr; } }
ServletContext中的EnvironmentLoader.ENVIRONMENT_ATTRIBUTE_KEY屬性是在何時設置的呢?app
WebEnvironment的類圖結構
jsp
EnvironmentLoaderListeneride
package org.apache.shiro.web.env; public class EnvironmentLoaderListener extends EnvironmentLoader implements ServletContextListener { // Web應用被初始化時默認調用的方法 public void contextInitialized(ServletContextEvent sce) { // 調用父類EnvironmentLoader的initEnvironment方法 initEnvironment(sce.getServletContext()); } // Web應用被銷燬時默認調用的方法(reload時是會調用該方法) public void contextDestroyed(ServletContextEvent sce) { destroyEnvironment(sce.getServletContext()); } }
EnvironmentLoader工具
package org.apache.shiro.web.env; public class EnvironmentLoader { // 在web.xml文件中指定WebEnvironment的實現類 public static final String ENVIRONMENT_CLASS_PARAM = "shiroEnvironmentClass"; // 在web.xml文件中指定ini文件路徑(不指定則默認加載/WEB-INF/shiro.ini) public static final String CONFIG_LOCATIONS_PARAM = "shiroConfigLocations"; // 初始化Environment實例 public WebEnvironment initEnvironment(ServletContext servletContext) throws IllegalStateException { if (servletContext.getAttribute(ENVIRONMENT_ATTRIBUTE_KEY) != null) { // 第一次Web應用啓動時上下文中已經存在該KEY的屬性,說明web.xml文件配置有問題,可能有多個EnvironmentLoader*的定義 // 異常 } // 記錄日誌 servletContext.log("Initializing Shiro environment"); log.info("Starting Shiro environment initialization."); // 記錄當前時間 long startTime = System.currentTimeMillis(); try { // 獲取WebEnvironment類的實例 WebEnvironment environment = createEnvironment(servletContext); // 在ServletContext中設置KEY,設置完成後在WebUtils中就能夠獲取到了 servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, environment); // 在日誌中輸出ServletContext中設置WebEnvironment耗費的時間(毫秒) if (log.isInfoEnabled()) { long elapsed = System.currentTimeMillis() - startTime; log.info("Shiro environment initialized in {} ms.", elapsed); } return environment; } catch (RuntimeException ex) { // 異常 } catch (Error err) { // 異常 } } // 在給定的ServletContext中設置WebEnvironment protected WebEnvironment createEnvironment(ServletContext sc) { Class<?> clazz = determineWebEnvironmentClass(sc); if (!MutableWebEnvironment.class.isAssignableFrom(clazz)) { // native方法,底層JVM實現 // 異常 } // 從ServletContext中獲取shiroConfigLocations屬性的值(classpath:shiro/shiro-form-filter.ini) String configLocations = sc.getInitParameter(CONFIG_LOCATIONS_PARAM); boolean configSpecified = StringUtils.hasText(configLocations); if (configSpecified && !(ResourceConfigurable.class.isAssignableFrom(clazz))) { // 異常 } // 獲取類的實例(ClassUtils.newInstance(clazz) ==> return clazz.newInstance();) MutableWebEnvironment environment = (MutableWebEnvironment) ClassUtils.newInstance(clazz); // 調用父類DefaultWebEnvironment的setServletContext environment.setServletContext(sc); if (configSpecified && (environment instanceof ResourceConfigurable)) { // 調用父類ResourceBasedWebEnvironment的setConfigLocations ((ResourceConfigurable) environment).setConfigLocations(configLocations); } customizeEnvironment(environment); // LifecycleUtils.init中會調用environment.init方法(IniWebEnvironment.init()) LifecycleUtils.init(environment); // 返回獲得的WebEnvironment類的實例(IniWebEnvironment的實例) return environment; } // 獲取WebEnvironment的Class類對象 protected Class<?> determineWebEnvironmentClass(ServletContext servletContext) { // ENVIRONMENT_CLASS_PARAM = "shiroEnvironmentClass";獲取web.xml文件中聲明的屬性值 String className = servletContext.getInitParameter(ENVIRONMENT_CLASS_PARAM); if (className != null) { try { // web.xml配置的參數對應className=org.apache.shiro.web.env.IniWebEnvironment return ClassUtils.forName(className); } catch (UnknownClassException ex) { // 異常 } } else { // 若是未配置則使用該IniWebEnvironment類 return IniWebEnvironment.class; } } // 空的方法體,能夠實現自定義的邏輯 protected void customizeEnvironment(WebEnvironment environment) { // ...... } }