问题
compile-time 与 request-time(即运行时)的区别是完全正确的。你的代码的原因
<s:if test="#session.languageId == 2"> // languageId = 2 (Chinese), 1 (English)
<fmt:setLocale value="zh" />
<%@ page trimDirectiveWhitespaces="true" %>
</s:if>
不起作用是因为<%@ page %> 是一个编译时指令,它配置JSP 如何被翻译成servlet 类,而<s:if> 标记是一个请求时JSP 标记。而且由于 JSP 必须先编译/翻译成 servlet 才能为请求提供服务,因此无法在请求时设置 <%@ page %> 指令。
解决方案
因为<%@ page %> 指令是编译时的,并且您希望提供两个不同的页面内容之一(trimDirectiveWhitespaces 分别设置为true 和false),您需要有两个相同的 JSP文件,除了一个 trimDirectiveWhitespaces true 和另一个 false。我们将这两个 JSP 文件称为trim.jsp 和notrim.jsp。
而不是在trim.jsp 和notrim.jsp 中保留相同的内容,您可以改为将其放入一个公共JSPF 文件中,这两个JSP 文件使用<%@ include %> 静态包含该文件。我们将这个通用文件称为common.jspf。
此时,如果您按照下面的示例进行操作,您应该能够将浏览器指向trim.jsp(和notrim.jsp)以查看common.jspf 的空白修剪(和未修剪)版本。
作为最后一步,您需要引入最终的、客户端可见的 JSP 文件,我们将其称为 index.jsp。 index.jsp 将根据某些请求时间条件动态包含 trim.jsp 或 notrim.jsp。在您的情况下,它是 Struts 表达式 #session.languageId == 2,但在示例中,它是 EL 表达式 ${param.languageId == 2}。
现在您可以将浏览器指向index.jsp 并查看“英文版”(未删除空格)或转到index.jsp?languageId=2 并查看“中文版”(已删除空格)。
示例
本示例中的文件说明了上述解决方案,但它们使用 JSTL 标签而不是 Struts 标签来保持通用性。
common.jspf
您希望根据语言环境对内容进行空白修剪或不进行空白修剪。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="myvar" value="myvalue" />
<c:out value="${myvar}" />
trim.jsp
common.jspf 的表示,指令空白已修剪。
<%@ page trimDirectiveWhitespaces="true"
%><%@ include file="./common.jspf" %>
notrim.jsp
common.jspf 的表示,带有指令空白未修剪。
<%@ page trimDirectiveWhitespaces="false"
%><%@ include file="./common.jspf" %>
index.jsp
客户端可见的 JSP 页面,它决定在请求时是提供 trim.jsp 还是 notrim.jsp。
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- languageId = 2 (Chinese), not 2 (English) --%>
<jsp:include page="${param.languageId == 2 ? './include_nows.jsp' : './include_ws.jsp'}" />
杂项
common.jspf 是 JSPF 而不是 JSP,因为它的唯一目的是包含在 JSP 文件中,我们不希望它可以直接访问。 (见:What is .jspf file extension? How to compile it?)
trim.jsp 和 notrim.jsp 使用 <%@ include %>(静态或编译时包含)而不是 <jsp:include>(动态或请求时包含) 包含common.jspf,因为我们希望它们表现得好像common.jspf 的内容直接出现在包含发生的位置。 (见:What's the difference between including files with JSP include directive, JSP include action and using JSP Tag Files?)
trim.jsp 和 notrim.jsp 有意将终止符 %> 放在下一行,以免在 common.jspf 之前或之后引入空格。这通常使用trimDirectiveWhitespace 完成,但这里不是一个选项,因为它也会影响common.jspf。
trim.jsp 和 notrim.jsp 必须是 JSP 文件而不是 JSPF 文件,因为它们将被动态包含在 <jsp:include> 中。但是,它们也不应该被客户端直接访问。如果您将 JSP 文件保存在 <webapp-root>/WEB-INF 下,那么这不是问题。否则,您可能希望拒绝直接访问它们。 (见:Denying direct access to jsp pages)
index.jsp 使用<jsp:include> 包含trim.jsp(或notrim.jsp)而不是<%@ include %>,因为后者是编译时包含,如解决方案中所述>,不能在请求时有条件地使用。
index.jsp 使用 <%@ page trimDirectiveWhitespace="true" %> 代替 (3) 中描述的方法以提高可读性,并且因为它不会干扰包含文件中的任何空白修剪行为。 (因为它使用动态包含,并且包含的文件有自己的空白修剪行为。)