一个ClassCastException引发的思考,在做一个简单的功能试验时,代码抛出了下面的异常
明明类的完全限定名是一样的,竟然会转换失败。。。
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SessionManager;
public class SessionTestServlet extends HttpServlet {
Map<String, HttpSession> allSessions = new HashMap<String, HttpSession>();
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(true);
if (request instanceof org.eclipse.jetty.server.Request) {
Request req = (Request) request;
SessionManager sessionManager = req.getSessionManager();
System.out.println("session manager:" + sessionManager.getClass().getName());
}
System.out.println("request class:" + request.getClass().getName());
System.out.println("response class:" + response.getClass().getName());
System.out.println("session class:" + session.getClass().getName());
if (null != session) {
System.out.println(session.getId());
if (!allSessions.containsKey(session.getId())) {
allSessions.put(session.getId(), session);
} else {
HttpSession existSession = allSessions.get(session.getId());
System.out.println(session == existSession);
}
}
session.setAttribute("testSetting", "value");
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + ":" + cookie.getValue());
}
}
}
项目背景:maven项目,使用eclipse IDE来做的开发,在pom中配置的jetty来作为服务器运行项目
<
plugin
>
<
groupId
>
org.mortbay.jetty
</
groupId
>
<
artifactId
>
jetty-maven- plugin
</
artifactId
>
<
version
>
8.1.4.v20120524
</
version
>
<
configuration
>
<
webAppConfig
>
<
contextPath
>
/${project.artifactId}
</
contextPath
>
</
webAppConfig
>
<
connectors
>
<
connector
implementation
=
"org.eclipse.jetty.server.bio.SocketConnector"
>
<
port
>
8097
</
port
>
<
maxIdleTime
>
60000
</
maxIdleTime
>
</
connector
>
</
connectors
>
<
scanIntervalSeconds
>
10
</
scanIntervalSeconds
>
</
configuration
>
</
plugin
>
运行方式:直接通过eclipse来运行jetty,启动项目
有请求到达时程序的输出如下
request class:org.eclipse.jetty.server.Request
response class:org.eclipse.jetty.server.Response
session class:org.eclipse.jetty.server.session.HashedSession
16dzhskpd3is2ahcw57bfl2dn
问题:从程序的输出来看,request对象其实是一个
org.eclipse.jetty.server.Request实例,但这里的这个if语句条件 if (request instanceof org.eclipse.jetty.server.Request) ,判断结果为false。这里的原因是什么?
这里涉及到类加载的一些内容,大致可以解释为,我们使用
org.eclipse.jetty.server.Request类时,项目加载这个类使用的ClassLoader和加载request、response所属的类对象的ClassLoader不是同一个。不同的ClassLoader加载的类之间,是不能进行转换的。所以这里的if语句条件判断为false。
下面是修改了输出代码,以及某次运行过程中的输出结果
System.
out
.println(
"org.eclipse.jetty.server.Request,loaded by "
+ org.eclipse.jetty.server.Request.
class
.getClassLoader());
System.
out
.println(
"request class:"
+ request.getClass().getName () +
",loaded by "
+ request.getClass().getClassLoader());
System.
out
.println(
"response class:"
+ response.getClass().getName () +
",loaded by "
+ response.getClass().getClassLoader());
System.
out
.println(
"session class:"
+ session.getClass().getName () +
",loaded by "
+ session.getClass().getClassLoader());
org.eclipse.jetty.server.Request,loaded by WebAppClassLoader=32261531@1ec459b
request class:org.eclipse.jetty.server.Request,loaded by org.codehaus.classworlds.RealmClassLoader@15253d5
response class:org.eclipse.jetty.server.Response,loaded by org.codehaus.classworlds.RealmClassLoader@15253d5
session class:org.eclipse.jetty.server.session.HashedSession,loaded by org.codehaus.classworlds.RealmClassLoader@15253d5
pxdj253ehd4l10i83lcd7cfi8
JSESSIONID:8c8nfkgiflfsrnv51wehpd6i
参考资料
http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html