代码改变世界

Cached JSP引发的问题与思考

2005-07-15 18:59  FantasySoft  阅读(...)  评论(...编辑  收藏

       在最近的Project中遇到了一个表面上看起来蛮奇怪的问题。具体问题是这样的,在Project中,所有跨模块的constant都会定义在一个名字叫Constants的interface中,然后在JSP里面,我们也会相应地使用到这些constant。 每当更改了Interface里面某一个constant的值的时候,在JSP中并不会反应出来,从而引起了很多混淆。由于Constants是由我来负责的,每当我修改了constant的值,都会有同事问我,到底constant的值修改了没有,为什么JSP上面没有看到更新的值。一开始我也很迷惑,后来仔细一想,应该是由于Cached JSP引起的。大家都知道,JSP的本质仍然是Servlet,一个更新的JSP文件在第一次被访问的时候,会translate(翻译)成一个Servlet,然后再被编译成.class文件,存放在固定的一个folder中,以后的访问就不必再进行编译的动作,从而提高JSP的访问速度。而JSP的编译动作通常都会在JSP本身发生改变后进行,那么JSP所依赖的class发生变化之后,是不是也会引发JSP的重新编译呢?带着这个问题,我做了一个很简单的试验。
        我在WSAD中建立了一个很简单的Dynamic Web Project,这个Project中之包含了一个JSP:Test.jsp和一个interface:Constants。具体
代码如下:

<HTML>
<HEAD>
<%@ page import="constants.Constants" %>
<TITLE>Test.jsp</TITLE>
</HEAD>
<BODY>
<P><%=Constants.NAME%></P>
</BODY>
</HTML>
                                                                          ( Test.jsp )

public interface Constants {
    
public static final String NAME = "Java"
;
}
                                                                      ( Constants.java )

编译Project并且在浏览器中访问Test.jsp,我们可以看到"Java"字样出现在屏幕上。接着,我将NAME的值从"Java"改为"Perhaps"并将
Project编译。但是不管我是以刷新页面的方式还是重启Server,都没有办法看到我期待的"Perhaps"。当然,改动一下Test.jsp就可以得到我想要的结果。从这个小小的试验可以看出,Constants这个interface的改变并没有让JSP重新编译。 试验到这里并没有结束,因为同事告诉我说,interface的改变没有引发依赖这个interface的JSP文件的编译动作,是因为interface中variable是final所致。既然有了这样的解释,我就再来验证一下。
        我新建了一个class:NewConstants并且在Test.jsp中增加了对它的访问。具体代码如下:

public class NewConstants {
    
public static final String NAME = "Fantasy"
;
}

重复以上的步骤,当我改变了NAME的值之后,譬如改为"Soft",编译Project却会引发JSP的重新编译。 由此可以得出,final关键字的
使用并非问题的关键所在。
        最后我得出的结论就是JSP是否能够自动编译,需要看所依赖的是class还是interface。如果是class,则class的改动也会相应引起JSP的编译,而interface则不会。这只是我的试验的结论,哪位朋友可以更深入地对这个问题解释一下呢?在下不胜感激了。:)