首页 > 代码库 > Jetty类加载
Jetty类加载
ssloader,系统classloader作为它的父亲。在Java中这样的层级关系是正常的,然而servlet规范复杂化了层级关系,因为它要求:
1)包含在WEB-INF/lib或者WEB-INF/classes中的类优先于在父classloader上的类。这和通常的Java 2 classloader的行为是对立的。
2)系统类例如java.lang.String被从webapp优先权中排除,你不可以使用在WEB-INF/lib或者WEB-INF/classes中的类代替它们。不幸的是规范没有清晰地陈述什么类是系统类,是否所有javax类都应该作为系统类对待。
3)Server实现类像Server应该被从web应用隐藏,在任何classloader中都不应该是可用的。不幸的是规范没有陈述什么类是Server类,是否像Xerces解析器这样的公共库应该被作为实现类对待。
配置Webapp Classloading
Jetty提供配置选项控制上面列出的3个webapp类加载问题。
你能通过在WebAppContext上的几个方法配置webapp classloader。你能直接调用这几个方法,或者你能通过上下文XML文件配置。你不能从jetty-web.xml设置这些方法,因为它会在classloader配置被设置之后执行。
控制Webapp Classloader优先级
方法org.eclipse.jetty.webapp.WebAppContext.setParentLoaderPriority(boolean)允许你控制优先级。如果你设置它到false(默认),Jetty使用标准webapp类加载优先级。然而,如果在这种模式下一些被其它类依赖的类被父加载器加载(归因于下面的系统类设置),歧义可以出现于webapp和系统classloader版本都能结束被加载。
如果设置到true,Jetty使用通常的JavaSE类加载优先级,并给优先级到父/系统classloader。这避免了一个webapp内的一个类的多版本问题,但是父/系统加载器提供的版本必须是对所有webapp都正确的版本。
设置系统类
你能调用方法org.eclipse.jetty.webapp.WebAppContext.setSystemClasses(String Array)或者org.eclipse.jetty.webapp.WebAppContext.addSystemClass(String)来控制哪些类是系统类。
1)一个web应用能看到一个系统类;
2)一个WEB-INF类不能替代一个系统类。
默认系统类包括:
java.
Java SE classes (per servlet spec v2.5 / SRV.9.7.2)。
javax.
Java SE classes (per servlet spec v2.5 / SRV.9.7.2)。
org.xml.
被javax.xml需要。
org.w3c.
被javax.xml需要。
org.eclipse.jetty.continuation.
webapp能看见但不能改变continuation类。
org.eclipse.jetty.jndi.
webapp能看见但不能改变命名类。
org.eclipse.jetty.jaas.
webapp能看见但不能改变JAAS类。
org.eclipse.jetty.websocket.
WebSocket是一个Jetty扩展。
org.eclipse.jetty.servlet.DefaultServlet
webapp能看见但不能改变默认servlet。
绝对类名是合法的,名称以.结束被作为包名,名称以-开始作为否定匹配并必须在任何封闭的包之前列出。
设置Server类
你能调用方法org.eclipse.jetty.webapp.WebAppContext.setServerClasses(String Array)或者org.eclipse.jetty.webapp.WebAppContext.addServerClass(String)控制哪个类是Server类。
1)web应用不能看到Server类;
2)WEB-INF类能替代Server类。
默认Server类包括:
-org.eclipse.jetty.continuation.
不隐藏continuation类。
-org.eclipse.jetty.jndi.
不隐藏命名类。
-org.eclipse.jetty.jaas.
不隐藏jaas类。
-org.eclipse.jetty.servlets.
不隐藏servlet类,如果提供了。
-org.eclipse.jetty.servlet.
不隐藏默认servlet类。
-org.eclipse.jetty.servlet.listener.
不隐藏listeners
-org.eclipse.jetty.websocket.
不隐藏websocket扩展
org.eclipse.jetty. Do hide all other Jetty classes.
隐藏其它所有Jetty类。
增加额外的类路径到Jetty
你能增加额外的类路径到Jetty,有下面几种方式:
使用start.jar
如果你正在使用start.jar,在启动时jetty运行时自动从顶层$jetty.home/lib文件夹加载可选的Jar。默认的设置包括:
1)增加Jar在$jetty.home/lib/ext下到系统类路径。你能放附加的Jar在这儿。
2)增加文件夹$jetty.home/resources到类路径(可以包含类路径或者其它资源)。
3)通过命令行参数path增加单个的路径定义。
使用extraClasspath()方法
你能增加一个附加的类路径到一个上下文classloader,通过使用一个逗号分隔的路径列表调用 org.eclipse.jetty.webapp.WebAppContext.setExtraClasspath(String)。你能通过上下文XML文件做到,如下;
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> ... <Set name="extraClasspath>../my/classes,../my/jars/special.jar,../my/jars/other.jar> </Set> ...
使用自定义webapp classloader
如果上面提供的方式都不满足你的需求,你能为你的webapp提供一个自定义的classloader。我们推荐,但不要求,你的自定义加载器继承自WebAppClassLoader。你为你的应用配置classloader如下:
MyCleverClassLoader myCleverClassLoader = new MyCleverClassLoader(); ... WebAppContext webapp = new WebAppContext(); ... webapp.setClassLoader(myCleverClassLoader);
你也能在一个上下文xml文件中完成配置。
使用自定义ClassLoader启动Jetty
如果你使用自定义classloader启动Jetty server,考虑Jetty类对系统类加载器不是可用的,仅对你的自定义类加载器可用,当WebAppClassLoader进入时,你可能遇到类加载问题。默认WebAppClassLoader使用系统类加载器作为他的父亲,因此存在问题。这是容易修复的,采用如下方式:
context.setClassLoader(new WebAppClassLoader(this.getClass().getClassLoader(), context));
或者
context.setClassLoader(new WebAppClassLoader(new MyCustomClassLoader(), context));