• 使用URLClassLoader类载入类实例


    Tomcat当中在接受到要调用的Servlet请求后,需要载入相应的Servlet类,然后创建Servlet类实例,从而调用Servlet类实例的service()方法

    下面实例的场景,request和response分别是一个javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例,request通过getUri()方法从ServletRequest当中获取uri

    uri格式为/servlet/servletName

    其中servletName就是所请求servlet资源的类名,针对这个资源名,调用URLClassLoader类载入相应的类实例

    public void process(Request request, Response response)
    	{
    
    		String uri = request.getUri();
    		String servletName = uri.substring(uri.lastIndexOf("/") + 1);
    		URLClassLoader loader = null;
    
    		try
    		{
    			// create a URLClassLoader
    			URL[] urls = new URL[1];
    			URLStreamHandler streamHandler = null;
    			File classPath = new File(Constants.WEB_ROOT);
    			// the forming of repository is taken from the createClassLoader
    			// method in
    			// org.apache.catalina.startup.ClassLoaderFactory
    			String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
    			// the code for forming the URL is taken from the addRepository
    			// method in
    			// org.apache.catalina.loader.StandardClassLoader class.
    			urls[0] = new URL(null, repository, streamHandler);
    			loader = new URLClassLoader(urls);
    		} catch (IOException e)
    		{
    			System.out.println(e.toString());
    		}
    		Class myClass = null;
    		try
    		{
    			myClass = loader.loadClass(servletName);
    		} catch (ClassNotFoundException e)
    		{
    			System.out.println(e.toString());
    		}
    
    		Servlet servlet = null;
    
    		try
    		{
    			servlet = (Servlet) myClass.newInstance();
    			servlet.service((ServletRequest) request, (ServletResponse) response);
    		} catch (Exception e)
    		{
    			System.out.println(e.toString());
    		} catch (Throwable e)
    		{
    			System.out.println(e.toString());
    		}
    
    	}
    

    使用java.net.URLClassLoader类来完成,该类是java.lang.ClassLoader类的一个直接子类,一旦创建了URLClassLoader类的实例之后,就可以使用它的loadClass()方法来载入Servlet类,实例化URLClassLoader类有三种方法,也就是有三个构造方法

    构造方法摘要
    URLClassLoader(URL[] urls)
    使用默认的委托父 ClassLoader 为指定的 URL 构造一个新 URLClassLoader。
    URLClassLoader(URL[] urls, ClassLoader parent)
    为给定的 URL 构造新 URLClassLoader。
    URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory)
    为指定的 URL、父类加载器和 URLStreamHandlerFactory 创建新 URLClassLoader。
    URLClassLoader
    
    
    参数:
    urls - 从其位置加载类和资源的 URL 
    抛出: 
    SecurityException - 如果安全管理器存在并且其 checkCreateClassLoader 方法不允许创建类加载器。
    另请参见:
    SecurityManager.checkCreateClassLoader()
    


    public URLClassLoader(URL[] urls)使用默认的委托父 ClassLoader 为指定的 URL 构造一个新 URLClassLoader。
    首先在父类加载器中搜索 URL,然后按照为类和资源指定的顺序搜索 URL。这里假定任何以 '/' 结束的 URL 都是指向目录的。
    如果不是以该字符结束,则认为该 URL 指向一个将根据需要下载和打开的 JAR 文件。
    如果有安全管理器,该方法首先调用安全管理器的 checkCreateClassLoader 方法以确保允许创建类加载器。

    参数中urls是一个java.net.URL  对象数组,当载入一个类时每个URL对象都指明了类载入器要到哪里查找类。

    若一个URL以“/”结尾,则表明它指向的是个目录,否则,URL默认指向一个JAR文件,根据需要载入器会下载并打开这个JAR文件。

    在这个例子当中,类载入器只需要查找一个位置,即工作目录下的webroot目录,因此,需要先创建一个只有一个URL对象的数组。

    URL类提供了一系列的构造函数,因此有很多方法可以创建URL对象。

      
    URL
    public URL(URL context,
               String spec,
               URLStreamHandler handler)
        throws MalformedURLException通过在指定的上下文中用指定的处理程序对给定的 spec 进行解析来创建 URL。如果处理程序为 null,则使用两参数构造方法进行解析。 
    
    参数:
    context - 要在其中解析规范的上下文。
    spec - 将作为 URL 解析的 String。
    handler - URL 的流处理程序。 
    抛出: 
    MalformedURLException - 如果未指定任何协议,或者找到了未知协议。 
    SecurityException - 如果安全管理器存在并且其 checkPermission 方法不允许指定流处理程序。
    另请参见:
    URL(java.lang.String, java.lang.String, int, java.lang.String), URLStreamHandler, URLStreamHandler.parseURL(java.net.URL, java.lang.String, int, int)
    

    可以将第二个参数指定为一个目录,指定第一个和第三个参数为null,这样就可以使用构造函数了,但是我们看到在URL当中,还有一个构造函数,它也接受三个参数,

    URL
    public URL(String protocol,String host,String file) throws MalformedURLException

    根据指定的 protocol 名称、host 名称和 file 名称创建 URL。使用指定协议的默认端口。
    此方法等同于调用带四个参数的构造方法,四个参数为 protocol、host、-1 和 file。 此构造方法不执行对输入的验证。


    参数:
    protocol - 要使用的协议名称。
    host - 主机名称。
    file - 主机上的文件。
    抛出:
    MalformedURLException - 如果指定了未知协议。
    另请参见:
    URL(java.lang.String, java.lang.String, int, java.lang.String)

    所以为了编译器的区别,指明第三个参数的类型

    URLStreamHandler streamHandler = null;

    new URL(null,aString,streamHandler);

    第二个参数中的字符串指明了仓库的路径,也就是查找servlet类的目录。可以使用下面的代码生成仓库

    String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
  • 相关阅读:
    艺术与科技的狂欢,云端XR支撑阿那亚2022砂之盒沉浸艺术季
    阿里云架构师金云龙:基于云XR平台的视觉计算应用部署
    圣庭医疗联合创始人谷红仓:高通量基因测序在药物研发和靶向治疗中的应用
    阿里云贾朝辉:云 XR 平台支持彼真科技呈现国风科幻虚拟演唱会
    阿里云鲍文乐:基于事件的自动化运维最佳实践
    加码企业服务,阿里云发布计算巢加速器
    阿里云张新涛:支持沉浸式体验应用快速落地,阿里云云XR平台发布
    阿里云新增三大高性能计算解决方案,助力生命科学行业快速发展
    阿里云杨红军:应用管理——云上资源DevOps最佳实践
    最多可省19%!阿里云第七代云服务器ECS中国大陆地域调价通知
  • 原文地址:https://www.cnblogs.com/wuxinliulei/p/4967101.html
Copyright © 2020-2023  润新知