580 likes | 699 Vues
Intermediate JSP. Matt Wheeler. Notes. This is a training NOT a presentation If you have questions please ask them Prerequisites Introduction to Java Stack Basic Java and XML skills Introduction to JSP Installed LDSTech IDE (or other equivalent). Overview. Review Scriptlets
E N D
Intermediate JSP Matt Wheeler
Notes • This is a training NOT a presentation • If you have questions please ask them • Prerequisites • Introduction to Java Stack • Basic Java and XML skills • Introduction to JSP • Installed LDSTech IDE (or other equivalent)
Overview • Review • Scriptlets • Expressions • Expression Language (EL) • Taglibs (JSTL, Spring, Stack) • Custom taglibs • Functions • Templating
Review • Scriptlets • Expressions • …
Scriptlets • Scriptlets are code in a JSP page (delimited with <% %>) • Will be compiled into the service method of the resulting servlet • Lets look at a simple example <% String user = request.getAttribute(“loggedInUser”); if (user != null) { %> Welcome <% } %>
Expressions • Like scriptlets but evaluate a singular Java expression and return the result • Result must be a String or convertible to a String • The syntax is as follows: <%= expression %> • For example: <%= someBean.something%> <%-- Or we could enhance our previous example --%> <% String user= request.getAttribute(“loggedInUser”); if (user != null) { %> Welcome <%= user %> <% } %>
Disadvantages • Maintenance, maintenance, maintenance • Difficult to read • Difficult to understand • Not testable • Not reusable • Difficult to refactor • Tightly coupled UI and back end code • The long version can be found here: • http://www.javaranch.com/journal/200603/Journal200603.jsp#a5
Expression Language (EL) • The expression language is meant to provide easy access within a JSP page to application data/logic in JavaBeans • EL is really the bridge between the model and the view and allows for separation of concerns • For detailed information on the JSP EL please see: http://download.oracle.com/javaee/6/tutorial/doc/gjddd.html
EL (continued) • Use of EL will help mitigate too much logic in JSP pages • EL allows access to properties and attributes of: • JavaBeans • Collections • Implicit objects //accessing a JavaBean ${someBean} ${someBean.someProperty} //accessing a value of a map with key of someKey ${someBean.map['someKey']} //accessing an implicit object (request) ${request.param}
EL (JavaBeans) • EL looks for a specified bean in all scopes (request, session, application) to resolve the expression • ${someBean.whatever} • After a bean/resource named someBean is found EL attempts to access the whatever property of the bean public class SomeBean { private String whatever; public String getWhatever() { return this.whatever; } public void setWhatever(String whatever) { this.whatever = whatever; } }
EL (Collections) • EL provides special syntax for accessing items in lists or maps • List properties can be accessed with array notation • Map items can be accessed with map or dot notation ${someBean.someList[0]} //access the first item in the list ${someBean.someMap['key']} //access the item in the map with key of 'key' ${someBean.someMap.key} //equivalently use dot notation for the same result
EL (Implicit Objects) • Objects exposed for reference in EL without any extra work or configuration from the developer • Some of these objects include: • pageContext, request, session, application, pageScope, requestScope, sessionScope, applicationScope, param, paramValues, header, headerValues, cookie, cookies, initParam, exception ${requestScope['nameOfSubmitted']} //extracts value for attribute of given name ${param['nameOfRequestParam']} //gets value off the url for the given name ${header['Accept-Language']} //find value for header with name Accept-Language ${initParam['paramName']} //gets the value of the initParam with name paramName ${pageContext.request.servletPath} //gets the servlet path from the request
EL (operators) • While most of the view logic will be in JavaBeans, EL allows for limited logic in the view • EL provides some basic operators • Logical: &&, ||, !, and, or not • Comparison: ==, !=, <, >, <=, >=, eq, ne, lt, gt, ge, le • Conditional (turnary): test ? result1 : result2 • Arithmetic: +, -, *, /, div, %, mod, E • Empty: empty, null • For operator precedence, please see: http://download.oracle.com/javaee/6/tutorial/doc/bnaik.html
EL (operators) • Some examples ${someBean.administrator && someBean.owner} ${someBean.count > 0} ${someBean.count + 1 % 2} ${someBean.count * .1 gt 50 && (someBean.payTaxes || someBean.goToJail)} ${4.0 eq (3 + 1)/1} ${someBean.map['someKey']}
EL (Evaluation) • There are multiple implicit resolvers that attempt to handle EL expressions • In general, say we are resolving ${someBean.abc} • One of the EL resolvers will, grab the first portion someBean • Will look for an implicit object of that name • Will then look for a bean of that name • Once found, it will look for a property on that name or implicit object (abc) and get that value
Lab 1 https://tech.lds.org/wiki/Intermediate_JSP#Lab_1_Expression_Language_.28EL.29
Taglibs • Primary goal of taglibs it to provide reusable functionality • Through reusable tag elements • Through functions that extend EL • Simplifies jsp pages making them more readable / maintainable by separating logic from the page’s presentation
Basic Usage • Taglibs • Declare the namespace • Use the tag • Functions • Declare the namespace • Use the function <%@ taglib prefix="web" uri="http://code.lds.org/web" %> <web:display-exception style="font-style: italic" /> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> ${fn:join(array, ', ')}
What did these save us? • Without the taglib <%@ page import="java.io.PrintWriter" %> <% String style = pageContext.getRequest().getAttributes(“exceptionStyle”); if (style == null || "".equals(style.trim())) { out.write("<pre style=\"font-style: 'Helvetica'; word-wrap: break-word; … \"> } else { writer.write("<pre style=\"" + style + "\">"); } if (pageContext.getException() == null) { out.write("No exception was available to print."); } else { pageContext.getException().printStackTrace(new PrintWriter(out)); } out.write("</pre>"); %>
What did this save us? • Without the function <%! public String join(String[] array, String separator) { if (array == null) return ""; if (separator == null) separator = ""; StringBufferbuf = new StringBuffer(); for (int i=0; i<array.length; i++) { buf.append(array[i]); if (i < array.length-1) buf.append(separator); } return buf.toString(); } %> <% String joined = join(someArray, “,”)); … %>
JSP Include • Allows you to include static or dynamic resources in a JSP page • Facilitates reuse • Allows separation into manageable pieces • Two include mechanisms available in JSP • <jsp:include page="some.jsp" /> • <%@include file="some.jsp" %>
jsp:include • Executes the included content and then includes the result in the containing JSP page //include.jsp Include me, include me! ${parentValue} //include-demo.jsp <!DOCTYPE html> <html> <body> <% String parentValue = “Something spectial"; pageContext.setAttribute("parentValue", parentValue); %> <jsp:include page="/include.jsp" /> </body> </html> //resulting output: Include me, include me!
@include (directive) • Includes the content and then executes the page • Can depend on (or conflict) with variables in the containing page • Page takes a relative url //include.jsp Include me, include me! ${parentValue} //include-demo.jsp <!DOCTYPE html> <html> <body> <% String parentValue = “Something special”; pageContext.setAttribute("parentValue", parentValue); %> <%@ include file="include.jsp" %> </body> </html> //resulting output: Include me, include me! Something special
Additional info • Also note that using the jsp:include, parameters can be passed to the included page as follows: • For more info on jsp:include: http://java.sun.com/products/jsp/syntax/1.2/syntaxref1214.html • For more info on @include: http://java.sun.com/products/jsp/syntax/1.2/syntaxref129.html#997991 <jsp:include page="/include.jsp"> <jsp:param name="parameterName" value="parameterValue " /> </jsp:include>
Demo DEMO
Common Taglibs (JSTL) • JavaServer Pages Standard Tag Library (JSTL) taglibs for many common web use cases • Core • Xml processing • Internationalization and formatting • For more info: http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/index.html
Core Tags (c:out) • c:out evaluates an expression and outputs it to the JspWriter • Allows you to provide a default <c:out value=”${someBean.someProperty}” default=”Empty” />
Core (conditionals) • c:if – executes based on the result of the test attribute • If / else equivalent (choose, when, otherwise) <c:if test="${someBean.day < 12 && someBean.hour > 2}"> Party time </c:if> <c:choose> <c:when test="${empty someBean.results}"> Display this if there are no results </c:when> <c:otherwise> Display all of the results </c:otherwise> </c:choose>
Core (Looping and Iteration) • c:forEach – loops over an array, Collection, Iterator, Enumeration, Map, String of comma separated values <c:forEach var="result" items=“${results}"> <tr> <td>${result.property1}</td><td>${result.property2}</td> </tr> </c:forEach>
Core (c:set) • Facilitates scoped variable manipulation • Sets the value of the given key in the given scope • Basically equivalent to: • Value can also be provided as the body content of the tag • If var is null (i.e. not specified – var="null" will set the attribute to the String "null") the value is removed <c:set var="key" value="${header['User-Agent']}" scope="session" /> <% pageContext.session.setAttribute("key", ${header['User-Agent']} ); %> <c:set var="key" scope="session"> <c:if test="${admin}"> Append confidential data </c:if> </c:set>
Core (c:set) • <c:set> - can also be used to set a property on a scoped object <c:set target="someBean" property="something" value="awesome" />
Core (Urls) • <c:url> - Aids in constructing correctly formatted URLs with encoding applied • <c:param> - Often used in correlation with c:url to add query parameters to the url • Note that the name and value are URL encoded by default (more later) • For example: <c:url value="http://www.whatever.com/whatever.jsp"> <c:param name=“&apathy" value="&don'tcare" /> <c:param name=“@ignorance" value="@don'tknow" /> </c:url> Result would be something like: http://www.whatever.com/whatever.jsp?%26apathy=%26don'tcare&%40ignorance=%40don'tknow;jsessionid=123456789
Core • Internationalization and Formatting Taglib • Provides support for internationalization related functions such as: • Locales, resource bundles, and base names • Xml Processing Taglib • Provides support for basic xml processing as well as xml flow control and transformations
JSTL Functions • For more info: http://download.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/
Other Useful Taglibs • Spring taglibs • http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/spring.tld.html • Stack Security taglib • JSP doesn’t defend against xss like JSF did (i.e. encode all output) • In JSF everything output with an h:outputText was encoded by default • In JSP you have to take special care to encode values that are displayed to avoid cross site scripting errors
XSS: The Problem • In short, cross-site scripting is when user entered data executes as a script instead of being displayed as text • For example: • Assume a page takes a parameter on the url and displays it • And then in your page, you put ${param.userInput} • Instead of showing on the page as text this will actually become a script in the page and be executed displaying an alert to the user • For more info: http://en.wikipedia.org/wiki/Cross-site_scripting http://whatever.com/?userInput=<script>alert('You should encode this silly.');</script>
XSS: Avoidance • To avoid this, all output (especially user entered data) should be encoded before it is displayed • Stack provides following encoding functions • Or in code • More comprehensive information: • https://tech.lds.org/wiki/Java_Stack_Security_%28Encoding%29_Tech_Tip • http://code.lds.org/maven-sites/stack/module.html?module=security-web/index.html <%@ taglib prefix="ssw" uri="http://code.lds.org/security/web" %> ${ssw:encodeHtml(param.something)} ${ssw:encodeAttribute(param.something)} ${ssw:encodeJS(param.something)} EncodingUtils.encodeHtml(String input); EncodingUtils.encodeAttribute(String input); EncodingUtils.encodeJS(String input);
Other Stack Provided Taglibs • Other taglibs • message-source • xsrfToken • display-exception
Lab 2 https://tech.lds.org/wiki/Intermediate_JSP#Lab_2_Taglibs
Custom Taglibs • Example • As the page is being processed, the tag is read, mapped to the appropriate taglib handler, and processed • Further note that hello maps to a tag class (org.lds.stack.whatever.web.HelloTag) that processes the tag <%@ taglib prefix="what" uri="http://code.lds.org/whatever/web" %> <what:hello formal="true" />
Associated tld file <?xml version="1.0" encoding="UTF-8" ?> <taglibxmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <description>Tag library for stack security web.</description> <tlib-version>1.0</tlib-version> <uri>http://code.lds.org/whatever/web</uri> <tag> <description>Spits out hello.</description> <name>hello</name> <tag-class>org.lds.stack.whatever.web.HelloTag</tag-class> <body-content>empty</body-content> <attribute> <description>Whether hello formal or informal</description> <name>formal</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
Taglib class (HelloTag) • HelloTag public class HelloTag extends BodyTagSupport { private Boolean formal; public intdoStartTag() throws JspException { try { if (formal) { String username = (String) ((HttpServletRequest) pageContext.getRequest()).getAttribute("currentUser"); pageContext.getOut().write("Good day to you " + username); } else { pageContext.getOut().write("Howdy Partner. "); } } catch (IOException e) { throw new JspException("Error: IOException while writing to client"); } return SKIP_BODY; } public void setFormal(Boolean formal) { this. formal = formal; } }
Functions • Sometimes a taglib might be overkill and all that is needed is some calculation or processing • You may not want to embed that code in the page, particularly if it is reusable • Accordingly EL functions allow you to call a static Java function to perform the processing
Functions (example) • Suppose you have a class with static methods • In a tld file define the function for use in JSP • Then in the JSP page use the function as follows public class MiscUtils { public static String concat(String one, String two) { return one+two; } } <function> <description>Concatenates two strings into one.</description> <name>concat</name> <function-class>org.lds.stack.web.util.MiscUtils</function-class> <function-signature>java.lang.Stringconcat( java.lang.String, java.lang.String )</function-signature> </function> <%@ taglib prefix="util"uri="http://code.lds.org/web" %> Hello ${util:concat(param.firstName, param.lastName)}
Tag Files (Taglets) • Simpler way to create taglibs • Better for content driven tags as opposed to complex logic tags • Tag files are not quite as powerful as the regular tag approach • However they are much simpler to create • For instance you cannot put a scriptlet in a taglet
Tag Files (Taglets) • Basically you create a .tag file in WEB-INF/tags (or a subdirectory) • The container then makes it available as a JSP taglib • It uses the name of the file as the tag name by default and the namespace points to a tagdir instead of a uri • Lets re-create our hello tag using this approach <%@ taglib prefix="tags" tagdir="WEB-INF/tags"%> <%@ taglib prefix="util" uri="http://code.lds.org/web" %>
Tag Files (Taglets) • We would create a file named hello.tag and place it in WEB-INF/tags (maybe put Hello! in it) • WEB-INF/tags/hello.tag • And that is it, believe it or not, it is ready for use <!DOCTYPE html > <%@tag description="Base Template Tag" pageEncoding="UTF-8“ %> Hello! <%@ taglib prefix="tags" tagdir="WEB-INF/tags"%> <tags:hello /> <%-- Which of course will print the very useful Hello! --%>
Tag Files (Taglets) • In out hello.tag file we can add an attribute as follows: • Then you would add some logic to the tag (hello.tag): <%-- this directive only valid in tag files --%> <@% attribute name="formal" required="false" rtexprvalue="true" %> <%-- Replace Hello! with the following --%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <c:choose> <c:when test="${formal} "> Good day ${request.currentUser} </c:when> <c:otherwise> Howdy partner </c:otherwise> </c:choose>
Tag Files • Now our new tag can be used as follows: • Notice that the tag is really just a basic jsp file, but that you can customize with the attributes specified <%@ taglib prefix="tags" tagdir="WEB-INF/tags"%> <tags:hello formal="true" /> //or <tags:hello> <jsp:attribute name="formal" value="${user.formal}" /> </tags:hello>
<jsp:doBody /> • Define a portion of the tag that can be overridden by the user of the tag • bodytest.tag • This tag could be utilized as follows: Before body content <jsp:doBody /> After body content <%@ taglib prefix="tags" tagdir="WEB-INF/tags"%> <tags:bodytest> My body content </tags:bodytest> <%-- or if you have other content in the body --%> <tags:bodytest> <jsp:attribute name="whatever" value="Good stuff"/> <jsp:body>My body content</jsp:body> </tags:bodytest>