Remember in the original MVC beer app,the Servlet controller talked to the model (Java class with business
logic),the set an attribute in request scope before forwarding to the JSP view.The JSP had to get the attribute
from the request scope,and use it to render a response to send back to the client.
Servlet(controller)code:
public void do_Post(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException{
String name = request.getParameter("userName");
request.setAttribute("name",name);
RequestDispatcher view = request.getRequestDispatcher("/result.jsp");
view.forward(request,response);
}
JSP (view) code:
<html><body>
Hello
<%= request.getAttribute("name") %>
</body></html>
what if the attribute is not a String ,but an instance of Person?
Servlet(controller)code:
public void do_Post(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException{
foo.Person p = new foo.Person();//foo.Person has getName()and setName(String) methods
p.setName("Evan");
request.setAttribute("person",p);
RequestDispatcher view = request.getRequestDispatcher("/result.jsp");
view.forward(request,response);
}
JSP (view) code:
<html><body>
<% foo.Person p = (foo.Person) request.getAttribute("person");%>
Person is:<%=p.getName() %>
</body></html>
OR using an expression:
<html><body>
Person is:<%=((foo.Person) request.getAttribute("person")).getName()%>
</body></html>
the way above,we used scripting.Now we 're with standard actions (no scripting)
JSP (view) code:
<html><body>
<jsp:useBean id="person" class="foo.Person" cope="request"/>
Person created by servlet:<jsp:getProperty name="person" property="name">
</body></html>
<jsp:useBean>can have a body!
if you put your setter code (<jsp:setProperty>)inside the body of <jsp:useBean>,the property setting is
conditional!In other words,the property values will be set only if a new beam is created ,If an existing bean
with that scope and id are found,the body of the tag will never run,so the property won't be reset from your
JSP code.If you don't specify a scope in either the <jsp:useBeam>or <jsp:getProperty>tags,the Container uses
the default of "page".
<jsp:useBean id="person" class="foo.Person" scope="page">
<jsp:setProperty name="person" property="name" value="Fred"/>
</jsp:useBean>
You can send a request parameter straight into a bean ,without scripting ,using the param attribute.The param
attribute lets you set the value of a bean property to the value of a request parameter .Just by naming the
request parameter!
<jsp:useBean id="person" type="foo.Person" class="foo.Employee">
<jsp:setProperty name="person" property="name" param="userName"/>
</jsp:useBean>
<html><body>
<form action=”TestBean.jsp”>
name: <input type=”text” name=”userName”>
ID#: <input type=”text” name=”userID”> <input type=”submit”> </form>
</body></html>
It gets even better...
all you have to do is make sure your form input field name (which becomes
the request parameter name) is the same as the property name in your bean. Then
in the <jsp:setProperty> tag, you don’t have to specify the param attribute. If you
name the property but don’t specify a value or param, you’re telling the Container to
get the value from a request parameter with a matching name.
We get to do THIS
<jsp:useBean id=”person” type=”foo.Person” class=”foo.Employee”>
<jsp:setProperty name=”person” property=”name” />
</jsp:useBean>
we change the HTML so that the input field name matches the property name.If the request parameter name matches
the bean property name, you don’t need to specify a value in the <jsp:setProperty> tag for that property.
making ALL the request parameter names match the bean property names.
We get to do this
<jsp:useBean id=”person” type=”foo.Person” class=”foo.Employee”>
<jsp:setProperty name=”person” property=”*” />
</jsp:useBean>
EL makes it easy to print nested properties... in other words, properties of properties!
This:
${person.dog.name}
Replaces this:
<%= ((foo.Person) request.getAttribute(“person”)).getDog().getName() %>
The syntax and range of the EL language are dirt simple. The tricky part is that some of EL looks like Java,
but behaves differently. You’ll see when we get to the [] operator in a moment. So you’ll find things that
wouldn’t work in Java but will work in EL, and vice-versa. Just don’t try to map Java language/syntax rules
onto EL. Think of EL as a way to access Java objects without using Java.
EL expressions are ALWAYS within curly braces, and prefi xed with the dollar sign:${person.name}
The first named variable in the expression is either an implicit object or an attribute.
${firstThing.secondThing}:the firstThing can be:EL implicit object or attribute
EL implicit object:
pageScope //it is map object.
requestScope //it is map object.
sessionScope //it is map object.
applicationScope //it is map object.
param //it is map object.
paramValues //it is map object.
header //it is map object.
headerValues //it is map object.
cookie //it is map object.
initParam //it is map object.
pageContext //of all the implicit objects ,only pageContext is not a map.It's an actual reference to the
pageContext object!pageContext is a JavaBean.
attribute:if the first thing in the EL expression ia an attribute,it can be the name of an attribute stored in
any of the four available scopes:
in page scope
in request scope
in session scope
in application scope
note:EL implicit objects are not the same as the implicit objects available to JSP scripting,except for
pageContext.
A map is a collection that holds key/value pairs ,like Hashtable and HashMap.
Using the dot (.) operator to access properties and map values.The first variable is either an implicit object
or an attribute, and the thing to the right of the dot is either a map key (if the first variable is a map) or
a bean property if the first variable is an attribute that's a JavaBean.
The [] operator is like the dot only way better. The dot operator works only when the thing on the right is a
bean property or map key for the thing on the left. That’s it. But the [ ] operator is a lot more powerful and
flexible...
If the expression has a variable followed by a bracket [ ], the left-hand variable can be a Map, a bean, a
List, or an array.
If the thing inside the brackets is a String literal (i.e., in quotes), it can be a Map key or a bean property,
or an index into a List or array.
Using the [] operator with an array.
In a Servlet:
String[] favoriteMusic = {“Zero 7”, “Tahiti 80”, “BT”, “Frou Frou”};
request.setAttribute(“musicList”, favoriteMusic);
In a JSP:
First song is: ${musicList[0]} //or First song is: ${musicList["0"]} A String index is coerced to an int for
arrays and Lists
The EL for accessing an array is the same as the EL for accessing a List.this is NOT Java. In EL, the [ ]
operator is NOT the array access operator. No, it’s just called the [ ] operator. (We swear, look it up in the
spec—it has no name! Just the symbol [ ]. Like Prince, kind of.) If it DID have a name, it would be the
array/List/Map/bean Property access operator.
Obviously ArrayList has a nice overridden toString().
For beans and Maps you can use either operator,For JavaBeans and Maps, you can use either the [] operator or
the convenient dot operator. Just think of map keys the same way you think of property names in a bean.
You ask for the key or property name, and you get back the value of the key or property.
In a Servlet:
java.util.Map musicMap = new java.util.HashMap();
musicMap.put(“Ambient”, “Zero 7”);
musicMap.put(“Surf”, “Tahiti 80”);
musicMap.put(“DJ”, “BT”);
musicMap.put(“Indie”, “Travis”);
request.setAttribute(“musicMap”, musicMap);
In a JSP:
Ambient is: ${musicMap.Ambient} //or Ambient is: ${musicMap[“Ambient”]}
eg:
In a servlet:
java.util.Map musicMap = new java.util.HashMap();
musicMap.put(“Ambient”, “Zero 7”);
musicMap.put(“Surf”, “Tahiti 80”);
musicMap.put(“DJ”, “BT”);
musicMap.put(“Indie”, “Frou Frou”);
request.setAttribute(“musicMap”, musicMap);
String[] musicTypes = {“Ambient”, “Surf”, “DJ”, “Indie”};
request.setAttribute(“MusicType”, musicTypes);
In a Jsp:
This DOES work in a JSP
Music is ${musicMap[MusicType[0]]}
The param implicit object is fine when you know you have only one parameter for that particular parameter name.
Use paramValues when you might have more than one parameter value for a given parameter name.
In the HTML form:
<form action=”TestBean.jsp”>
Name: <input type=”text” name=”name”>
ID#: <input type=”text” name=”empID”>
First food: <input type=”text” name=”food”>
Second food: <input type=”text” name=”food”>
<input type=”submit”>
</form>
In the JSP:
Request param name is: ${param.name}
Request param empID is: ${param.empID}
Request param food is: ${param.food}
First food request param: ${paramValues.food[0]}
Second food request param: ${paramValues.food[1]}
Request param name: ${paramValues.name[0]}
Getting the “host” header,We know we can do it with scripting
Host is: <%= request.getHeader(“host”) %>
But with EL, we’ve got the header implicit object
Host is: ${header[“host”]}
Host is: ${header.host}
The header implicit object keeps a Map of all the headers. Use either access operator to pass in the header
name and the value of that header will print. (Note: there’s also a headerValues implicit object for headers
with multiple values. It works just like paramValues.)
Getting the HTTP request method,We know we can do it with scripting.
Method is: <%= request.getMethod() %>
Method is: ${request.method} //this will NOT work,There IS no implicit request object!
Method is: ${requestScope.method} //There IS an implicit requestScope, but it’s NOT the request object
itself.The requestScope is NOT the request object.The implicit requestScope is just a Map of the request scope
attributes,not the request object itself!Use pageContext to get to everything else...
Method is: ${pageContext.request.method}//pageContext has a request property,request has a method property
If all you need is to print the name of a person, and you really don’t care what scope the person is in (or,
you do care, but you know there’s only one person out of all four scopes), you just use:${person.name}
Or, if you’re worried about a potential naming conflict, you can be explicit about which person you want:
${requestScope.person.name}
note:if you have a name that’s not in quotes in brackets [ ], that means it MUST adhere to Java naming rules,
right? Here, we’re OK, because person is a perfectly legal Java variable name. But that’s because somewhere,
someone said,
request.setAttribute(“person”, p);
But an attribute name is a String!
Strings don’t follow Java variable name rules!
That means someone could say:
request.setAttribute(“foo.person”, p);
And then you’d be in trouble, because THIS won’t work:
${foo.person.name}//This is certainly legal, but the Container just thinks that “foo” is an attribute
somewhere, with a “person” property. But the Container never finds a “foo” attribute.
But you’ll be so thankful for scope objects, because using a scope object lets you switch to the [ ] operator,
that can take String names that don’t conform to Java naming rules.
request.setAttribute(“foo.person”, p);
{requestScope[“foo.person”].name}
Getting Cookies and init params
We’ve looked at all the implicit objects except cookies and init params, so here we are. the request object
does NOT have a getCookie(cookieName) method! We have to get the whole Cookie array and iterate through it
ourselves.We know we can do it with scripting:
<% Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++) {
if ((cookies[i].getName()).equals(“userName”)) {
out.println(cookies[i].getValue());
}
} %>
But with EL, we’ve got the Cookie implicit object
${ cookie.userName.value}
Printing the value of the “userName” Cookie.Just give it the name, and the value comes back from the Map of
Cookie names/values.this is how you configure context (app-wide) parameters. These are NOT the same as servlet
init params.We have to configure the parameter in the DD:
<context-param>
<param-name>mainEmail</param-name>
<param-value>
[email protected]</param-value>
</context-param>
Printing the value of a context init parameter ,We know we can do it with scripting
email is: <%= application.getInitParameter(“mainEmail”) %>
And with EL, it’s even easier:
email is: ${ initParam.mainEmail}
about EL functions:
1.Write a Java class with a public static method.The method MUST be public and static, and it can have
arguments. It should (but isn’t required to) have a non-void return type. After all, the whole point is to
call this from a JSP and get something back that you can use as part of the expression or to print out.
package foo;
public class DiceRoller {
public static int rollDice() {
return (int) ((Math.random() * 6) + 1);
}
}
2.Write a Tag Library Descriptor (TLD) file.For an EL function, the TLD provides a mapping between the Java
class that defines the function and the JSP that calls the function.That way, the function name and the actual
method name can be different.Put the TLD file inside the /WEB-INF directory. Name it with a .tld xtension.maybe
you want to provide a more obvious or intuitive name to page designers using EL. No problem—the TLD says,
“This is the Java class, this is the method signature for the function (including return type) and this is the
name we’ll use in EL expressions”.
The Tag Library Descriptor (TLD) file:
<?xml version=”1.0” encoding=”ISO-8859-1” ?>
< taglib xmlns=”http://java.sun.com/xml/ns/j2ee”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee/web-
jsptaglibrary_2_0.xsd” version=”2.0”>
<tlib-version>1.2</tlib-version>
<uri>DiceFunctions</uri>
<function>
<name>rollIt</name>
<function-class>foo.DiceRoller</function-class>
<function-signature>
int rollDice()
</function-signature>
</function>
</taglib>
3.Put a taglib directive in your JSP.The taglib directive tells the Container, “I’m going to use this TLD,
and in the JSP, when I want to use a function from this TLD, I’m going to prefix it with this name...” In
other words, it lets you define the namespace. You can use functions from more than one TLD, and even if the
functions have the same name, that’s OK. The taglib directive is kind of like giving all your functions
fully-qualified names. You invoke the function by giving both the function name AND the TLD prefix. The prefix
can be anything you like.
The JSP
<%@ taglib prefix=”mine” uri=”DiceFunctions”%>
<html><body>
${mine:rollIt()}
</body></html>
4.Use EL to invoke the function.
EL artithmetic, relational, and logical operators:
Addition: +
Subtraction: -
Multiplication: *
Division: / and div
Remainder: % and mod
Logical (3)
AND: && and and
OR: || and or
NOT: ! and not
Relational (6)
Equals: == and eq
Not equals: != and ne
Less than: < and lt
Greater than: > and gt
Less than or equal to: <= and le
Greater than or equal to: >= and ge
${num > 3}