使用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。\n
首先在父類加載器中搜索 URL,然后按照為類和資源指定的順序搜索 URL。這里假定任何以 '/' 結束的 URL 都是指向目錄的。\n
如果不是以該字符結束,則認為該 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();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM