450 likes | 609 Views
COMP 321. Week 11. Overview. Lab 8-1 Solution Tag Files Custom Tags Web Application Deployment. Lab 8-1 (“Servlets”) Solution. Tag Files. Allow creation of reusable content Better than jsp:include and c:import Don’t require adding request parameters to pass information around
E N D
COMP 321 Week 11
Overview • Lab 8-1 Solution • Tag Files • Custom Tags • Web Application Deployment
Tag Files • Allow creation of reusable content • Better than jsp:include and c:import • Don’t require adding request parameters to pass information around • Easier to read than jsp:include or c:import
Tag Files <!-- Header.tag file - placed in WEB-INF/tags directory --> <img src="images/Web-Services.jpg"><br> <!-- Home.jsp --> <%@taglibprefix="myTags"tagDir="/WEB-INF/tags"%> <html><body> <!-- This used to be <jsp:include page="Header.jsp"/> --> <myTags:Header/> Welcome to our site. </body></head>
Passing Parameters <!-- The old way --> <!-- Header.jsp file --> <img src="images/Web-Services.jpg"><br> <em><strong>${param.subTitle}</em></strong><br> <!-- Main.jsp file --> <html><body> <jsp:include page="Header.jsp"> <jsp:param name="subTitle" value="We take the string out of SOAP." /> </jsp:include> <br> Contact us at: ${initParam.mainEmail} </body></html>
Passing Parameters <!-- The better way --> <!-- Header.tag file --> <%@attributename="subTitle"required="true"rtexprvalue="true"%> <img src="images/Web-Services.jpg"><br> <em><strong>${subTitle}</em></strong><br> <!-- Main.jsp file --> <html><body> <!-- This is easier to read, and the parameters only have tag scope, too! --> <myTags:Header subTitle="We take the string out of SOAP." /> <br> Contact us at: ${initParam.mainEmail} </body></html>
Passing Parameters <!-- Use jsp:doBody for long values --> <!-- Header.tag file --> <%@tag body-content="tagdependent"%> <img src="images/Web-Services.jpg"><br> <em><strong><jsp:doBody></em></strong><br> <!-- Main.jsp file --> <html><body> <myTags:Header> We take the sting out of SOAP. OK, so it's not Jini,<br> but we'll help you get through it with the least<br> frustration and hair loss. </myTags:Header> <br> Contact us at: ${initParam.mainEmail} </body></html>
Finding Tag Files • The container looks for tag files in: • WEB-INF/tags • Subdirectories of WEB-INF/tags • META-INF/tags in library JAR files • Subdirectories of META-INF/tags in library JAR files • If the tag file is in a JAR, there must be a TLD file for it!
Sharpen Your Pencil • What do you put in the Tag File to declare that the tag has one required attribute called title, that can use an EL expression as its value? • What do you put in the Tag File to declare that the tag must NOT have a body? • Draw a Tag File in each of the locations where the Container will look for Tag Files.
Sharpen Your Pencil • What do you put in the Tag File to declare that the tag has one required attribute called title, that can use an EL expression as its value? <%@ attribute name=“title” required=“true” rtexprvalue=“true” %> • What do you put in the Tag File to declare that the tag must NOT have a body? <%@ tag body-content=“empty” %>
Sharpen Your Pencil • Draw a Tag File in each of the locations where the Container will look for Tag Files.
Custom Tag Handlers • Allow much more flexibility than Custom Tag Files • Written in Java • Come in two flavors • Classic • Simple (JSP 2.0 and above)
Creating a Simple Tag Handler • Write a class that extends SimpleTagSupport • Override the doTag() method • Create a TLD for the tag • Deploy the tag handler and TLD • Write a JSP that uses the tag
Simple Tag Handlers publicclassSimpleTagTest1 extendsSimpleTagSupport { publicvoiddoTag() throwsJspException, IOException { getJspContext().getOut().write("Lamest tag EVAR!"); } } <tag> <!-- In TLD --> <description>worst use of a custom tag</description> <name>simple1</name> <tag-class>foo.SimpleTagTest1<tag-class> <body-content>empty</body-content> </tag> <!-- In JSP --> <%@ taglib prefix="myTags" uri="simpleTags" %> <html><body> <myTags:simple1/> </body></head>
Simple Tag Handlers publicclassSimpleTagTest2 extendsSimpleTagSupport { publicvoiddoTag() throwsJspException, IOException { getJspBody().invoke(null); } } <tag> <!-- In TLD --> <description>slightly better use of a custom tag</description> <name>simple2</name> <tag-class>foo.SimpleTagTest2<tag-class> <body-content>scriptless</body-content> </tag> <!-- In JSP --> <myTags:simple2> This is the body </myTags:simple2>
Tag Handler Lifecycle • Load and instantiate class • Call setJspContext(JspContext) • If tag is nested, call setParent(JspTag) • If tag has attributes, call setters • If tag has a body, call setJspBody(JspFragment) • Call doTag()
Tags and Expressions <!-- In JSP --> <myTags:simple3> <!-- What if message isn't defined yet? --> This is the message: ${message} </myTags:simple2> publicclassSimpleTagTest3 extendsSimpleTagSupport { publicvoiddoTag() throwsJspException, IOException { getJspContext().setAttribute("message", "Wear sunscreen."); getJspBody().invoke(null); } }
Tags with Attributes <tag> <!-- In TLD --> <description>takes an attribute and iterates over body</description> <name>simple5</name> <tag-class>foo.SimpleTagTest5<tag-class> <body-content>scriptless</body-content> <attribute> <name>movieList</attribute> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag>
Tags with Attributes <table> <myTags:simple5movieList="${movieCollection}"> <tr> <td>${movie.name}</td> <td>${movie.genre}</td> </tr> </myTags:simple5> </table> publicvoidsetMovieList(List<Movie> movieList) { this.movieList = movieList; } publicvoiddoTag() throwsJspException, IOException { for(Movie movie : movieList) { getJspContext().setAttribute("movie", movie); getJspBody().invoke(null); } }
Sharpen Your Pencil • SkipPageException allows tag evaluation to be aborted without killing the rest of the page. What is the output of the tag below? • publicvoiddoTag() throwsJspException, IOException { • getJspContext().getOut().print("Message from within doTag().<br>"); • getJspContext().getOut().print("About to throw a SkipPageException"); • thrownewSkipPageException(); • } • <%@ taglib prefix="myTags"uri="simpleTags" %> • <html><body> • About to invoke a tag that throws SkipPageException <br> • <myTags:simply6/> • <br>Back in the page after invoking the tag. • </body></html>
Sharpen Your Pencil publicvoiddoTag() throwsJspException, IOException { getJspContext().getOut().print("Message from within doTag().<br>"); getJspContext().getOut().print("About to throw a SkipPageException"); thrownewSkipPageException(); } <%@ taglib prefix="myTags"uri="simpleTags" %> <html><body> About to invoke a tag that throws SkipPageException <br> <myTags:simply6/> <br>Back in the page after invoking the tag. </body></html> Result: About to invoke a tag that throws SkipPageException Message from within doTag(). About to throw a SkipPageException
Sharpen Your Pencil publicvoiddoTag() throwsJspException, IOException { getJspContext().getOut().print("Message from within doTag().<br>"); getJspContext().getOut().print("About to throw a SkipPageException"); thrownewSkipPageException(); } <html><body> This is page (A) that includes another page (B).<br> Doing the include now:<br> <jsp:include page="badTagInclude.jsp" /> <br>Back in page A after the include... </body></html> <%@ taglib prefix="myTags" uri="simpleTags" %> This is page B that invokes the tag that throws SkipPageException. Invoking the tag now:<br> <myTags:simply6/> <br>Still in page B after the tag invocation…
Sharpen Your Pencil Output: This is page (A) that includes another page (B). Doing the include now: This is page B that invokes the tag that throws SkipPageException. Invoking the tag now: Message from within doTag(). About to throw a SkipPageException Back in page A after the include…
Classic Tag Handlers <!-- No changes in JSP or TLD publicclassClassic1 extendsTagSupport { publicintdoStartTag() throwsJspException { JspWriter out = pageContext.getOut(); try{ out.println("classic tag output"); } catch(IOException e) { thrownewJspException("IOException-" + e.toString()); } returnSKIP_BODY; } }
Classic Tag Handlers // Simple tag with a body publicclassSimpleTag extendsSimpleTagSupport { publicvoiddoTag() throwsJspException, IOException { getJspContext().getOut().print("Before body."); getJspBody().invoke(null); getJspContext().getOut().print("After body."); } }
Classic Tag Handlers publicintdoStartTag() throwsJspException { out = pageContext.getOut(); try{ out.println("Before body."); } catch (IOException e) { thrownewJspException("IOException-" + e.toString()); } returnEVAL_BODY_INCLUDE; } publicintdoEndTag() throwsJspException { try{ out.println("After body."); } catch (IOException e) { thrownewJspException("IOException-" + e.toString()); } returnEVAL_PAGE; }
Classic Tag Handlers publicintdoStartTag() throwsJspException { out = pageContext.getOut(); try{ out.println("Before body."); } catch (IOException e) { thrownewJspException("IOException-" + e.toString()); } returnEVAL_BODY_INCLUDE; } publicintdoEndTag() throwsJspException { try{ out.println("After body."); } catch (IOException e) { thrownewJspException("IOException-" + e.toString()); } returnEVAL_PAGE; } How can we make the tag body repeat?
Sharpen Your Pencil // Write the classic tag handler that is the equivalent of this simple handler publicvoiddoTag() throwsJspException, IOException { String [] movies = {"Spiderman", "Saved!", "Amelie"}; for (String movie : movies) { getJspContext().setAttribute("movie", movie); getJspBody().invoke(null); } } publicclassMyIteratorTag extendsTagSupport { publicintdoStartTag() throwsJspException {} publicintdoAfterBody() throwsJspException {} publicintdoEndTag() throwsJspException {} }
Sharpen Your Pencil publicclassMyIteratorTag extendsTagSupport { String [] movies = {"Spiderman", "Saved!", "Amelie"}; intmovieCounter; publicintdoStartTag() throwsJspException { movieCounter = 0; pageContext.setAttribute("movie", movies[movieCounter]); movieCounter++; returnEVAL_BODY_INCLUDE; }
Sharpen Your Pencil publicintdoAfterBody() throwsJspException { if(movieCounter < movies.length) { pageContext.setAttribute("movie", movies[movieCounter]); movieCounter++; returnEVAL_BODY_AGAIN; } returnSKIP_BODY; } publicintdoEndTag() throwsJspException { returnEVAL_PAGE; } }
Dynamic Attributes <!-- remember our beer selection page? --> <form method="POST" action="SelectBeer.do"> <p>Select beer color:</p> <select name="color" size="1"> <option value="light">light</option> ... </select> <inputtype="submit"> </form> <!-- We would like to do this instead --> <form method="POST" action="SelectBeer.do"> <p>Select beer color:</p> <formTags:select name="color" size="1" optionsList="${applicationScope.colorList"/> <inputtype="submit"> </form>
Dynamic Attributes • <select> supports the following attributes • Core Attributes: id, class, style, title • I18N Attributes: lang, dir • Event Attributes: onclick, ondblclick, onmouseup, onmouseover, onmousemove, onmouseout, onkeypress, onkeyup, onkeydown • Form Attributes: name, disabled, multiple, size, tabindex, onfocus, onblur, onchange
Dynamic Attributes publicclassSelectTagHandler extendsSimpleTagSupport implementsDynamicAttributes { privateString name; privateList optionsList; privateMap<String, Object> tagAttrs = newHashMap<String, Object>(); publicvoidsetName(String name) { this.name = name; } publicvoidsetOptionsList(List value) { this.optionsList = value; } @Override publicvoidsetDynamicAttribute(String uri, String name, Object value) throwsJspException { tagAttrs.put(name, value); }
Dynamic Attributes publicvoiddoTag() throwsJspException, IOException { JspWriter out = ((PageContext)getJspContext()).getOut(); out.print("<select "); out.print(String.format(ATTR, "name", name)); for(String attrName : tagAttrs.keySet()) { out.print(String.format(ATTR, attrName, tagAttrs.get(attrName))); } out.println('>'); // Generate options from optionList here out.println("</select>"); } privatestaticfinalString ATTR = "%s='%s' "; }
Dynamic Attributes <tag> <!-- In TLD --> <description>Builds select tag</description> <name>select</name> <tag-class>foo.SelectTagHandler<tag-class> <body-content>empty</body-content> <attribute> <name>name</attribute> <required>true</required> </attribute> <attribute> <name>optionsList</attribute> <type>java.util.List</type> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <dynamic-attributes>true<dynamic-attributes> </tag>
WAR Files • Pack your web application in one file • Allow library dependencies to be declared and checked at deployment time • Have the same structure as your webapp, except for adding META-INF/MANIFEST.MF
Accessing Static Content • Static HTML and JSPs can only be accessed if they are not inside WEB-INF • This allows pages to be hidden from direct access, but they can still be forwarded to or included in other pages
Servlet Mapping <web-app ...> <servlet> <servlet-name>Beer</servlet-name> <servlet-class>com.example.BeerSelect</servlet-class> </servlet> <servlet-mapping> <servlet-name>Beer</servlet-name> <!-- This has NOTHING to do with the actual layout of your files --> <url-pattern>/Beer/SelectBeer.do</url-pattern> </servlet-mapping> </web-app>
Servlet Mapping - Three Types of url-pattern • Exact match: /Beer/SelectBeer.do • Directory match: /Beer/* • Extension match: *.do • Container looks for matches in the above order • If more than one pattern matches, the longest (most-specific) is used
Welcome Files • A list of welcome files can be specified in the DD • When none of the servlet mappings match, the container looks for the specified files in order • <welcome-file-list> • <welcome-file>index.html</welcome-file> • <welcome-file>default.jsp</welcome-file> • </welcome-file-list>
Welcome Files - Example • Client requests www.wickedlysmart.com/MyTestApp/search • Container checks for a servlet mapping • Container checks for MyTestApp/search/index.html • Container checks for MyTestApp/search/default.jsp
Progress Check • Due this week: • Exam 2