JSP: JavaServer Pages
Transcription
JSP: JavaServer Pages
-- 4 -JSP: JavaServer Pages Turning Servlets Inside Out 56 JavaServer Pages: Java code embedded in HTML More similar to languages such as PHP ▪ out.println(”<p>The value of pi is: ” + Math.pi); // Servlet ▪ <p>The value of pi is: <%= Math.PI %> // JSP Code is still executed by the server, not the client! ▪ Use the .jsp extension to indicate that it is not pure HTML ▪ The server translates the file into a servlet, executes it Useful when there is much more HTML than Java code JSP source: HTML code with JSP code added Output: Compilation Servlet code Execution Pure HTML jonkv@ida JSP 1: What is it? 57 Initial versions defined “JSP pages” Three different pseudo‐tags identify Java code ▪ <%= EXPRESSION %> to insert the value of an expression ▪ <% SCRIPTLET %> to insert plain Java code ▪ <%! DECLARATION %> to insert a declaration Current versions also support ”JSP documents” Based on pure XML, true tags ▪ Positive: Use XML tools, validate against standard JSP DTD, … ▪ Negative: Must use well‐formed XML (longer tags, …) ▪ <jsp:expression> EXPRESSION </jsp:expression> ▪ <jsp:scriptlet> SCRIPTLET </jsp:scriptlet> ▪ <jsp:declaration>DECLARATION</jsp:declaration> Current lab instructions use both “page” and “document”, since you may choose to use either one! jonkv@ida JSP 2: Pages and Documents 58 Must declare the contents of the page Which scripting language is used on the server side? Which document langauge is generated and seen on the client? Older JSP ”pages” (.jsp) use JSP‐specific tools The source file has a standard HTML doctype, plus a JSP pseudo‐tag declaring JSP options ▪ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <%@ page contentType="text/html;charset=UTF-8” %> <html> … </html> The source file lies, claiming to be HTML. JSP‐specific tools still know that the source file is JSP. jonkv@ida JSP 3: Language and Content Type 59 Newer JSP ”documents” (.jspx) use the XML standard Suppose the doc source file started with an HTML doctype ▪ Standard XML tools apply this to the entire document – wrong! But the client should still see an HTML DOCTYPE at the top! ▪ Solution: Use code that ”prints” the doctype! ▪ <jsp:output doctype-root-element="html” doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system=”http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd” omit-xml-declaration=”false” /> ▪ (By default, jsp:output will declare your document to be XML, which is only true for XHTML. Use omit‐xml‐declaration=”true” for ordinary HTML.) Then, the page directive must be different ▪ <%@ page …> is not well‐formed XML, can’t be used here ▪ <jsp:directive.page contentType="text/html;charset=UTF-8" /> <html>…</html> jonkv@ida JSP 4: Language and Content Type Inserting the value of an expression: In JSP pages, use <%= … %> ▪ …DOCTYPE… <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>A Simple JSP Page</title></head> <body> <p>Today is <%= new java.util.Date() %> <p>The value of pi is: <%= Math.PI %> </body> </html> <jsp:expression> new java.util.Date()</jsp:expression> Automatically converted into a servlet: ▪ public void doGet(HttpServletRequest req, HttpServletResponse res) { … res.setContentType("text/html;charset=UTF-8"); … out.print("<html>\n<head><title>…Today is "); out.print(new java.util.Date()); out.print("\n\n<p>The value…"); 60 jonkv@ida JSP 5: Inserting Expressions 61 Use scriptlets to insert complete Java code fragments Use <% … %> or <jsp:scriptlet> … </jsp:scriptlet> ▪ <p>Will you win the lottery? <% double rand = Math.random(); if (rand < 0.1) { out.println("You win!"); } else { out.println(“Reload the page to try again!"); } What’s inside <% … %> is inserted as-is in the resulting servlet! %> What’s inside <%= … %> was inserted inside out.print(…). <p>Random: <%= double r = Math.random(); out.println(r); %> out.println(”<p> Random: ” + double r = Math.random(); out.println(r);); <p>Pi is equal to <% Math.PI %> out.println(”<p>Pi is equal to ”); Math.Pi jonkv@ida JSP 6: Inserting Code Fragments Declare methods and fields Use <%! … %> or <jsp:declaration>DECLARATION</jsp:declaration> ▪ <%! private int visitsSinceServerStarted = 0; %> ▪ <%! private Connection getDatabaseConnection() { … } %> Ends up outside the doGet() method ▪ At the top level of the resulting servlet class 62 jonkv@ida JSP 7: Declaring Methods and Fields Using JSP to display a database table: ▪ <% Connection conn = …; Statement statement = conn.createStatement(); ResultSet result = statement.executeQuery(…); %> <TABLE …> <% while (result.next()) { %> <tr> <td><%= result.getString("name") %></td> <td><%= result.getString("phone") %></td> </tr> <% } %> HTML within a Java loop! Works due to the translation: ▪ while (result.next()) { out.print("<tr>\n"); out.print(" <td>"); out.print(result.getString("name")); out.print("</td>"); … } 63 jonkv@ida JSP 8: Database Example A number of variables are set up for your use: request response pageContext session ‐ an HTTPServletRequest ‐ an HTTPServletResponse ‐ a javax.servlet.jsp.PageContext ‐ a javax.servlet.http.HttpSession ‐ a javax.servlet.ServletContext application ▪ Example: Retrieve a <context‐param> from web.xml using <%= application.getInitParameter("Webmaster") %> out config ‐ a javax.servlet.jsp.JspWriter ‐ a javax.servlet.ServletConfig 64 jonkv@ida JSP 9: Implicit Variables 65 Processing Forms using JSP First, the form: ▪ <html> <body> <form method="POST" action="form.jsp"> <input type="checkbox" name="city" value="LA">LA<br> <input type="checkbox" name="city" value="Boston">Boston<br> <input type="checkbox" name="city" value="Calgary">Calgary<br> <br> <input type="radio" name="month" value="January">January<br> <input type="radio" name="month" value="June">June<br> <input type="radio" name="month" value="August">August<br> <br> <input type="submit" value="Submit"> </form> </body> </html> jonkv@ida JSP 10: Form example (HTML form) 66 Processing Forms using JSP Then, the JSP page, using request (the HTTPServletRequest): ▪ <p>The cities selected are:</p> <% final String[] cities = request.getParameterValues("city"); final String month = request.getParameter("month"); if (cities != null) { %> <ul> <% for (int i=0; i < cities.length; i++) { %> <li><%= cities[i] %> <% } %> Some of this code might be </ul> extracted into "real" classes! <% } else { %> <p>None selected.</p> <% } %> … jonkv@ida JSP 11: Form example (JSP) 67 Page directives (at the top of the file) are used to: Import necessary Java classes ▪ <%@ page import=“{package.class | package.* }” %> ▪ <jsp:directive import=“{package.class | package.* }” /> Turn on or off session handling (discussed later) ▪ … session = ”true | false” (default is true) Change buffer sizes ▪ … buffer = ”none | 8kb | sizekb” (default is 8kb) Declare whether your page is threadsafe ▪ … isThreadSafe = ”true | false” ▪ Default is true: The page may be called multiple times concurrently! jonkv@ida JSP 12: Page Directives 68 Init parameters for JSP pages Also specified within servlet tag – JSP compiled into servlet! ▪ <servlet> <servlet‐name>newuser</servlet‐name> <jsp‐file>directory/newuser.jsp</jsp‐file> … <init‐param> <param‐name>emailConfirmationRequired</param‐name> <param‐value>true</param‐value> </init‐param> <init‐param>…</init‐param> </servlet> ▪ JSP: <%= config.getInitParameter("emailConfirmationRequired") %> jonkv@ida JSP 13: Configuration -- 5 -JSP Standard Tag Library (JSTL) JavaServer Pages Standard Tag Library Custom Tag Libraries Java code and HTML don't mix very well Harder to read mixed languages with mixed indentation… ▪ <% for (int i=0; i < cities.length; i++) { %> <li><%= cities[i] %> <% } %> Also, Java is strongly typed, exceptions must be handled, … ▪ A nuisance if you prefer the ”script language” style Solution: Use tag libraries ▪ Well‐defined interface to define your own ”server‐side tags” JSTL: JavaServer Pages Standard Tag Library ▪ Standard tags, relevant for most applications ▪ Written in Java, but used as tags JSTL EL: Expression Language ▪ Calculate simple expressions within JSP, without Java code 70 jonkv@ida JSTL 1: Why? Consider a simple example… Square numbers using println to generate HTML ▪ <% for (int i = 0; i < 10; i++) { out.println(”<p>Here's a number: ” + i + ”</p>”); out.println(”<p>Its square is ” + (i*i) + ”</p>”); } %> Square numbers using mixed HTML and Java ▪ <% for (int i = 0; i < 10; i++) { %> <p>Here's a number: <%= i %></p> <p>Its square is <%= i*i %></p> <% } %> jonkv@ida JSTL 2: Square Example and <c:forEach> 71 A JSTL version: Declare the use of the "core" tag library, give it the prefix ”c” ▪ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ▪ JSPX: <html xmlns:c="http://java.sun.com/jsp/jstl/core" …> ▪ The tag library itself consists of Java code (class library must be included with the final application) Use tags from JSTL Core, prefixed by ”c:” ▪ <c:forEach var="i" begin="0" end="9"> <p>Here's a number: ${i}</p> <p>Its square is ${i*i}</p> </c:forEach> <c:forEach> creates a scoped variable ▪ Not the same as ”ordinary” Java variables ▪ Its value can be used in the Expression Language (EL), inside ${…} ▪ The Expression Language is not plain Java either! jonkv@ida JSTL 3: Square Example and <c:forEach> 72 73 Conditionals are available… ▪ <c:forEach var="i" begin="0" end="9"> <p>Here's a number: ${i}.</p> <c:if test="${i mod 2 eq 0}"> <c:if> contains a test written in the <p>The number is even.</p> Expression Language. (Not Java – </c:if> notice the operators "mod" and "eq", <p>Its square is ${i*i}.</p> though "%" and "==" are also available here.) </c:forEach> jonkv@ida JSTL 4: Conditionals, <c:if> 74 There is no "else”! But there is a choose/when/otherwise: ▪ <c:forEach var="i" begin="0" end="9"> <p>Here's a number: ${i}</p> <c:choose> <c:when test="${i mod 2 eq 0}"> <p>The number is even.</p> This is similar to switch/case in Java, in </c:when> that you can have multiple "when" tags <c:otherwise> <p>The number is odd.</p> in a "choose" tag. </c:otherwise> </c:choose> <p>Its square is ${i*i}</p> </c:forEach> jonkv@ida JSTL 5: Conditionals, <c:choose> Then, the JSP page, using JSTL tags The EL variable ”param” contains all parameter values ▪ Implicitly declared, always available ▪ Parameters are provided by forms (PUT or POST), or by URLs of the form ”something.jsp?yourname=Jonas&par1=val1&par2=val2&…” ▪ <p>Your name is: <c:out value="${param.yourname}” /></p> The ”empty” operator tests for null, empty strings, empty arrays, … ▪ <c:if test="${empty param.yourname}"> <p>You forgot to specify a name.</p> </c:if> 75 jonkv@ida JSTL 6: Forms, Revisited (JSP+JSTL) 76 Use ”paramValues” for parameters with multiple values ▪ Many checkboxes may be selected Use <c:forEach> to iterate over arrays, collections, … ▪ <c:choose> <c:when test="${empty paramValues.city}"> <p>None selected.</p> </c:when> paramValues.city is a list of cities <c:otherwise> selected in the form (in Java code: <p>The cities selected are:</p> request.getParameterValues(”city” <ul> ) <c:forEach var="city" items="${paramValues.city}"> <li><c:out value="${city}"/></li> </c:forEach> ”city” is a new scoped variable in the </ul> Expression Language </c:otherwise> </c:choose> jonkv@ida JSTL 7: Forms, Revisited (JSP+JSTL) 77 JSTL has special tags for SQL access Specify use of the SQL tag library in each JSP page/doc ▪ <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%> Specify a default DataSource used by these tags ▪ A DataSource was already configured and named in Tomcat’s config ▪ Tell JSTL you want to use this DataSource using web.xml: <context-param> <param-name>javax.servlet.jsp.jstl.sql.dataSource</param-name> <param-value>jdbc/mydb</param-value> </context-param> ▪ …where jdbc/mydb is replaced with the name you chose before! jonkv@ida JSTL/SQL 1: Databases – setup 78 Display a database table using JSTL: Use <sql:query> ‐‐ opens and closes connections as needed Returns a Result, whose ”rows” field can be iterated over ▪ <sql:query var="result">SELECT * FROM myTable; </sql:query> <TABLE …> <tbody> <c:forEach var="row" items="${result.rows}"> <tr> <td><c:out value="${row.name}"/></td> <td><c:out value="${row.phone}"/></td> </tr> </c:forEach> </tbody> </TABLE> Use <c:out /> tag to convert ”<” into ”<” etc. ▪ If the user enters name = ”<b>hello”, you will see ”<b>hello” ▪ With just plain ”<td>${row.name}</td>”, the rest of the web page would be bold… jonkv@ida JSTL/SQL 2: Queries – <sql:query> 79 Queries are always PreparedStatements Use ? as placeholder for a parameter ▪ Can be used in most places, but not (for example) in LIMIT clauses ▪ <sql:param> for most parameter values ▪ <sql:dateparam> for dates ▪ <sql:query var="result"> SELECT * FROM myTable WHERE name LIKE ’?’ <sql:param value="${param.namepattern}"/> </sql:query> jonkv@ida JSTL/SQL 3: Query Parameters 80 You may want to limit the number of result rows If you have a thousand topics, you don’t display all on one page JSTL always reads all rows resulting from a query… Solution: <sql:query var="result" startRow=”0" maxRows=”50”> … </sql:query> <c:if test=”${result.limitedByMaxRows}”> There are additional results that have not been returned. </c:if> jonkv@ida JSTL/SQL 4: Limiting Results 81 Database updates using JSTL A form to enter information for a new user ▪ <form method="post" action="addUser.jsp"> <input type="text" name="subject"></input> … </form> A JSP+JSTL page to which this information is sent ▪ <!‐‐ First ensure that parameters are correctly provided! ‐‐> <sql:update var="updateResult"> <!‐‐ Result: # rows changed ‐‐> INSERT INTO messages VALUES(NULL,?,?,NULL,?,?) <sql:param value="${param.topicid}"/> <sql:param value="${param.user}"/> <sql:param value="${user.messagesWritten + 1}"/> <sql:param value="${param.message}"/> </sql:update> jonkv@ida JSTL/SQL 5: Updates – <sql:update> Database transactions using JSTL Enclose in <sql:transaction> ▪ <sql:transaction> <sql:query> … </sql:query> <!– do something based on the query ‐‐> <sql:update> … </sql:update> <sql:update> … </sql:update> <sql:update> … </sql:update> </sql:transaction> Java (and JSP / JSTL) signal errors using exceptions ▪ If an exception occurs ”inside” <sql:transaction>, the transaction is automatically rolled back 82 jonkv@ida JSTL/SQL 6: <sql:transaction> 83 Processing and rewriting relative URLs May be necessary to add session ID for session tracking <c:url> generates a variable containing a rewritten URL Message forum example: Suppose this webapp is mapped at "/forum" <c:url var="myURL" value="/adduser" > <c:param name=“user" value="${param.name}" /> </c:url> Result: "myURL" variable may become either… ▪ "http://www.host.com/forum/adduser?user=Jonas+Kvarnstr%F6m" or ▪ "http://www.host.com/forum/adduser;jsession=ede1ac355149582fb3 4ba9e6d5a347bc?user=Jonas+Kvarnstr%F6m" Used later in the page ▪ <p><a href="${myURL}">Add user!</a> jonkv@ida JSTL: Building URLs – <c:url> 84 JSTL is just the standard tag library – many others exist You can write your own tags! ▪ http://java.sun.com/developer/technicalArticles/xml/WebAppDev3/ ▪ public class Subtract extends TagSupport { private int num1, num2; public void setNum1(int num1) { this.num1 = num1; } public void setNum2(int num2) { this.num2 = num2; } public int doStartTag() throws JspException { try { pageContext.getOut().print("Welcome to First Grade Math! "); pageContext.getOut().print("If you subtract" + num2 + " from " + num1 + ", you get: "+ (num1 ‐ num2)); } catch (IOException ioe) { … } return SKIP_BODY; } } ▪ … plus XML config JSP tag <math:sub num1="12" num2="3" /> jonkv@ida Custom Tag Libraries -- 6 -The JSTL Expression Language Expression language used within ${…} is NOT JAVA! JSP‐specific expressions where some operators are similar Translated into Java by servlet container Operators: == (or eq), != (or ne), < (or lt), > (or gt), <= (or le), >= (or ge) ▪ Operator names without <> can be used more easily in XML! Addition (+), subtraction (‐), multiplication (*), division (/ or div), remainder/modulo (% or mod) && (or and), || (or or), and ! (or not). "empty" is used to determine if a value is null or empty ▪ <c:if test=”${empty param.name}”> <p>Please specify your name.</p> </c:if> 86 jonkv@ida EL 1: Not Java; operator overview 87 Implicit variables are set up automatically to access: HTTP request parameters (such as form input) ▪ param.name or param["name"]: Single‐valued parameter "name" ▪ paramValues.name: When multiple values are possible (returns array) HTTP request headers (user‐agent, accept‐language, …) ▪ Via header and headerValues Servlet/JSP initialization parameters ▪ initParam (specified in web.xml for configuration; discussed later) Cookies ▪ cookie (cookies received in request; discussed later) The PageContext ▪ pageContext gives access to a JSP PageContext object ▪ Gives access to HttpServletRequest, ServletContext, and HttpSession ▪ ServletContext: Global configuration for the entire webapp jonkv@ida EL: Some implicit variables Variables available in EL are not Java variables <c:out value="${param}" /> ‐‐ OK <% System.out.println(param) %> ‐‐ "param" unknown! Reason: You can choose their scope Choose how they are shared and how long they live Page: Local to this page (the most restricted) Request: A single call from the browser to the server ▪ May consist of multiple pages, using e.g. <jsp:include> Session: Persists during multiple calls from the same user ▪ Will discuss sessions in detail later Application: Globally available in the web application ▪ Many sessions for this and other users) 88 jonkv@ida EL: Variables are not Java Variables Supporting scopes requires special care Use JSTL maps containing variable names and values ▪ One applicationScope map ▪ One sessionScope map per session ▪ One requestScope map per request ▪ One pageScope map per page ▪ <c:set value=”val" var=”myVar” scope=”session” /> ▪ Actually results in sessionScope.put(”myVar”, ”val”); ▪ ${sessionScope.myVar} … ▪ <c:remove var="variableName" [scope=…] /> (important for long‐lived scopes such as session/application!) Or use corresponding JSP/Java objects and methods ▪ pageContext.getAttribute(”…”) ▪ … 89 jonkv@ida EL: Variables are not Java Variables 90 Implicit scope references If you don’t specify a scope, all scopes are searched ▪ Smallest scope first ▪ <c:set value=”val" var=”myVar” scope=”session” /> ▪ ${sessionScope.myVar} ▪ Guaranteed to refer to the variable above ▪ ${myVar} ▪ Checks the page scope for myVar ▪ If not found, checks request scope ▪ If not found, checks sessionScope and returns the same myVar used above jonkv@ida EL: Variables are not Java Variables 91 Variables may be composite (objects, arrays, maps) Access using "." or [] ▪ ".foo" for identifier syntax ▪ "[foo]" when an expression (foo) identifies the ”index” Example: param is a map from parameter names to values ▪ In form.html: <FORM action="http://somesite.com/add.jsp" method="get"> <table class="mytable"> <tr><td>Name:<td><INPUT type="text" name="name"> <tr><td><INPUT type="submit" value="Send"> </table> </FORM> ▪ Fill in "Bob Jones" and press Send ▪ In add.jsp: ${param.name} is "Bob Jones" ▪ In add.jsp: ${param["name"]} is also "Bob Jones" ▪ In add.jsp: ${param["na" + "me"]} is also "Bob Jones" jonkv@ida EL: Composite variables JSTL variables have default values No null pointer exceptions (but less exact error checking) ▪ Java: If user.address is null, user.address.city NPException ▪ JSTL/EL: If user.address is null or not defined, user.address.city is null Integers default to 0 ▪ <c:forEach items=”${products}” begin=”${param.start + 10}”> ... </c:forEach> ▪ If param.start undefined (no "start=…" provided to the script), param.start is considered to be 0 Provide your own defaults in <c:out>! ▪ <c:out value="${user.address.city}" default="N/A" /> 92 jonkv@ida EL: Default Values 93 Standard EL functions available in functions tag library JSP: <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> JSPX: <html xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" … > ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ length (of array, Collection, String, …) toUpperCase, toLowerCase substring, substringAfter, substringBefore trim replace indexOf, startsWith, endsWith, contains, containsIgnoreCase split, join escapeXml jonkv@ida EL: Standard Functions 94 A JSP page, test.jsp, contains the following: ▪ ${param.a} > ${param.b}: ${param.a > param.b} ${param.a} > 13: ${param.a > 13} We call it: test.jsp?a=2&b=13 ▪ 2 > 13: true 2 > 13: false Why? All query parameters are stored as strings! ▪ Converted to numbers when required ▪ The string “2” is greater than the string “13” The string “2” is converted to the number 2 which is not greater than 13 jonkv@ida EL: Variable Types…