8.1 Tomcat学习(加载器)

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值