Advanced JSP

Download Report

Transcript Advanced JSP

Advanced Java Server Pages
Written by Dr. Yaron Kanza, Edited by permission from author by Liron Blecher
© Yaron Kanza
Agenda
• Java Beans in JSP
• Custom JSP tags - TagLib
• JSP Expression Language
Motivation
Software components (e.g. objects, data structures, primitives) are
extensively used in Web applications
For example:
 Service local variables
 Attributes forwarded in requests
 Session attributes, such as user information
 Application attributes, such as access counters

3
See tutorial at http://docs.oracle.com/javase/tutorial/javabeans/
Motivation
Standard actions are used to manipulate components: declaration,
reading from the suitable context, setting of new values
(according to input parameters), storing inside the suitable
context, etc.
Java Beans provide a specification for automatic handling and
manipulation of software components in JSP (and other
technologies...)
4
Java Beans: The Idea
Java Beans are simply objects of classes that follow some (natural)
coding convention:
• An empty constructor
• A readable property has a matching getter
• A writable property has a matching setter
Use JSP actions to access and manipulate the bean, and special
action attributes to specify the properties of the bean, e.g., its
scope
JSP programmers do not wish to write cumbersome code or class
files
5
Example 1: Access Counter
In the following example, we use a Bean to maintain an
access counter for requests to the pages
6
Counter Bean - CounterBean.java
package myUtils;
A Bean is a concept and
therefore there’s no need
to extend any class or
implement any interface!
Bean must reside
in a package
public class CounterBean {
(though it would’ve been
very Java-ish to create an
empty interface “Bean”)
private int counter;
public CounterBean() { counter = 0; }
public int getCounter() { return counter; }
public void setCounter(int i) { counter = i; }
A Bean is created by
an empty constructor
public void increment() { ++counter; }
}
Other methods can be
implemented as well
7
Counter setter
and getter
<html>
An instance named
according to the given id is
<jsp:useBean id="accessCounter"
either found in the relevant
class=“myUtils.CounterBean" scope="application"/> scope or is created
<head><title>Bean Example</title></head><body>
You could also use the type attribute in order to
instantiate a data type which is either superclass of
class or an interface that class implements
The default scope is page
<% accessCounter.increment(); %>
<h1> Welcome to Page A</h1>
Invokes getCounter()
<h2>Accesses to this application:
<jsp:getProperty name="accessCounter" property="counter"/>
</h2>
<a href="pageB.jsp">Page B</a></body>
</html>
pageA.jsp
8
Counter Bean – cont.
<html>
<head><title>Bean Example</title></head><body>
<jsp:useBean id="accessCounter"
class=“myUtils.CounterBean" scope="application"/>
<% accessCounter.increment(); %>
<h1> Welcome to Page B</h1>
<h2>Accesses to this application:
Since an instance named
according to the given id can be
found in the application scope,
no instantiation takes place
<jsp:getProperty name="accessCounter" property="counter"/>
</h2>
<a href="pageA.jsp">Page A</a></body>
</html>
pageB.jsp
A very similar JSP
9
Part of the Generated Servlet
myUtils.CounterBean accessCounter = null;
synchronized (application) {
The instance is created
and kept in the
application’s scope as
required. Note however
that accessing this
instance is out of the
synchronized scope
accessCounter = (myUtils.CounterBean)
_jspx_page_context.getAttribute("accessCounter",
PageContext.APPLICATION_SCOPE);
Similar effect to
getServletContext().getAttribute()
accessCounter = new myUtils.CounterBean();
if (accessCounter == null) {
_jspx_page_context.setAttribute("accessCounter",
accessCounter, PageContext.APPLICATION_SCOPE);
}
}
10
Similar effect to
getServletContext().setAttribute()
counter
DEMO
11
Example 2: Session Data
In the following example, we use a Bean in order to keep a user's
details throughout the session
12
Example 2: Session Data – cont.
package myUtils;
public class UserInfoBean {
private String firstName;
private String lastName;
public UserInfoBean() { firstName = lastName = null;}
public String getFirstName() {return firstName;}
public String getLastName() {return lastName;}
public void setFirstName(String string) {firstName = string;}
public void setLastName(String string) {lastName = string;}
}
UserInfoBean.java
13
Example 2: Session Data – cont.
<html>
<head><title>Information Form</title></head>
<body>
<h1>Fill in your details:</h1>
<form action="infoA.jsp" method="get"><p>
Your First Name:
<input type="text" name="firstName" /> <br/>
Your Last Name:
<input type="text" name="lastName" /><br/>
<input type="submit" /></p>
</form>
</body></html>
infoForm.html
14
Example 2: Session Data – cont.
<jsp:useBean id="userInfo" class=“myUtils.UserInfoBean" scope="session"/>
<jsp:setProperty name="userInfo" property="*"/>
The String values are converted to the
right bean’s property types..
<html>
<head><title>Page A</title></head><body>
<h1>Hello
<jsp:getProperty name="userInfo" property="firstName"/>
Match all the request
parameters to
corresponding
properties. You could
match parameters to
properties explicitly
using property=…
param=…
<jsp:getProperty name="userInfo" property="lastName"/>, You can also set
properties with
</h1>
explicit values using
property=… value=…
<h1>Have a nice session!</h1>
<h2> <a href="infoB.jsp">User Info B</a></h2>
</body></html>
15
infoA.jsp
Example 2: Session Data – cont.
<jsp:useBean id="userInfo" class=“myUtils.UserInfoBean" scope="session"/>
<jsp:setProperty name="userInfo" property="*"/>
<html>
This time the request has no parameters
<head><title>Page B</title></head><body>
so no bean properties are set
<h1>Hello
<jsp:getProperty name="userInfo" property="firstName"/>
<jsp:getProperty name="userInfo" property="lastName"/>,
</h1>
A very similar JSP
<h1>Have a nice session!</h1>
<h2> <a href="infoA.jsp">User Info A</a></h2>
</body></html>
16
infoB.jsp
Advantages of Java Beans
Easy and standard management of data
• Automatic management of bean sharing and lots more
Good programming style
• Allow standard but not direct access to members
• You can add code to the setters and getters (e.g. constraint
checks) without changing the client code
• You can change the internal representation of the data without
changing the client code
Increase of separation between business logic (written by
programmers) and HTML (written by GUI artists)
17
session
DEMO
18
Agenda
• Java Beans in JSP
• Custom JSP tags - TagLib
• JSP Expression Language
Custom JSP Tags
JSP code may use custom tags – tags that are defined and
implemented by the programmer
The programmer defines how each of the custom tags is translated
into Java code
There are two methods to define custom tags:
• Tag libraries - used in old versions of JSP
• Tag files - much simpler, introduced in JSP 2.0
20
Tag Libraries
A tag library consists of:
• Tag handlers - Java classes that define how each of the new
tags is translated into Java code
• A TLD (Tag Library Descriptor) file, which is an XML file that
defines the structure and the implementing class of each tag
• (see a tutorial at
http://java.sun.com/products/jsp/tutorial/TagLibrariesTOC.html)
21
Date Tag Example
• Goal: <mytag:date/>
The java file is placed in
webapps/myapp/WEB-INF/src/my/
We must use a package (not necessarily
named like your application) since this is a
helper class which is imported form the JSP’s
generated Servlet that is placed within a
named package
The class file is placed in
package my;
webapps/myapp/WEB-INF/classes/my/
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
Base class of
public class DateTag extends SimpleTagSupport {
tags which
public void doTag() throws JspException, IOException {
don’t handle
getJspContext().getOut().print(new java.util.Date());
the body or the
attributes
}
}
Using the JSP-context, You can also
acquire other implicit objects by
calling getSession(), getRequest()
etc…
22
DateTag.java
Date Tag Example – cont.
Set this value that indicates your
<taglib>
tag library version
<tlib-version>1.0</tlib-version><jsp-version>2.0</jsp-version>
<tag>
<name>date</name>
Name of the tag
<tagclass>my.DateTag</tagclass>
Tag’s class file in
/myapp/WEB-INF/classes/my/
<body-content>empty</body-content>
</tag>
This defined tag contains no body
</taglib>
my-taglib.tld
23
Date Tag Example – cont.
You can add here
more tags…
The prefix for this tag must appear
before the tag itself (looks like a
namespace).
The Prefix can’t be empty
<%@ taglib prefix=“mytag" uri="/WEB-INF/tags/my-taglib.tld" %>
<html><body>
<h1>Hello. The time is: <mytag:date/></h1>
</body></html>
The path could be a URL.
If you choose to use a local path, it
must begin with /WEB-INF/tags/
taglibuse.jsp
24
Taglib with Attributes
package my;
Base class of tags which do
handle attributes
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;
public class DateTag2 extends TagSupport {
private boolean isLongFormat = false;
The setter/getter methods should be
named after the attribute
(i.e. “get” + capital (<attribute>))
public void setIsLongFormat(boolean b) {
the attribute is defined as
not required so it must have
a default value
This member’s name
should be identical to the
attribute’s.
isLongFormat = b; }
public boolean getIsLongFormat() {
return isLongFormat; {
25
Attribute’s setter method
Attribute’s getter method
DateTag2.java
public int doStartTag() throws JspException {
try {
if (isLongFormat) {
Invoked when the generated Servlet starts
processing the “start tag”
pageContext.getOut().print(new java.util.Date().getTime()); }
else { pageContext.getOut().print(new java.util.Date()); }
}
catch (Exception e) {
Prints the date according to the
isLongFormat attribute
throw new JspException("DateTag: " + e.getMessage()); }
return SKIP_BODY;
}
Signals the generated Servlet there’s no
body within the tag to process
public int doEndTag() {
return EVAL_PAGE;
}}
Signals the generated Servlet to
continue executing the generated
Servlet code
26
Invoked when the generated Servlet starts
processing the “end tag”
<tag>
<name>date2</name>
Same as before, only with different names
for the tagclass
<tagclass>my.DateTag2</tagclass>
<body-content>empty</body-content>
You can put several blocks one after another
<attribute>
<name>isLongFormat</name>
<required>false</required>
The attribute is
“not required” so you have to define a
default value in DateTag2.java
</attribute>
my-taglib2.tld
</tag>
<%@ taglib prefix=“mytag" uri="/WEB-INF/tags/my-taglib2.tld" %>
<html><body>
Uses default attribute value
<h1>Hello.</h1>
<h2>The time is: <mytag:date2/></h2>
<h2>Milliseconds since the epoch : <mytag:date2 isLongFormat="true" /></h2>
</body></html>
Uses a given attribute value
27
taglibuse2.jsp
How does it work?
taglibuse2_jsp.java
Create the JspContext
taglibuse2.jsp
JSP to Java Servlet
translation
The attribute value is set
using the setter method.
The translator actually
translated the attribute
string value as it appears in
the JSP source, to a
boolean value as the Java
tag class expects it…
28
When the translation
engine first encounters
<mytag:date2> it
creates a new instance
of DateTag2 (so we
needn’t worry about
concurrency issues)
and passes it the
JspContext reference
JspContext
DateTag2
setIsLongFormat()
“Start tag” is reached
doStartTag()
“End tag” is reached
doEndTag()
Tag Files
JSP 2.0 provides an extremely simplified way of defining tags
The motivation: JSP programmers prefer not to write cumbersome
code or class files
The idea: for each custom tag, write a tag file tagName.tag that
implements the tag translation using JSP code
This way, the programmer can avoid creating tag handlers and TLD
files
29
The Simplified Example
<%= new java.util.Date() %>
date.tag
<%@ taglib prefix=“mytag" tagdir="/WEB-INF/tags/" %>
<html>
<body>
In this new mechanism we use tagdir instead
of uri we used in the old taglib
implementation
<h1>Hello. The time is: <mytag:date/></h1>
</body>
</html>
30
taguse.jsp
A new directive
The Attributes Example
<%@ attribute name="isLongFormat" required="false" %>
date3.tag
<%!private String createDate(String isLong) {
if ((isLong == null) || (isLong.equals("false"))) {
Private method
declaration
return new java.util.Date().toString();}
Default and
else { return new Long(new java.util.Date().getTime()).toString();}
isLongFormat=“false” case
} %>
<%=createDate(isLongFormat)%>
isLongFormat=“true” case
Calls the private method
The isLongFormat parameter is identified as the isLongFormat attribute because
we used the attribute directive
<%@ taglib prefix=“mytag" tagdir="/WEB-INF/tags/" %>
<html><body>
<h1>Hello.</h1>
<h2>The time is: <mytag:date3/></h2>
Default case
<h2>Milliseconds since the epoch : <mytag:date3 isLongFormat="true" /></h2>
</body></html>
isLongFormat=“true”
31
taguse3.jsp
Other Capabilities of Custom Tags
Attributes
• You can add validation mechanism for the attributes values
Tag Body
• Tag translation may choose to ignore, include or change the tag
body
32
taglib
DEMO
33
Agenda
• Java Beans in JSP
• Custom JSP tags - TagLib
• JSP Expression Language
JSP Expression Language
JSP expression language is a comfortable tool to access useful
objects in JSP
This language provides shortcuts in a somewhat JavaScript-like
syntax
An expression in EL is written as ${expr}
For example:
Hi, ${user}. <em style="${style}">Welcome</em>
Note that the EL expression does not violate the
XML syntax as opposed to <%= expression %>
35
EL Variables
JSP EL does not recognize JSP's implicit objects, but rather has its
own set
Each of these objects maps names to values
Map a parameter name to a single
• param, paramValues,
value or to multiple values
• header ,headerValues,
Map a header name to a single value
or to multiple values
• cookie,
• initParam,
• pageScope, requestScope,
• sessionScope, applicationScope
Maps a cookie name to a single value
Maps a context initialization
parameter name to a single value
For example, use the param[“x”] or param.x to get the value of the
parameter x
36
EL Variables (cont)
A variable that is not an EL implicit object is looked up at
the page, request, session (if valid) and application
scopes
That is, x is evaluated as the first non-null element
obtained by executing
pageContext.getAttribute("x"),
request.getAttribute("x"), etc.
Might be confusing. Make sure you know what you’re
accessing!
37
Object Properties
In JSP EL, Property prop of Object o is referred to as o[prop]
Property prop of Object o is evaluated as follows:
• If o is a Map object, then o.get(prop) is returned
• If o is a List or an array, then prop is converted into an integer
and o.get(prop) or o[prop] is returned
• Otherwise, treat o “as a bean”, that is: convert p to a string, and
return the corresponding getter of o, that is o.getProp()
The term o.p is equivalent to o["p"]
38
An Example
<% response.addCookie(new Cookie(“nameof",“homer"));
session.setAttribute(“homepage", new
java.net.URL("http://www.simpsons.com"));
String[] strs = {"str1","str2"};
session.setAttribute("arr", strs); %>
<html><head><title>JSP Expressions</title></head><body>
<form method="get" action="el.jsp">
<h2>Write the parameter x: <input name="x" type="text" />
<input type="submit" value="send" /></h2>
</form>
</body></html>
elcall.jsp
39
An Example
<%@ page isELIgnored="false" %>
The default value is TRUE
<html>
<head><title>EL Examples</title></head>
${…} means evaluate the
expression inside the {}
<h1>Expression-Language Examples</h1>
<h2>Parameter <code>x</code>: ${param["x"]} </h2>
cookie[“nameof”].getValue()
<h2>Cookie <code>name</code>:
header [“Connection”]
${cookie.nameof.value}</h2>
<h2>Header <code>Connection</code>:
${header.Connection} </h2>
<h2>Path of session attr. <code>homepage</code>:
${sessionScope.homepage.path}</h2>
<h2>Element <code>arr[${param.x}]</code>:
${arr[param.x]} </h2>
</body></html>
el.jsp
40
sessionScope[“homepage”].
getPath().
You can omit the
sessionScope
Only the ${param.x} is
evaluated
sessionScope
[“arr”][param[“x”]