8.1 Tomcat学习(加载器)

来源:互联网 发布:国外大学 canvas 软件 编辑:程序博客网 时间:2024/05/15 22:32

java中载入器分为以下3种:


关于类加载器可以参考:http://blog.csdn.net/shakespeare001/article/details/51765353

Tomcat使用自定义载入器的原因:



Resources 和 Repositories:


Loader接口及其实现类UML图:


本章使用的Context容器是由Tomcat提供的StandardContext。

启动类的代码:

package ex08.pyrmont.startup;import ex08.pyrmont.core.SimpleWrapper;import ex08.pyrmont.core.SimpleContextConfig;import org.apache.catalina.Connector;import org.apache.catalina.Context;import org.apache.catalina.Lifecycle;import org.apache.catalina.LifecycleListener;import org.apache.catalina.Loader;import org.apache.catalina.Wrapper;import org.apache.catalina.connector.http.HttpConnector;import org.apache.catalina.core.StandardContext;import org.apache.catalina.loader.WebappClassLoader;import org.apache.catalina.loader.WebappLoader;import org.apache.naming.resources.ProxyDirContext;public final class Bootstrap {  public static void main(String[] args) {    System.setProperty("catalina.base", System.getProperty("user.dir"));    Connector connector = new HttpConnector();    Wrapper wrapper1 = new SimpleWrapper();    wrapper1.setName("Primitive");    wrapper1.setServletClass("PrimitiveServlet");    Wrapper wrapper2 = new SimpleWrapper();    wrapper2.setName("Modern");    wrapper2.setServletClass("ModernServlet");    Context context = new StandardContext();    context.setPath("/myApp");//设置context的path属性,path是访问这个web应用的URL    context.setDocBase("myApp");//设置context的docBase属性,docBase是web应用的本地路径    context.addChild(wrapper1);    context.addChild(wrapper2);    context.addServletMapping("/Primitive", "Primitive");    context.addServletMapping("/Modern", "Modern");    LifecycleListener listener = new SimpleContextConfig();    ((Lifecycle) context).addLifecycleListener(listener);    Loader loader = new WebappLoader();创建一个WebappLoader    context.setLoader(loader);    connector.setContainer(context);    try {      connector.initialize();      ((Lifecycle) connector).start();      ((Lifecycle) context).start();//Context容器启动时,同时新起一个线程来运行关联的WebappLoader      WebappClassLoader classLoader = (WebappClassLoader) loader.getClassLoader();从WebappLoader中获取一个类加载器      System.out.println("Resources' docBase: " + ((ProxyDirContext)classLoader.getResources()).getDocBase());      String[] repositories = classLoader.findRepositories();      for (int i=0; i<repositories.length; i++) {        System.out.println("  repository: " + repositories[i]);      }      System.in.read();      ((Lifecycle) context).stop();    }    catch (Exception e) {      e.printStackTrace();    }  }}
WebappLoader类start()方法执行时,主要完成以下4个工作:

createClassLoader()执行时时序图:


setRepositories()方法时序图,该方法执行后类载入器就能在WEB-INF/classes和WEB-INF/lib两个目录下载入相关类


setClassPath()的代码如下:

    private void setClassPath() {        if (!(container instanceof Context))//验证容器信息            return;        ServletContext servletContext = ((Context) container).getServletContext();        if (servletContext == null)            return;        StringBuffer classpath = new StringBuffer();//将所有Class路径存放到classpath字符串中        ClassLoader loader = getClassLoader();        int layers = 0;        int n = 0;
//循环最多执行3次(ExtensionClassLoader、ApplicationClassLoader、UserClassLoader),将所有类的URL都添加到classpath中        while ((layers < 3) && (loader != null)) {            if (!(loader instanceof URLClassLoader))                break;            URL repositories[] =                ((URLClassLoader) loader).getURLs();            for (int i = 0; i < repositories.length; i++) {                String repository = repositories[i].toString();                if (repository.startsWith("file://"))                    repository = repository.substring(7);                else if (repository.startsWith("file:"))                    repository = repository.substring(5);                else if (repository.startsWith("jndi:"))                    repository =                        servletContext.getRealPath(repository.substring(5));                else                    continue;                if (repository == null)                    continue;                if (n > 0)                    classpath.append(File.pathSeparator);                classpath.append(repository);                n++;            }            loader = loader.getParent();            layers++;        }        //将classpath和Globals.CLASS_PATH_ATTR属性关联        servletContext.setAttribute(Globals.CLASS_PATH_ATTR,                                    classpath.toString());    }



0 0