【问题标题】:Why does tomcat return error HTTP500?为什么tomcat返回错误HTTP 500?
【发布时间】:2012-03-04 15:43:49
【问题描述】:

我创建了自己的 Session,子类化 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);
}

}

【问题讨论】:

    标签: java tomcat wicket


    【解决方案1】:

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

    简而言之,您不能强制超类像子类一样行事,除非它能够真正履行子类的约定。考虑一个Animal 接口、一个ZooAnimal 实现和一个Zebra 子类。 ZooAnimal 可能不是 Zebra,它可能是 Giraffe

    【讨论】:

    • 我虽然这可以帮助。但它不是。 @Override public Session newSession(Request request, Response response) { // TODO 自动生成的方法存根 //return super.newSession(request, response);返回新的 SessionPQLRD(请求); }
    • 因此,错误是此方法返回 SessionPQLRD 而不是 Session 的代码。我已经改变了它,并会尝试这个。但是在我研究的示例中,由于 java 协方差,这是允许的。这令人困惑。 public static Session getSessionPQLRD(){ return (SesionPQLRD) Session.get(); }
    【解决方案2】:

    pqlrd.is.seguridad.SessionPQLRD 不能转换为 org.apache.wicket.Session

    这表示某些东西试图将您的SesionPQLRD 对象之一转换为org.apache.wicket.Session,并且您的类不会继承或扩展该类。从表面上看,这是无稽之谈。根据源码,你的类明明是WebSession的子类,而WebSessionSession的子类。那么是什么给出的呢?

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

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

    • 停止在两个 web 应用之间共享对象,或者

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

    【讨论】:

    • 类加载问题确实是最可能的原因。但是,不要从应用程序的 WEB-INF/lib 中删除 wicket 的 jar,而是将它们保留在那里(每个应用程序都有自己的一组 wicket jar),并从 tomcat 的 lib(shared/lib,common/lib,取决于它的版本)文件夹。 Tomcat 将保持类的版本分开(尽管 JBoss 在某些情况下不会)。或者只保留服务器版本(如 Stephen C 所述),但在这种情况下,请务必确保任何其他文件夹或应用程序中没有其他版本。
    • @tetsuo - “Tomcat 将保持类的版本分开”。如果是这样的话,那么这个问题根本不会发生。我怀疑他在幕后实现了一些允许 webapps 共享实例的通道。我的建议是 1)不要共享实例,或者 2)将所有相关的 JAR 放入共享的 lib 目录中。
    • 当你把冲突的jar放到common/lib和WEB-INF/lib中时会出现这个问题。 Tomcat 将其类加载器构建为一棵树,其中应用程序的 jar 是叶子,相互保护。但是 common/lib 是 webapp 类加载器的父类,因此在它们之间共享。 tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html
    • @tetsuo - 我知道这一切,这并不重要。实际上,您可能在不同的 web 应用程序中有冲突的 JAR ......只要每个 web 应用程序加载的不同版本的类不聚集在一起。只有聚在一起才有问题;例如在 webapp 上时可以获取其他版本的类的 instances。事实上,当这种情况发生时,JAR 可以有相同的内容,你仍然会遇到这个问题。
    • 是的,“冲突的 jars”是指包含具有相同包/名称的类的 jar,不一定具有不同的内容。无论如何,不​​同类加载器加载的类是不同的类,无论它们是否相同。
    【解决方案3】:

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

    public class WicketApplication extends WebApplication {
    
       //...
    
       @Override
       public Session newSession(final Request request, final Response response) {
           return new SessionPQLRD(request);
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-23
      • 2019-08-06
      • 1970-01-01
      • 2014-08-21
      • 2021-07-17
      • 1970-01-01
      • 2011-01-14
      相关资源
      最近更新 更多