首页 > 其他 > 详细

项目启动时shiro加载过程

时间:2021-05-18 15:52:51      阅读:37      评论:0      收藏:0      [点我收藏+]

1.web下的shiro启动过程(shiro1.2及之后版本)

web入口web.xml配置

<!--- shiro 1.2 -->
    <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><!-- 默认先从/WEB-INF/shiro.ini,如果没有找classpath:shiro.ini -->
    </context-param>
    <context-param>
        <param-name>shiroConfigLocations</param-name>
        <param-value>classpath:shiro.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>
EnvironmentLoaderListener是一个ServletContextListener,会在容器启动和销毁的时候执行对应方法。实际上具体的方法在父类EnvironmentLoader中实现
public class EnvironmentLoaderListener extends EnvironmentLoader implements ServletContextListener {

   //servlet容器启动的时候调用
    public void contextInitialized(ServletContextEvent sce) {
        initEnvironment(sce.getServletContext());
    }

    //servlet容器销毁的时候调用
    public void contextDestroyed(ServletContextEvent sce) {
        destroyEnvironment(sce.getServletContext());
    }
}

下面详细看一下EnvironmentLoader中启动初始化方法initEnvironment(源码EnvironmentLoader类119行)

    public WebEnvironment initEnvironment(ServletContext servletContext) throws IllegalStateException {

//防止已经被初始化过了,这里做个校验
if (servletContext.getAttribute(ENVIRONMENT_ATTRIBUTE_KEY) != null) { String msg = "There is already a Shiro environment associated with the current ServletContext. " + "Check if you have multiple EnvironmentLoader* definitions in your web.xml!"; throw new IllegalStateException(msg); } servletContext.log("Initializing Shiro environment"); log.info("Starting Shiro environment initialization."); long startTime = System.currentTimeMillis(); try {
       //重点是这,创建WebEnvironment WebEnvironment environment
= createEnvironment(servletContext); servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, environment); log.debug("Published WebEnvironment as ServletContext attribute with name [{}]", ENVIRONMENT_ATTRIBUTE_KEY); if (log.isInfoEnabled()) { long elapsed = System.currentTimeMillis() - startTime; log.info("Shiro environment initialized in {} ms.", elapsed); } return environment; } catch (RuntimeException ex) { log.error("Shiro environment initialization failed", ex); servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, ex); throw ex; } catch (Error err) { log.error("Shiro environment initialization failed", err); servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, err); throw err; } }

下面看一下创建WebEnvironment过程(源码EnvironmentLoader类,193行)

    protected WebEnvironment createEnvironment(ServletContext sc) {
        
//加载IniWebEnvironment Class
<?> clazz = determineWebEnvironmentClass(sc); if (!MutableWebEnvironment.class.isAssignableFrom(clazz)) { throw new ConfigurationException("Custom WebEnvironment class [" + clazz.getName() + "] is not of required type [" + WebEnvironment.class.getName() + "]"); }
//获取shiro配置路径 String configLocations
= sc.getInitParameter(CONFIG_LOCATIONS_PARAM); boolean configSpecified = StringUtils.hasText(configLocations); if (configSpecified && !(ResourceConfigurable.class.isAssignableFrom(clazz))) { String msg = "WebEnvironment class [" + clazz.getName() + "] does not implement the " + ResourceConfigurable.class.getName() + "interface. This is required to accept any " + "configured " + CONFIG_LOCATIONS_PARAM + "value(s)."; throw new ConfigurationException(msg); } MutableWebEnvironment environment = (MutableWebEnvironment) ClassUtils.newInstance(clazz); environment.setServletContext(sc); if (configSpecified && (environment instanceof ResourceConfigurable)) { ((ResourceConfigurable) environment).setConfigLocations(configLocations); } customizeEnvironment(environment);
//重点是初始化过程 LifecycleUtils.init(environment);
return environment; }

上面代码加载IniWebEnvironment的就是web.xml中shiroEnvironmentClass配置的org.apache.shiro.web.env.IniWebEnvironment,加载过程如下(源码EnvironmentLoader类,165行),ENVIRONMENT_CLASS_PARAM=shiroEnvironmentClass,CONFIG_LOCATIONS_PARAM=shiroConfigLocations(就是web.xml配置的两个全局参数)

    protected Class<?> determineWebEnvironmentClass(ServletContext servletContext) {
        String className = servletContext.getInitParameter(ENVIRONMENT_CLASS_PARAM);
        if (className != null) {
            try {
                return ClassUtils.forName(className);
            } catch (UnknownClassException ex) {
                throw new ConfigurationException(
                        "Failed to load custom WebEnvironment class [" + className + "]", ex);
            }
        } else {
            return IniWebEnvironment.class;
        }
    }

下面分析初始化过程
LifecycleUtils.init(environment),最终会调用IniWebEnvironment的init()方法(源代码IniWebEnvironment类,62行)
    public void init() {
        //这里暂时还没有配置文件,需要从前面加载的configLocations路径中加载
Ini ini
= getIni(); String[] configLocations = getConfigLocations(); if (log.isWarnEnabled() && !CollectionUtils.isEmpty(ini) && configLocations != null && configLocations.length > 0) { log.warn("Explicit INI instance has been provided, but configuration locations have also been " + "specified. The {} implementation does not currently support multiple Ini config, but this may " + "be supported in the future. Only the INI instance will be used for configuration.", IniWebEnvironment.class.getName()); } if (CollectionUtils.isEmpty(ini)) { log.debug("Checking any specified config locations.");
//从配置路径下加载shiro配置 ini
= getSpecifiedIni(configLocations); } if (CollectionUtils.isEmpty(ini)) { log.debug("No INI instance or config locations specified. Trying default config locations."); ini = getDefaultIni(); } if (CollectionUtils.isEmpty(ini)) { String msg = "Shiro INI configuration was either not found or discovered to be empty/unconfigured."; throw new ConfigurationException(msg); } setIni(ini);
//重点又来了,shiro需要的类是从这里开始加载的 configure(); }

下面分析configure()方法,(源代码IniWebEnvironment类,95行)

    protected void configure() {

        this.objects.clear();

        WebSecurityManager securityManager = createWebSecurityManager();
        setWebSecurityManager(securityManager);

        FilterChainResolver resolver = createFilterChainResolver();
        if (resolver != null) {
            setFilterChainResolver(resolver);
        }
    }

 

项目启动时shiro加载过程

原文:https://www.cnblogs.com/ouym/p/14780367.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!