一个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