在接口方法上使用@Override会导致JSP编译失败

3
由于某种原因,在重写接口方法时加上@Override会导致在Weblogic中编译JSP失败。虽然所有东西都确实基于JDK 1.6.0_14运行,但是这种Java 5的问题仍然存在。
奇怪的是,JSP编译有时会失败,并指向JSP本身显然没有使用的代码的堆栈跟踪。
这里发生了什么?

Weblogic 10支持哪个版本的JSP规范? - Dilum Ranatunga
1
它只是告诉你JSP不是这项工作的正确选择。 - BalusC
2
也许Weblogic配置为使用Java 5 JDK编译JSP,或将它们编译为Java 5类文件? - Michael
有任何想法在哪里进行配置吗?这也是我想到的,但我不知道从哪里开始查找。我不是一个 Weblogic 专家。 - Stefan Kendall
根据此,使用Java 6至少需要Weblogic 10.3:http://forums.oracle.com/forums/thread.jspa?threadID=884263。 我没有看到您在使用Weblogic 10,但我没有在任何地方看到次要版本(我可能错过了)。 - Bert F
显示剩余9条评论
5个回答

3
我自己也经常遇到这种情况。在Java 6中,可以(假定)在接口实现方法上使用 @Override。但在Java 5中,这是一个错误。然而,在我的Java 6代码中,有时可以接受接口实现方法上的 @Override,有时不行。
更奇怪的是,一些IDE(例如NetBeans)可以正常工作,而IntelliJ IDEA有时可以,有时不行。但是,我发现,在任何IDE中编译代码都会忽略所报告的错误。
换句话说,问题是否出现在您的IDE中?如果是这样,请直接编译代码(必要时请使用命令行),看看会发生什么。IDE可能会报告虚假错误。

不,这是JSP编译中的一个真正问题。如果JSP(在weblogic下)触及任何覆盖接口方法的代码,JSP将无法编译和呈现。 - Stefan Kendall

3
"@Override" 应该只在源代码中保留,不应出现在字节码中。您可以确保这些类与JSP分开编译,并且仅在类路径中可用,而不是在源路径中。如果已经是这种情况,那么可能是一个与立即显示的问题不同的问题。以前,JSP编译器是一个单独的库,随服务器一起提供,与服务器运行的vm无关。WLS曾经使用过Javelin。似乎他们在10年切换到了Java Compiler API。只要您拥有Sun vm Java 1.6,它就应该正常工作。但是,如果您的堆栈跟踪中有任何“javelin”,请务必检查该角度。"

谢谢。我会寻找这个。我们大多数的WLS安装都是升级的,我相信,或者在某个时候安装了WLS9,所以这可能是罪魁祸首。 - Stefan Kendall
标枪肯定在运行。我该如何切换? - Stefan Kendall
看起来JavelinxJSPStub在weblogic.jar中。我怎么可能禁用它? - Stefan Kendall
不太确定。他们在发布说明中提到了 switch:http://download.oracle.com/docs/cd/E12840_01/wls/docs103/notes/new.html#wp1090981 - David Blevins
我知道。我也发现了:(。然而,现实似乎与文档脱节了。 - Stefan Kendall

1

一个可能的解决方法是使用appc预编译JSP。这至少可以避免这个问题。

关于“真正”的问题,我的理解是您已经升级了域,因此可以查看以下资源:

这只是一个猜测,但也许某些向后兼容标志被激活了,WebLogic继续使用“旧”方法。


我原以为JSPCompilerBackwardsCompatible的标识会解决问题,但没用。 - Stefan Kendall

0

我同意你的直觉和其他答案,WLS 在某个地方使用了 Java 5。以下是来自 Oracle/WebLogic 资源的一些有用信息。我没有 WebLogic Server 10.3 的安装包来确认这些信息:

Weblogic Server 10.3

根据这个,至少需要 Weblogic Server 10.3 才能使用 Java 6,但我没有看到任何证实这是权威信息的内容:

关于WebLogic 10.0是否支持Java 6?
回复于2009年4月9日下午12:26,针对用户user8324142的问题:
您好,
Weblogic 10不支持JDK6。
请升级到Weblogic 10.3以使用JDK 6。

检查Java版本

确定您正在使用的JDK版本 您可以通过以下命令来确定您正在使用的JDK版本:
  1. 打开命令提示符窗口并转到适当的目录:
    BEA_HOME\WL_HOME\server\bin(Windows)
    BEA_HOME/WL_HOME/server/bin(UNIX)

    在这两个路径名中,BEA_HOME表示您安装软件的目录,而WL_HOME表示wlserver_<version>。

  2. 确保您的环境设置正确,输入以下命令: setWLSenv.cmd(Windows)
    setWLSenv.sh(UNIX)

  3. 在提示符处输入以下命令: java -version

配置Java版本:

设置启动WebLogic Server的Java参数
...每次启动WebLogic Server时都必须指定Java参数。Oracle建议将该命令合并到[启动]脚本中...
如果您使用配置向导创建域,则WebLogic启动脚本位于您指定域的域名称目录中。默认情况下,此目录为BEA_HOME\user_projects\domain\domain-name,其中BEA_HOME是包含产品安装的目录,而domain-name是所选配置模板定义的域目录的名称...
将变量JAVA_HOME的值更改为JDK的位置。例如:
set JAVA_HOME=C:\bea\jdk150_03

-2
在我看来,@Override 只适用于覆盖方法而非实现方法。
因此,如果您有一个接口:
public interface MyInterface {
    public void doSomething();
}

一个实现该接口的类如下(MyClassA):
public MyClassA implements MyInterface {
    public void doSomething() {
        System.out.println("This is from MyClassA");
    }
}

接下来,下面的类继承了MyClassA并且覆盖了doSomething方法,因此我会添加@Override注解。

public MyClassB extends MyClassA implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("This is from MyClassB");
    }
}

无论是否允许,我都不会做以下操作,因为它违反了覆盖某个东西的理念 - 你正在实现而不是覆盖接口:

public MyClassA implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("This is from MyClassA");
    }
}

那么在扩展抽象类时,你不应该抛出 @Override 吗?使用 @Override 可以确保你清除了从继承树上的某个地方得到的任何东西,而不是创建一个新的定义。这种情况最为臭名昭著的例子就是创建一个错误的“equals”方法,该方法接受类型 A 而不是类型 Object 的对象。每当你依赖于继承来覆盖/实现一个方法时,这个问题就会无处不在。@Override 可以保证你正在做你认为自己在做的事情。 - Stefan Kendall
重写抽象类与实现接口是非常不同的。我的例子展示了使用接口时(而不是抽象类)。你提到了接口,而不是抽象类;也就是说,我认为你只是在实现一个接口,如果使用 @Override 注解可能会引起问题。 - jamiebarrow
如果我有一个抽象类,其中包含需要实现的方法,但它还实现了一个接口,那么使用 @Override 可以立即看到并确定哪些方法来自接口,并进行编译时检查。如果没有该注释,则无法获得这样的检查。尽管如此,在 JDK6 中,该语法是完全有效的,不应该导致我的 JSP 失败。 - Stefan Kendall
当然。但是你说了在“接口”实现方法上覆盖,但没有提到抽象类;) 我认为这导致了混淆和我的回答... - jamiebarrow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接