Problem
You are completely correct in the compile-time versus request-time (i.e. runtime) distinction. The reason your code
<s:if test="#session.languageId == 2"> // languageId = 2 (Chinese), 1 (English)
<fmt:setLocale value="zh" />
<%@ page trimDirectiveWhitespaces="true" %>
</s:if>
does not work is because the <%@ page %>
is a compile-time directive which configures how the JSP gets translated into a servlet class, whereas the <s:if>
tag is a request-time JSP tag. And since a JSP must be compiled/translated into a servlet before it can serve a request, it is impossible to set the <%@ page %>
directive at request-time.
Solution
Because the <%@ page %>
directive is compile-time, and you want to serve one of two different page contents (with trimDirectiveWhitespaces
set to true
and false
, respectively), you need to have two identical JSP files, except one with trimDirectiveWhitespaces
true
and the other one false
. Let's call the two JSP files trim.jsp
and notrim.jsp
.
And rather than keeping the same content in trim.jsp
and notrim.jsp
, you can instead put it into a common JSPF file which the two JSP files statically include using <%@ include %>
. Let's call this common file common.jspf
.
At this point if you're following the example below, you should be able to point your browser at trim.jsp
(and notrim.jsp
) to see the whitespace-trimmed (and untrimmed) version of common.jspf
.
As a final step, you need to introduce your final, client-visible JSP file, which we'll call index.jsp
. index.jsp
will dynamically include either trim.jsp
or notrim.jsp
based on some request-time condition. In your case it's the Struts expression #session.languageId == 2
, but in the example it's the EL expression ${param.languageId == 2}
.
Now you can point your browser at index.jsp
and see the "English version" (no whitespace trimmed) or go to index.jsp?languageId=2
and see the "Chinese version" (whitespace trimmed).
Example
The files in this example illustrate the Solution outlined above, but they use JSTL tags instead of Struts tags to keep it generic.
common.jspf
Contents which you want to be whitespace-trimmed or not based on the locale.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="myvar" value="myvalue" />
<c:out value="${myvar}" />
trim.jsp
A representation of common.jspf
with directive whitespace trimmed.
<%@ page trimDirectiveWhitespaces="true"
%><%@ include file="./common.jspf" %>
notrim.jsp
A representation of common.jspf
with directive whitespace not trimmed.
<%@ page trimDirectiveWhitespaces="false"
%><%@ include file="./common.jspf" %>
index.jsp
Client-visible JSP page which decides whether to serve trim.jsp
or notrim.jsp
at request time.
<%@ 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'}" />
Miscellany
common.jspf
is a JSPF instead of a JSP because its only intention is to be included from a JSP file and we don't want it acessible directly. (See: What is .jspf file extension? How to compile it?)
trim.jsp
and notrim.jsp
use <%@ include %>
(static, or compile-time include) instead of <jsp:include>
(dynamic, or request-time include) to include common.jspf
since we want them to behave as if the contents of common.jspf
appeared directly where the include happens. (See: What's the difference between including files with JSP include directive, JSP include action and using JSP Tag Files?)
trim.jsp
and notrim.jsp
intentionally put the terminator %>
on the next line to not introduce whitespace before or after common.jspf
. This is normally done with trimDirectiveWhitespace
but that's not an option here since it will affect common.jspf
as well.
trim.jsp
and notrim.jsp
MUST be JSP files and not JSPF files, because they are to be included dynamically with <jsp:include>
. However, they too, are not supposed to be accessed directly by the client. If your keep your JSP files under <webapp-root>/WEB-INF
then this is not a problem. Otherwise, you may want to deny direct access to them. (See: Denying direct access to jsp pages)
index.jsp
uses <jsp:include>
to include trim.jsp
(or notrim.jsp
) instead of <%@ include %>
because the latter is a compile-time include which, as explained in Solution, cannot be used applied conditionally at request time.
index.jsp
uses <%@ page trimDirectiveWhitespace="true" %>
instead of the method described in (3) for readability and because it does not interfere with any whitespace trimming behavior in included files. (Because it uses a dynamic include and the included files have their own whitespace trimming behavior.)