zoukankan      html  css  js  c++  java
  • Shiro JNDI

    概念

      Shiro的JNDI主要是用来为JdbcRealm提供DataSource的。话说天下文章一大抄,shiro抄袭Spring的又一力证就是关于JNDI的设计。

    Tomcat配置JDNI,Shiro获得数据源的Demo

      ${catalina.base}/conf/context.xml中配置Resource

    <Resource 
             name="Iss002DataSource"
             type="org.apache.commons.dbcp.BasicDataSource"
             maxActive="100" 
             maxIdle="30" 
             maxWait="10000"
             username="iss002" 
             password="iss002password"
             driverClassName="oracle.jdbc.driver.OracleDriver"
             url="jdbc:oracle:thin:@127.0.0.1:1521:iss002" 
    />

      Shiro的API获得DataSource

    package com.wjz.demo.jndi;
    
    import javax.sql.DataSource;
    
    import org.apache.shiro.jndi.JndiObjectFactory;
    
    public class ShiroJndiDemo {
    
        public static void main(String[] args) {
            JndiObjectFactory<DataSource> factory = new JndiObjectFactory<DataSource>();
            factory.setResourceName("Iss002DataSource");
            factory.setRequiredType(DataSource.class);
            factory.setResourceRef(true);
            DataSource dataSource = factory.getInstance();
            System.out.println(dataSource.getClass().getName());
        }
    }

    JndiObjectFactory

      工厂模式,根据注入的resourceName和requiredType获得实例

    requiredType可以不注入,获得实例时找定位器开始定位

    public T getInstance() {
        try {
            if(requiredType != null) {
                return requiredType.cast(this.lookup(resourceName, requiredType));
            } else {
                return (T) this.lookup(resourceName);
            }
        } catch (NamingException e) {
            final String typeName = requiredType != null ? requiredType.getName() : "object";
            throw new IllegalStateException("Unable to look up " + typeName + " with jndi name '" + resourceName + "'.", e);
        }
    }

    JndiLocator

    具备了JndiTempleate模板器

    protected Object lookup(String jndiName, Class requiredType) throws NamingException {
        if (jndiName == null) {
            throw new IllegalArgumentException("jndiName argument must not be null");
        }
        String convertedName = convertJndiName(jndiName);
        Object jndiObject;
        try {
            // 使用JndiTemplate模板器定位jndiObject
            jndiObject = getJndiTemplate().lookup(convertedName, requiredType);
        }
        catch (NamingException ex) {
            if (!convertedName.equals(jndiName)) {
                // Try fallback to originally specified name...
                if (log.isDebugEnabled()) {
                    log.debug("Converted JNDI name [" + convertedName +
                            "] not found - trying original name [" + jndiName + "]. " + ex);
                }
                jndiObject = getJndiTemplate().lookup(jndiName, requiredType);
            } else {
                throw ex;
            }
        }
        log.debug("Located object with JNDI name '{}'", convertedName);
        return jndiObject;
    }
    
    // 因为jndiName必须有前缀'java:comp/env/',该方法为注入的name添加前缀
    protected String convertJndiName(String jndiName) {
        // Prepend container prefix if not already specified and no other scheme given.
        if (isResourceRef() && !jndiName.startsWith(CONTAINER_PREFIX) && jndiName.indexOf(':') == -1) {
            jndiName = CONTAINER_PREFIX + jndiName;
        }
        return jndiName;
    }

    JndiTemplate

      获得Jndi对象使用了javax.naming.*的API,获得过程都是相同的使用了模板模式,执行方法中使用了回调模式

    public Object lookup(final String name) throws NamingException {
        log.debug("Looking up JNDI object with name '{}'", name);
        // 类似于异步调用一样,执行了execute方法,又返回来调用了JndiCallBack的行为
        // 当然可以创建了InitialContext然后执行lookup再关闭context
        // execute方法传入一个回调,执行过程中创建了InitialContext,回调获得jndiObject再回来关掉context
        return execute(new JndiCallback() {
            public Object doInContext(Context ctx) throws NamingException {
                Object located = ctx.lookup(name);
                if (located == null) {
                    throw new NameNotFoundException(
                            "JNDI object with [" + name + "] not found: JNDI implementation returned null");
                }
                return located;
            }
        });
    }
    
    public Object execute(JndiCallback contextCallback) throws NamingException {
        Context ctx = createInitialContext();
        try {
            return contextCallback.doInContext(ctx);
        }
        finally {
            try {
                ctx.close();
            } catch (NamingException ex) {
                log.debug("Could not close JNDI InitialContext", ex);
            }
        }
    }
    
    protected Context createInitialContext() throws NamingException {
        Properties env = getEnvironment();
        Hashtable icEnv = null;
        if (env != null) {
            icEnv = new Hashtable(env.size());
            for (Enumeration en = env.propertyNames(); en.hasMoreElements();) {
                String key = (String) en.nextElement();
                icEnv.put(key, env.getProperty(key));
            }
        }
        return new InitialContext(icEnv);
    }

    JndiCallback

      定义公共行为,在javax.naming.Context中查找JndiObject

  • 相关阅读:
    [Matlab] subplot 紧凑,减少空白
    论文
    统计学习理论
    位操作
    Pattern Recognition and Machine Learning
    HDU6862 Hexagon (2020HDU 多校 D8 H)
    VS2008 : error PRJ0002 : 错误的结果 1 (从“d:/Program Files/Microsoft Visual Studio 9.0/VC/bin/cl.exe”返回)
    static简单实例说明其用法(转)
    ArcGIS Engine开发系列:将地图导出为图片的两种方法
    按类别列出的编译器选项
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/9724716.html
Copyright © 2011-2022 走看看