5.2 The <c:import> ActionThe <jsp:include> action lets you encapsulate functionality in one JSP page and include it in another; for example, you could include company headers and footers, like this: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> ... <body> < jsp:include page='/WEB-INF/jsp/company/companyHeader.jsp'/> <%-- Page content goes here--%> < jsp:include page='/WEB-INF/jsp/company/companyFooter.jsp'/> </body> </html> The preceding JSP page includes JSP files specified with context-relative URLs that reside in a /WEB-INF/jsp/company directory. [2] You can also specify request parameters for included files with the <jsp:param> action, like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> ... <body> < jsp:include page='/WEB-INF/jsp/company/companyHeader.jsp'> < jsp:param name='user' value='<%=session.getAttribute("userName")%>'/> </jsp:include> <%-- Page content goes here--%> <jsp:include page='/WEB-INF/jsp/company/companyFooter.jsp'/> </body> </html> In the preceding code fragment, companyHeader.jsp is passed a request parameter named user that references a user name stored in session scope. As handy as the <jsp:include> action is, its capabilities are limited; for example, it cannot import external resources or resources stored in foreign contexts. The JSTL <c:import> action can do all those things and more. Table 5.2 lists the features supported by <jsp:include> and <c:import>. Table 5.2. <jsp:include> vs. <c:import>
You can use <c:import> instead of <jsp:include> to import resources in the same Web application; for example, you could import company headers and footers like this: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> ... <body> < c:import url='/WEB-INF/jsp/company/companyHeader.jsp'/> <%-- Page content goes here--%> < c:import url='/WEB-INF/jsp/company/companyFooter.jsp'/> </body> </html> JSTL also provides a <c:param> action that you can use just like <jsp:param>; for example, the code fragment listed on page 202 could be rewritten like this: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> ... <body> < c:import url='/WEB-INF/jsp/company/companyHeader.jsp'> < c:param name='user' value='${sessionScope.userName}'/> </c:import> <%-- Page content goes here--%> < c:import url='/WEB-INF/jsp/company/companyFooter.jsp'/> </body> </html> The <c:import> action applies URL rewriting as necessary to maintain sessions if cookies are disabled on the client. The <c:import> action has two syntaxes; here's one of them: [3]
<c:import url [context] [charEncoding] [var] [scope]> <c:param> actions </c:import> The url attribute is similar to the <jsp:include> action's page attribute ”both attributes specify a URL, either context-relative or page-relative ”whose content is included in the JSP page in which the respective actions reside. But the URL specified with the <c:import> url attribute can also represent an external resource or a resource that resides in a foreign context. To access an external resource, you simply specify an absolute URL for the url attribute. To access a resource in a foreign context, you must specify a value for the context attribute that represents a context path for the foreign context in conjunction with the url attribute, which represents a context-relative path to the resource. For example, from another Web application in the same website, you could import test_2.jsp shown in Figure 5-1 on page 199 like this: <c:import url='/jsp/test_2.jsp' context='/core-jstl'/> See "Accessing External Resources" on page 210 for an example of importing external resources and "Accessing Resources in Foreign Contexts" on page 215 for an example of importing resources from a foreign context. The charEncoding attribute specifies a character encoding, such as UTF-8 , that <c:import> uses to decode characters that it imports; [4] for example, you could specify a character encoding of Shift_JIS to import a URL whose content is in Japanese like this:
<c:import url='http://www.tcvb.or.jp/jp/index-j.htm' charEncoding ='Shift_JIS'/> By default, the <c:import> action writes the content of the URL that it imports to the current JspWriter ; however, if you specify the var attribute, <c:import> will create a scoped variable whose name is specified with that attribute. That scoped variable references a string that contains the content that <c:import> imports. By default, <c:import> stores that scoped variable in page scope, but you can specify the scope attribute to store it in page, request, session, or application scope. You can also use <c:import> with this syntax: <c:import url [context] [charEncoding] varReader> body content that uses the varReader scoped variable: <c:param> actions not allowed </c:import> The preceding syntax is the same as the first syntax, except that the var and scope attributes are replaced by a varReader attribute and <c:param> actions are disallowed in the body of the <c:import> action. The varReader attribute specifies the name of a reader that references the imported content. That reader is only accessible in the body of the <c:import> action, and because it must be available immediately after the <c:import> start tag, <c:param> actions are not allowed in the body of the <c:import> action. This syntax is provided for efficiency because the imported content is not stored in a string but instead is accessed directly with a reader. Figure 5-2 shows a JSP page that uses <c:import> with the preceding syntax to display the content of a URL. Figure 5-2. Using <c:import> with a Reader
The JSP page shown in Figure 5-2 uses a custom action nested in the body of a <c:import> action. That custom action uses a reader created by <c:import> to directly access the content of a URL. That JSP page is listed in Listing 5.1. The preceding JSP page uses <c:import> to read the content of another JSP page named someContent.jsp , which resides in the same directory as the preceding JSP page. The varReader attribute is specified so that <c:import> will create a reader and store it in page scope. The custom action ”<core-jstl:displayUrlContent> ”uses the reader to display the imported content. Notice that the custom action has a reader attribute that specifies the name of the reader. That attribute's value must be the same as the value specified for the enclosing <c:import> action's varReader attribute. Listing 5.1 Using a Custom Action That Uses the Optional Reader Created by <c:import><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title> Using the Reader Created by <c:import> </title> </head> <body> <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%@ taglib uri='WEB-INF/core-jstl.tld' prefix='core-jstl' %> <c:import url='someContent.jsp' varReader='reader'> <core-jstl:displayUrlContent reader='reader'/> </c:import> </body> </html> The JSP page imported by the preceding JSP page is listed in Listing 5.2. Listing 5.2 someContent.jspCONTENT The tag handler for the <core-jstl:displayUrlContent> custom action is listed in Listing 5.3. The preceding tag handler's doStartTag method invokes the PageContext.findAttribute method to locate the reader created by an enclosing <c:import> action to read each character and write it to the current JspWriter . Note Unlike other JSTL actions, such as the iteration, SQL, and internationalization actions, the URL actions do not expose any classes or interfaces. Listing 5.3 WEB-INF/classes/tags/DisplayUrlAction.javapackage tags; import java.io.Reader; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.*; public class DisplayUrlAction extends TagSupport { private String readerName; public void setReader(String readerName) { this.readerName = readerName; } public int doStartTag() throws JspException { int character; Reader reader = (Reader) pageContext.findAttribute(readerName); if(reader == null) { throw new JspException("You can only use this action " + "in the body of a " + "<c:import> " + "action that exposes a reader "); } try { while((character = reader.read()) != -1) pageContext.getOut().print((char)character); } catch(java.io.IOException ex) { throw new JspException(ex.getMessage()); } return SKIP_BODY; } } If the <c:import> tag handler's class had been exposed, the preceding tag handler could check to make sure that it had an <c:import> ancestor action and could also obtain a reference to the reader that the enclosing <c:import> action created. However, because the URL actions do not expose any classes or interfaces, you must explicitly pass the tag handler the name of the reader created by its enclosing <c:import> action and the tag handler must also check to make sure that the reader is not null . |