Java 为什么tomcat返回错误HTTP500?

Java 为什么tomcat返回错误HTTP500?,java,tomcat,wicket,Java,Tomcat,Wicket,我创建了自己的会话,子类为WebSession。在Tomcat控制台中,我可以看到正在抛出异常: pqlrd.is.seguridad.SesionPQLRD cannot be cast to org.apache.wicket.Session 我的扩展网络会话: package pqlrd.is.seguridad; import org.apache.wicket.Session; import org.apache.wicket.protocol.http.WebSession; i

我创建了自己的会话,子类为
WebSession
。在Tomcat控制台中,我可以看到正在抛出异常:

pqlrd.is.seguridad.SesionPQLRD cannot be cast to org.apache.wicket.Session
我的扩展网络会话:

package pqlrd.is.seguridad;

import org.apache.wicket.Session;
import org.apache.wicket.protocol.http.WebSession;
import org.apache.wicket.request.Request;

import pqlrd.domain.AccesoWeb;
import pqlrd.domain.Usuario;

public final class SesionPQLRD extends WebSession {

public SesionPQLRD(Request request) {
    super(request);
    // TODO Auto-generated constructor stub
}

private AccesoWeb acceso;

public AccesoWeb getUsuario() {
    return acceso;
}

public void setUsuario(AccesoWeb usuario) {
    this.acceso = usuario;
}

public static SesionPQLRD getSesionPQLRD(){

    return (SesionPQLRD) Session.get();
}


public boolean estaLogeado(){
    return (acceso!=null);
}

}

仅仅因为
SessionPQLRD
is-a
WebSession
(因此
Session
)并不意味着
WebSession
is-a
SessionPQLRD
。您试图将
WebSession
强制为
SesionPQLRD
,但除非Wicket知道使用自定义会话而不是自己的会话,否则它将返回框架默认值

简而言之,你不能强迫一个超类像一个子类一样工作,除非它能真正履行子类的契约。考虑<代码>动物< /代码>接口,<代码>动物> <代码>实现,以及<代码>斑马> /代码>子类。动物可能不是斑马,而是长颈鹿

pqlrd.is.segurida.SesionPQLRD不能强制转换为org.apache.wicket.Session

这表示有东西试图将您的
SesionPQLRD
对象之一强制转换为
org.apache.wicket.Session
,而您的类不会继承或扩展该类。表面上看,这是胡说八道。根据源代码,您的类显然是
WebSession
的子类,
WebSession
Session
的子类。那么是什么原因呢

我认为最可能的解释是,您的Tomcat正在使用不同的类加载器加载两个
会话
/
WebSession
类的副本。最可能的原因是,在同一个容器中有两个Web应用程序共享对象。如果每个webapps都有自己的wicket JAR副本,其中包含
会话
WebSession
类,那么每个webapps都有自己版本的这些类。当您的一个Web应用程序尝试使用另一个Web应用程序创建的实例时,类型将不兼容,类型转换将失败

有两种简单的方法可以避免这种情况:

  • 停止在两个Web应用程序之间共享对象,或

  • 从webapps的lib目录中删除JAR文件,并将它们放在共享库目录中


确保您还重写了WicketApplication类中的newSession方法。您需要向Wicket指定它应该使用哪个会话类

public class WicketApplication extends WebApplication {

   //...

   @Override
   public Session newSession(final Request request, final Response response) {
       return new SessionPQLRD(request);
   }
}

我原以为这会有帮助,但事实并非如此@重写公共会话newSession(请求-请求,响应-响应){//TODO自动生成的方法存根//返回super.newSession(请求,响应);返回新的SesionPQLRD(请求);}因此,此方法返回SesionPQLRD而不是会话的代码是错误的。我已经换了,试试这个。但在我研究的示例中,由于java协方差,这是允许的。这令人困惑。公共静态会话getSesionPQLRD(){return(SesionPQLRD)Session.get();}类加载问题确实是最可能的原因。但是不要从应用程序的WEB-INF/lib中删除wicket的jar,而是将它们保留在那里(每个应用程序都有自己的wicket jar集),并从tomcat的lib(shared/lib,common/lib,取决于其版本)文件夹中删除任何wicket jar。Tomcat将保持类的版本分离(尽管JBoss在某些情况下不会)。或者只保留服务器版本(如Stephen C所述),但在这种情况下,请确保任何其他文件夹或应用程序中都没有其他版本。@tetsuo-“Tomcat将保持类的版本分离”。如果是这样,那么这个问题就不会发生了。我怀疑他在幕后实现了某种允许webapps共享实例的渠道。我的建议是1)不要共享实例,或者2)将所有相关的JAR放入共享库目录。当您将冲突的JAR放入common/lib和WEB-INF/lib时,就会出现此问题。Tomcat将其类加载器构造为一棵树,其中应用程序的jar是叶子,相互保护。但是common/lib是webapp类加载器的父类,因此在它们之间是共享的@铁锁-我知道所有这些,这并不直接重要。事实上,不同的Web应用程序中可能存在冲突的JAR。。。只要每个webapp加载的类的不同版本不在一起。只有当他们聚在一起时才有问题;e、 在webapp上时,可以获取其他版本的类的实例。事实上,当这种情况发生时,JAR可以具有相同的内容,而您仍然会遇到这个问题。是的,我所说的“冲突JAR”是指包含具有相同包/名称的类的JAR,不一定具有不同的内容。无论如何,由不同类加载器加载的类都是不同的类,不管它们是否相同。