tomcat 源码研究之自定义应用工程jar包加载路径

tomcat 启动应用工程的时候,它会加载应用工程中的jar包,而一般情况这些jar包默认放在WEB-INF/lib路径下,那么我们可以不可以指定额外的路径去加载应用工程中所需的jar包呢,这点我明确的告诉你是可以的,而且tomcat给我们预留了扩展 ,具体怎么做请看下面

我们需要在Context.xml中配置
<Context docBase="\webapps\mydocbase">
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="/dir/classes;/somedir/somejar.jar;
/somedir/*.jar"/>
</Context>

 而Context.xml 怎么存放在应用工程的META-INF/context.xml,其实就是在Context节点中配置一个Loader节点

loader节点中className就是解析映射这个Loader的类,virtualclasspath这个属性就是jar包所存放的路径

这里加载的jar包会跟默认路径WEB-INF/lib下的jar一样

下面请看

public class VirtualWebappLoader extends WebappLoader {

    private static final org.apache.juli.logging.Log log=
        org.apache.juli.logging.LogFactory.getLog( VirtualWebappLoader.class );

    /**
     * <code>;</code> separated list of additional path elements.
     */
    private String virtualClasspath = "";

    /**
     * Construct a new WebappLoader with no defined parent class loader (so that
     * the actual parent will be the system class loader).
     */
    public VirtualWebappLoader() {
        super();
    }

    /**
     * Construct a new WebappLoader with the specified class loader to be
     * defined as the parent of the ClassLoader we ultimately create.
     *
     * @param parent The parent class loader
     */
    public VirtualWebappLoader(ClassLoader parent) {
        super(parent);
    }

    /**
     * <code>virtualClasspath</code> attribute that will be automatically set
     * from the <code>Context</code> <code>virtualClasspath</code> attribute
     * from the context xml file.
     * @param path <code>;</code> separated list of path elements.
     */
    public void setVirtualClasspath(String path) {
        virtualClasspath = path;
    }

    /**
     * @return Returns searchVirtualFirst.
     */
    public boolean getSearchVirtualFirst() {
        return getSearchExternalFirst();
    }

    /**
     * @param searchVirtualFirst Whether the virtual class path should be searched before the webapp
     */
    public void setSearchVirtualFirst(boolean searchVirtualFirst) {
        setSearchExternalFirst(searchVirtualFirst);
    }

    /**
     * Implement the requirements
     * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
     *
     * @exception LifecycleException if this component detects a fatal error
     *  that prevents this component from being used
     */
    @Override
    protected void startInternal() throws LifecycleException {

        // just add any jar/directory set in virtual classpath to the
        // repositories list before calling start on the standard WebappLoader
        StringTokenizer tkn = new StringTokenizer(virtualClasspath, ";");
        Set<String> set = new LinkedHashSet<String>();
        while (tkn.hasMoreTokens()) {
            String token = tkn.nextToken().trim();

            if (token.isEmpty()) {
                continue;
            }

            if (log.isDebugEnabled())
                log.debug(sm.getString("virtualWebappLoader.token", token));

            if (token.endsWith("*.jar")) {
                // glob
                token = token.substring(0, token.length() - "*.jar".length());

                File directory = new File(token);
                if (!directory.isDirectory()) {
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString(
                                "virtualWebappLoader.token.notDirectory",
                                directory.getAbsolutePath()));
                    }
                    continue;
                }
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString(
                            "virtualWebappLoader.token.glob.dir",
                            directory.getAbsolutePath()));
                }
                String filenames[] = directory.list();
                Arrays.sort(filenames);
                for (int j = 0; j < filenames.length; j++) {
                    String filename = filenames[j].toLowerCase(Locale.ENGLISH);
                    if (!filename.endsWith(".jar"))
                        continue;
                    File file = new File(directory, filenames[j]);
                    if (!file.isFile()) {
                        if (log.isDebugEnabled()) {
                            log.debug(sm.getString(
                                    "virtualWebappLoader.token.notFile",
                                    file.getAbsolutePath()));
                        }
                        continue;
                    }
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString(
                                "virtualWebappLoader.token.file",
                                file.getAbsolutePath()));
                    }
                    set.add(file.toURI().toString());
                }
            } else {
                // single file or directory
                File file = new File(token);
                if (!file.exists()) {
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString(
                                "virtualWebappLoader.token.notExists",
                                file.getAbsolutePath()));
                    }
                    continue;
                }
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString(
                            "virtualWebappLoader.token.file",
                            file.getAbsolutePath()));
                }
                set.add(file.toURI().toString());
            }
        }

        for (String repository: set) {
            addRepository(repository);
        }

        super.startInternal();
    }

}

 从这个类我们可以知道他其实继承的是WebappLoader这个类,而这个WebappLoader类其实就是整个tomcat中加载jar class等文件的类,

而他的startInternal方法恰巧表明他在,启动过程中就会帮我处理好额外jar的加载

猜你喜欢

转载自584431411.iteye.com/blog/2377753