使用JNDI的方式配置javamail,如果common目录和web-inf/lib目录中都放置了mail.jar包,java虚拟机中将有两份类字节码,这两份类字节码相当于两个不同的类。[出现ClassCastException,javax.mail.Session不能转换成javax.mail.Session]在eclipse中开发这个项目时,要注意开发时环境与运行时环境,对于mail.jar包中,包含在j2ee库中了,必须手工部署到tomcat的common目录中。[类加载器问题,使用JNDI的方式配置javamail,tomcat加载类的时候使用自己的classloader,在他自己的目录中去找javax.mail.Session],你的库里面没有mail.jar,类加载器采取向上委托的方式委托给tomcat类加载器去加载。
使用如下两条语句打印出类加载器的名称:
System.out.println(initCtx.lookup("java:comp/env/mail/Session").getClass().getClassLoader().getClass().getName());
System.out.println(Session.class.getClassLoader().getClass().getName());
<Context>
<Resourcename="mail/Dog"auth="Container"
type="javax.mail.Session"
mail.smtp.host="smtp.sina.com"
mail.smtp.auth="true"
mail.transport.protocol="smtp"
/>
</Context>
try {
Context initCtx =new InitialContext();
Context envCtx =(Context) initCtx.lookup("java:comp/env");
Session session =(Session) envCtx.lookup("mail/Dog");
Message message =new MimeMessage(session);
message.setFrom(newInternetAddress("[email protected]"));
InternetAddressto[] = new InternetAddress[1];
to[0] = newInternetAddress("[email protected]");
message.setRecipients(Message.RecipientType.TO,to);
message.setSubject("ha");
message.setText("test");
//Transport.send(message);
Transporttransport = session.getTransport();
transport.connect("smtp.sina.com","itcast_test", "123456");
transport.sendMessage(message,to);
transport.close();
response.getWriter().print("ok!");
} catch(Exception e) {
// TODOAuto-generated catch block
e.printStackTrace(response.getWriter());
}
如果在你的lib下放了mail.jar,上面的Session就是这个jar中的Session类的字节码,而envCtx.lookup(“mail/Dog”);中Tomcat创建
Session的字节码却是Tomcat的lib中的,于是内存中就有两份字节码,出现同一个类的类型转换错误。
其实就,类加载器的问题。只要完全熟悉类加载器既不会束手无策了。