开发环境:
Eclipse IDE for Java EE Developers(下载地址)
struts-2.3.1.2(下载地址)
apache-tomcat-6.0.35(下载地址)
结果图:



要学习Struts对ServletAPI的使用以及OGNL,首先要了解两个东西ValueStack和ActionContext
(用弄懂今天的内容,有必要读懂下面的这些讲解内容)

(以下文字内容转载自百度文库文章“浅析struts2中的OGNL和 ValueStack”)有部分缩减
ActionContext
它是Action运行的上下文环境,Action的多项设置都存放在此,我们每一次Action调用都会创建一个ActionContext 。通常情况下我们可以通过静态方法getContext()来获得Action上下文,进而进行其它操作,比如说可以得到request session application等。
ValueStack
Struts 2要依赖于ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当Struts2接收个.action的请求后,会先建立Action类的对象实例,并且将Action类的对象实例压入ValueStack对象中(实际上,ValueStack对于相当一个栈)
Struts2框架把我们的ActionContext设置为OGNL 的上下文环境,凡是此环境中的值我们都应该通过#key的方式来进行访问,所以request,session等需要加前缀,又因为Struts2将我们的ValueStack作为OGNL的根对象,所以我们访问其中的内容只能通过非#的方式来进行。 需要注意的是我们访问这类对象时是不需要加入#的,因为它是根对象,所以不能加#,加了以后就不能访问到了。比如我们在Action中做了如下操作ActionContext.getContext(). getVlaueStack().
它是Action运行的上下文环境,Action的多项设置都存放在此,我们每一次Action调用都会创建一个ActionContext 。通常情况下我们可以通过静态方法getContext()来获得Action上下文,进而进行其它操作,比如说可以得到request session application等。
ValueStack
Struts 2要依赖于ValueStack对象。这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当Struts2接收个.action的请求后,会先建立Action类的对象实例,并且将Action类的对象实例压入ValueStack对象中(实际上,ValueStack对于相当一个栈)
Struts2框架把我们的ActionContext设置为OGNL 的上下文环境,凡是此环境中的值我们都应该通过#key的方式来进行访问,所以request,session等需要加前缀,又因为Struts2将我们的ValueStack作为OGNL的根对象,所以我们访问其中的内容只能通过非#的方式来进行。 需要注意的是我们访问这类对象时是不需要加入#的,因为它是根对象,所以不能加#,加了以后就不能访问到了。比如我们在Action中做了如下操作ActionContext.getContext(). getVlaueStack().
setVlaue(“MM”,”这是信息”),然后在页面就只可以通过
<s:property value=”MM” />就可以了。
Action的实例,总是放到value stack中。因为Action放在stack中,而stack是root(根对象),所以对Action中的属性的访问就可以省略#标记。但是,要访问ActionContext中其它对象的属性,就必须要带上#标记,以便让OGNL知道,不是从根对象,而是从其它对象中去寻找。
“#”主要有三种用途:
1. 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:
parameters
包含当前HTTP请求参数的Map
#parameters.id[0]作用相当于request.getParameter("id")
request
包含当前HttpServletRequest的属性(attribute)的Map
#request.userName相当于request.getAttribute("userName")
session
包含当前HttpSession的属性(attribute)的Map
#session.userName相当于session.getAttribute("userName")
application
包含当前应用的ServletContext的属性(attribute)的Map
#application.userName相当于application.getAttribute("userName")
attr
用于按request > session > application顺序访问其属性(attribute)
#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
******************以下的内容没有做验证***************************
2. 用于过滤和投影(projecting)集合,如books.{?#this.price<100};
3. 构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。[既字符串不是输出到页面,而是作为某个属性的取值],如下面的url就是一个取值。
例如在Ognl.jsp中加入以下代码:
4. <hr />
<h3>%的用途</h3>
<p><s:url value="#foobar['foo1']" /></p>
<p><s:url value="%{#foobar['foo1']}" /></p>
$符号 $符号主要有两个方面的用途。
(1) 在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。
(2) 在Struts 2框架的配置文件中引用OGNL表达式,例如下面的代码片断所示:
<validators>
<field name=”intb”>
<field-validator type=”int”>
<param name=”min”>10</param>
<param name=”max”>100</param>
<message>BAction-test校验:数字必须为${min}为${max}之间!</message>
</field-validator>
</field>
</validators>
*******************************************************************
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>struts2_20120314_01</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="default" extends="struts-default">
<action name="LoginAction" class="com.zeph.struts2.action.LoginAction">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
<result name="input">/index.jsp</result>
</action>
</package>
</struts>
重点,LoginAction.java
package com.zeph.struts2.action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String userName;
private String password;
private ActionContext context;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public void validate() {
if(getUserName().length() == 0){
addFieldError("userName", "User Name is required.");
}
}
@Override
public String execute() throws Exception {
context = ActionContext.getContext();
Integer count = (Integer) context.getApplication().get("count");
if (count == null) {
count = 1;
} else {
count++;
}
context.getApplication().put("count", count);
if (getUserName().equals("admin")) {
context.getSession().put("userName", getUserName());
return SUCCESS;
} else {
return ERROR;
}
}
}
index.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>login</title>
</head>
<body>
<s:form action="LoginAction">
<s:textfield name="userName" label="UserName"></s:textfield>
<s:password name="password" label="Password"></s:password>
<s:submit></s:submit>
</s:form>
</body>
</html>
重点,success.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login Success</title>
</head>
<body>
<s:property value="#session.userName" />
,login success,
<a href="context.jsp">redirect to context</a>. times:
<s:property value="#application.count" />
</body>
</html>
注意,在context.jsp中有一段代码是Javascript,用来显示今天的时间日期,不是struts中必要的。我只是想增加点内容,毕竟是欢迎页面。
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>context page</title>
</head>
<body>
welcome,
<s:property value="#session.userName" />
.
<script language="JavaScript" type="text/javascript">
var today;
var day;
var date;
today = new Date();
if (today.getDay() == 0)
day = "Sunday ";
if (today.getDay() == 1)
day = "Monday";
if (today.getDay() == 2)
day = "Tuesday ";
if (today.getDay() == 3)
day = "Wednesday";
if (today.getDay() == 4)
day = "Thursday ";
if (today.getDay() == 5)
day = "Friday";
if (today.getDay() == 6)
day = "Saturday ";
date = "Today is " + (today.getYear()) + "/" + (today.getMonth() + 1)
+ "/" + today.getDate();
document.write(date);
document.write(" " + day);
</script>
</body>
</html>
error.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>error</title>
</head>
<body>
<P>Sorry, login failed!!!!</P>
</body>
</html>