shiro web应用入口之EnvironmentLoaderListener类

EnvironmentLoaderListener 是shiro web应用的入口, 它是一个 ServletContext 的监听器, 用于监听容器的启动和关闭事件, 分别对应它的两个方法, contextInitialized(ServletContextEvent sce) 和contextDestroyed(ServletContextEvent sce), 可以从 ServletContextEvent 中直接获取 ServletContext.
请参考: http://shiro.apache.org/static/1.4.0/apidocs/org/apache/shiro/web/env/EnvironmentLoaderListener.html

我们通过在 web.xml 中定义下列代码来设置shiro web应用的入口

<listener>
     <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>

查看 EnvironmentLoaderListener 的源码我们可以发现, 真正用来处理逻辑的是它的父类 EnvironmentLoader, EnvironmentLoader 通过 initEnvironment
(ServletContext servletContext) 方法来初始化Shiro运行所需要的环境.

接下来我们就来看下 EnvironmentLoader 这个类. 我们先来看看这个类之中两个关键的变量

public static final String ENVIRONMENT_CLASS_PARAM = "shiroEnvironmentClass";

public static final String CONFIG_LOCATIONS_PARAM = "shiroConfigLocations";

shiroEnvironmentClass : 用来在 web.xml 中设置自定义的 WebEnvironment 具体实现类. 默认实现类是 IniWebEnvironment.
shiroConfigLocations : 用来在 web.xml 中指定 WebEnvironment 的配置文件. 默认路径是
1. /WEB-INF/shiro.ini
2. classpath:shiro.ini
我们来举个列子:

<context-param>
     <param-name>shiroEnvironmentClass</param-name>
     <param-value>com.foo.bar.shiro.MyWebEnvironment</param-value>
</context-param>
<context-param>
     <param-name>shiroConfigLocations</param-name>
     <param-value>/WEB-INF/someLocation/shiro.ini</param-value>
</context-param>

我们看下这个类的入口方法initEnvironment(ServletContext servletContext)方法(去掉了日志输出等代码)

public WebEnvironment initEnvironment(ServletContext servletContext) throws IllegalStateException {

    // 确保 WebEnvironment 在 ServletContext 中只能创建一次
    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);
    }
    try {
        // 创建 WebEnvironment
        WebEnvironment environment = createEnvironment(servletContext);
        // 将 WebEnvironment 放入 ServletContext 中
        servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY,environment);
        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;
    }
}

我们可以发现逻辑处理的主要实现实际上在createEnvironment(ServletContext sc)方法中, 那么我们再来看下createEnvironment(ServletContext sc)方法.

protected WebEnvironment createEnvironment(ServletContext sc) {

    // 确定用来创建 WebEnvironment 的具体实现类, 默认实现类是 IniWebEnvironment
    WebEnvironment webEnvironment = determineWebEnvironment(sc);
    // 确保 webEnvironment 实现了 MutableWebEnvironment 接口
    if (!MutableWebEnvironment.class.isInstance(webEnvironment)) {
        throw new ConfigurationException("Custom WebEnvironment class [" + webEnvironment.getClass().getName() +
                "] is not of required type [" + MutableWebEnvironment.class.getName() + "]");
    }

    // 获取 web.xml 中的 shiroConfigLocations 配置
    String configLocations = sc.getInitParameter(CONFIG_LOCATIONS_PARAM);
    boolean configSpecified = StringUtils.hasText(configLocations);

    // 判断 web.xml 中是否有配置 shiroConfigLocations, 并确保 WebEnvironment 的实现类实现了 ResourceConfigurable 接口
    if (configSpecified && !(ResourceConfigurable.class.isInstance(webEnvironment))) {
        String msg = "WebEnvironment class [" + webEnvironment.getClass().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) webEnvironment;

    // 将 ServletContext 放入该 WebEnvironment 实例中
    environment.setServletContext(sc);

    if (configSpecified && (environment instanceof ResourceConfigurable)) {
        ((ResourceConfigurable) environment).setConfigLocations(configLocations);
    }

    // 空方法 忽略
    customizeEnvironment(environment);

    // WebEnvironment 初始化
    LifecycleUtils.init(environment);

    return environment;
}

总结:
1. 通过在 web.xml 中配置licenser, 可以使容器在启动时, 通过 EnvironmentLoaderListener 类拿到 ServletContext, 然后通过其父类 EnvironmentLoader 去创建 WebEnvironment
2. EnvironmentLoader 会根据 web.xml 中配置的 shiroEnvironmentClass 去找到对应的 WebEnvironment 实现类, 如果没有配置, 默认使用 IniWebEnvironment 类, 要求自定义的 WebEnvironment 实现类必须实现MutableWebEnvironment 接口.
3. EnvironmentLoader 会根据 web.xml 中配置的 shiroConfigLocations 去找到对应的shiro配置文件, 如果没有配置, 默认先去找 /WEB-INF/shiro.ini, 如果还没有, 再去找 classpath:shiro.ini
4. 最后执行 WebEnvironment 实现类的初始化操作

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值