Struts 2基础
来源:互联网 发布:每天工作安排软件 编辑:程序博客网 时间:2024/06/14 08:46
Struts 2基础
第2章 Struts 2
此内容是《Java Web开发教程——入门与提高篇(JSP+Servlet)》一书附赠资料的一部分。
2.1概述
Struts现在分两个版本:Struts 1.X和Struts 2.X。Struts 1.X已经有很多年了,可以说非常流行,但是因为其他框架的快速发展以及自身存在的问题,Struts 2诞生了,Struts 2与Struts 1的区别非常大,实际上Struts 2的核心思想是基于另外一个非常成功的Web框架WebWork。两者的区别如表20.1所示。下面主要针对Struts 2进行介绍。
表2.1 Struts1和Struts2的比较
Feature
Struts 1
Struts 2
Action类
在Struts 1中要求Action类继承抽象的基类。在Struts 1中一个普遍存在的问题就是面向抽象类编程,而不是面向接口编程。
Struts 2中的Action可以实现一个Action接口,同时可以实现其他的接口,这样可以使用户有选择性地使用其它自定义的服务。Struts 2提供了基础类ActionSupport,该类实现了一些通用的接口。Action接口不是必须的。任何具有execute方法的POJO对象都可以用作Struts 2的Action对象。
线程模型
Struts 1的Actions是单例的,因为只有一个类的实例来处理所有对这个Action的请求,所以必须是线程安全的。单例策略对Struts 1的Action的能够完成的功能有很大限制,有些功能需要额外的努力才能完成。Action资源必须是线程安全的或者synchronized
Struts 2的Action对象是为每个请求实例化的,因此没有线程安全的问题。(在实践中,Servlet容器会为每个请求生成多个throw-away对象,增加的对象不会对性能产生太大影响或者对垃圾回收产生影响)
Servlet依赖
Struts 1的Action依赖Servlet API,因为当调用Action的execute方法时需要传参数HttpServletRequest和HttpServletResponse。
Struts 2的Action与容器不是紧密结合在一起的。多数情况下,servlet上下文被表示为Map对象,允许对Action进行独立的测试。如果需要,Struts 2的Action仍然可以访问原始的request和response对象。 然而,其它框架元素可以减少或者消除对HttpServetRequest和HttpServletResponse对象进行直接访问的必要。
可测试性
测试Struts 1 Action的一个主要障碍就是execute方法使用了Servlet API。1个第三方扩展Struts TestCase,为Struts 1提供了一组模拟(mock)对象。
Struts 2的Action可以通过实例化、设置属性和调用方法进行测试。依赖注入支持使测试更简单。
获取输入
Struts 1使用ActionForm对象来获取输入。像Action一样,所有的ActionForm必须继承一个基类。因为其它的JavaBean不能用作ActionForm,开发人员经常需要创建多余的类来获取输入。可以使用动态Form来替换传统的ActionForm类,但是开发人员同样可能需要重新描述已有的JavaBean。
Struts 2使用Action的属性作为输入属性,不用创建第二个输入对象。输入属性可以是复杂的对象类型,还可以有自己的属性。可以在页面中通过taglib访问Action属性。Struts 2也支持ActionForm模式,以及POJO表单对象和POJO Action。复杂对象类型,包括业务或者域对象,都可以作为输入/输出对象。模型驱动的特性简化了标签库对POJO输入对象的引用。
表达式语言
Struts 1集成了JSTL,所以可以使用JSTL的EL语言,EL提供了基本的对象结构遍历(object graph traversal),但是集合以及索引属性支持比较弱。
Struts 2可以使用JSTL,同时Struts还支持另外一种功能更强大、使用更灵活的表达式语言,这种语言是Object Graph Notation Language,简称OGNL。
值与视图的绑定
Struts 1使用了标准的JSP机制把对象与要访问的页面上下文绑定。
Struts 2使用了一种ValueStack技术,这样标签库不用把视图与要呈现的对象类型关联就可以访问值。ValueStack策略允许重用涉及多个类型的视图,这些类型可能有相同的属性名,但是属性类型不同。
类型转换
Struts 1的ActionForm属性通常都是字符串类型。Struts 1 使用Commons-Beanutils进行类型转换。转换器是针对每个类的,而不能为每个实例配置。
Struts 2使用OGNL进行类型转换,框架包含了常用对象类型和基本数据类型的转换器。
验证
Struts 1支持手动验证,通过ActionForm的validate方法或者通过继承通用的验证器来完成。对于同一个类可以有不同的验证上下文环境,但是不能链接到对子类型的验证。
Struts 2支持通过验证方法进行手工验证和XWork验证框架。Xwork验证框架支持对子属性的链接验证,使用为属性类型定义的验证规则和上下文。
Action执行的控制
Struts 1支持为每个模块提供独立的请求处理器(生命周期),但是同一个模块中的所有Action具有相同的生命周期。
Struts 2通过拦截器栈支持为每个Action创建不同的生命周期。必要的时候,可以使用不同的Actio创建和使用自定义栈。
注:来自Struts的官方网站:http://struts.apache.org/2.0.11.2/docs/comparing-struts-1-and-2.html
Strust 2结构图如图2.1(原图来自Strust 2文档)所示:
图2.1 Struts2结构图
在处理一个请求的时候,主要使用3个类:Action、Interceptor和Result
处理流程:
u 请求到达服务器之后,首先经过一系列过滤器,有的是可选的,最主要的过滤器是FilterDispatcher。所有的请求都会提交给它处理,该过滤器是在web.xml中配置的。配置代码如下:
<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>
u FilterDispatcher过滤器接收到请求之后调用ActionMapper查看是否需要调用Action。ActionMapper提供了HttpRequest与Action调用请求之间的映射关系,可以决定当前请求是否需要调用Action。如果ActionMapper返回的信息表明需要调用Action。FilterDispatcher过滤器把控制前交给ActionProxy;
u ActionProxy调用配置文件管理器ConfigurationManager,该管理器从struts.xml配置文件中获取配置信息,获取的信息主要包括当前请求对应哪个Action(对用户的请求进行处理),对应哪些Result(决定了如何对用户响应),有时候还涉及拦截器。然后根据这些信息创建ActionInvocation对象,该对象负责具体的调用过程。struts.xml是用户需要提供的最主要的配置文件。下面是一个struts.xml配置文件的部分内容。
<struts>
<package name="default" extends="struts-default">
<action name="Logon" class="mailreader2.Logon">
<result name="input">/pages/Logon.jsp</result>
<result name="cancel" type="redirectAction">Welcome</result>
<result type="redirectAction">MainMenu</result>
<result name="expired" type="chain">ChangePassword</result>
</action>
<action name="Logoff" class="mailreader2.Logoff">
<result type="redirectAction">Welcome</result>
</action>
</package>
</struts>
u ActionInvocation对象按照顺序执行当前请求所对应的拦截器,拦截器能够对请求进行预处理,例如验证、文件上传等,并能够对响应内容进行再处理。通常拦截器是由系统提供的,如果需要,编程人员只需要进行配置即可。在调用Action的方法之前,会调用拦截器的预处理方法;
u ActionInvocation对象调用拦截器的预处理方法之后会调用Action的execute方法,Action中的代码主要由编程人员根据功能进行编写的,通常从数据库检索信息或者向数据库存储信息。Action的方法返回一个字符串。下面是一个简单的Action例子。
package simple;
import java.util.Map;
import javax.servlet.http.HttpSession;
import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.xwork.ActionSupport;
public class LogoutAction extends ActionSupport {
public String execute() throws Exception {
Map session = ActionContext.getContext().getSession();
session.remove("logined");
session.remove("context");
return SUCCESS;
}
}
u ActionInvocation对象根据Action方法的返回结果以及struts配置文件生成Result对象。Result对象选择一个模板文件来响应用户,模板文件可以是JSP、FreeMarker和Velocity。
u 容器加载并执行模板文件,使用在Action中获取的信息对模版中的变量进行赋值,也可能从资源文件或者其他内部对象中获取信息。最终向浏览器呈现的是HTML、PDF或者其他内容。
u 模板文件执行的结果会经过拦截器进行再处理,最后通过过滤器返回给客户端。
在该结构图中,既包含了Struts框架提供的基础接口,也包括了用户要编写的文件。其中,ActionMapper、ActionProxy、ConfigurationManager、ActionInvocation和Result是框架提供的核心类。过滤器和拦截器是框架提供的,用户可以根据需要进行配置,当然也可以编写自己的过滤器和拦截器。用户需要编写的文件是struts.xml、Action和模板文件,这些也是用户在使用Struts 2框架时需要做的工作。
2.2 开发人员的主要任务
框架为开发人员提供了大量的辅助类,用户在使用框架开发的时候只需要编写很少文件。在使用Struts 2开发的时候,首先应该把环境搭建起来,然后使用Struts 2提供的标签开发界面,然后编写Action类,最后进行配置。
环境搭建
在进行具体的开发之前,需要先搭建环境。包括如下过程:
u 创建Web工程;
u 加载Struts 2的核心类库,核心类库包括commons-logging-1.0.4.jar、freemarker-2.3.8.jar、ognl-2.6.11.jar、struts2-core-2.0.11.2.jar和xwork-2.0.5.jar,把这些类库放到Web工程的WEB-INF/lib下面;
u 配置web.xml,主要配置Struts中心控制器FilterDispatcher,下面是1个例子。
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" 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 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Struts Blank</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.html</welcome-file>
</welcome-file-list>
</web-app>
u 创建struts.xml配置文件,与类文件放在一起,空白的struts文件如下所示。在使用Struts 2进行开发所有的配置基本上都在这个文件中完成。也可以根据需要创建多个配置文件,然后在这个配置文件中使用<include file="example.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.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<include file="example.xml"/>
<!-- Add packages here -->
</struts>
环境搭建完之后,在具体开发过程中主要完成3个方面的工作:
u 制作模板文件,可以使用JSP、FreeMarker或者Velocity等;
u 编写Action,基本上每个动作对应1个Action;
u 配置,主要在struts.xml中进行配置。
下面分别介绍。
制作模板文件
模版文件的主要作用是接收用户输入的信息,并向用户展示信息。Struts提供了多个标签库来简化页面的代码量,使用标签之后页面也更容易维护。下面是一段标签:
<s:actionerror/>
<s:form action="Profile_update" validate="true">
<s:textfield label="Username" name="username"/>
<s:password label="Password" name="password"/>
<s:password label="(Repeat) Password" name="password2"/>
<s:textfield label="Full Name" name="fullName"/>
<s:textfield label="From Address" name="fromAddress"/>
<s:textfield label="Reply To Address" name="replyToAddress"/>
<s:submit value="Save" name="Save"/>
<s:submit action="Register_cancel" value="Cancel" name="Cancel"
onclick="form.onsubmit=null"/>
</s:form>
Struts 2中提供了两类通用标签和3类界面标签:
u 控制标签
u 数据标签
u Form标签
u Non-Form用户接口标签
u Ajax标签
下面对这些类型的标签进行介绍。
控制标签及其用法如表2.2所示。
表2.2 控制标签
标签名
描述
例子
if
与Java中的if基本相同
<s:if test="%{false}">
<div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
<div>Will Be Executed</div>
</s:elseif>
<s:else>
<div>Will Not Be Executed</div>
</s:else>
else if
与Java中的else if基本相同
else
与Java中的else基本相同
append
按照顺序把多个迭代器的元素组合到一个迭代器中,保持原来的顺序不变。
<s:append var="myAppendIterator">
<s:param value="%{myList1}" />
<s:param value="%{myList2}" />
<s:param value="%{myList3}" />
</s:append>
<s:iterator value="%{#myAppendIterator}">
<s:property />
</s:iterator>
generator
根据val属性的给定的值生成迭代器对象。
<s:generator val="%{'aaa,bbb,ccc,ddd,eee'}">
<s:iterator>
<s:property /><br/>
</s:iterator>
</s:generator>
iterator
对迭代器或者集合进行遍历,类似于Java中的for-each循环。
<s:iterator value="#it.days" status="rowstatus">
<tr>
<s:if test="#rowstatus.odd == true">
<td style="background: grey"><s:property/></td>
</s:if>
<s:else>
<td><s:property/></td>
</s:else>
</tr>
</s:iterator>
merge
把多个迭代器的元素合并到一个迭代器中,合并后的顺序为1.1,2.1,3.1,1.2,1.3…,1.1表示第1个迭代器的第1个元素。
<s:merge var="myMergedIterator1">
<s:param value="%{myList1}" />
<s:param value="%{myList2}" />
<s:param value="%{myList3}" />
</s:merge>
<s:iterator value="%{#myMergedIterator1}">
<s:property />
</s:iterator>
sort
对List进行排序。
<s:sort var="mySortedList" comparator="myComparator" source="myList" />
subset
获取集合的子集。
<s:subset var="mySubset" source="myList" count="13" start="3" />
数据标签及其用法如表2.3所示。
表2.3 数据标签
标签名
描述
例子
a
生成HTML的<a>
<s:a href="%{testUrlId}"><img src="<s:url
value="/images/delete.gif"/>" border="none"/></s:a>
action
在JSP页面中直接调用Action
<s:action name="actionTagAction" executeResult="true" />
bean
实例化JavaBean对象
<s:bean name="org.apache.struts2.example.counter.SimpleCounter" var="counter">
<s:param name="foo" value="BAR" />
The value of foot is : <s:property value="foo"/> <br />
</s:bean>
date
创建Date对象
<s:date name="person.birthday" format="dd/MM/yyyy" />
debug
i18n
得到ResourceBundle对象。
<s:i18n name="myCustomBundle">
</s:i18n>
include
包含1个JSP或者Servlet的输出。
<s:include value="myJsp.jsp">
<s:param name="param1" value="value2" />
</s:include>
param
为其他标签提供参数
参考上面的例子
property
获取属性值
参考bean标签的例子
push
把值保存起来使用
<s:push value="user">
<s:propery value="firstName" />
<s:propery value="lastName" />
</s:push>
set
把某个值保存到某个作用范围的变量中。
<s:set name="personName" value="person.name"/>
Hello, <s:property value="#personName"/>. How are you?
text
呈现i18n的文本消息
<s:i18n name="struts.action.test.i18n.Shop">
<s:text name="main.title"/>
</s:i18n>
url
用于生成URL
<s:url value="editGadget.action">
<s:param name="id" value="%{selected}" />
</s:url>
Form标签及其用法如表2.4所示。
表2.4 Form标签
标签名
描述
例子
checkbox
生成复选框
<s:checkbox label="checkbox test" name="checkboxField1"
value="aBoolean" fieldValue="true"/>
checkboxlist
生成多个复选框
<s:checkboxlist name="foo" list="bar"/>
combobox
输入框与下拉框的组合。
<s:combobox
label="My Favourite Fruit"
name="myFavouriteFruit"
list="{'apple','banana','grape','pear'}"
headerKey="-1"
headerValue="--- Please Select ---"
emptyOption="true"
value="banana" />
doubleselect
生成联动菜单
<s:doubleselect label="doubleselect test1" name="menu"
list="{'fruit','other'}" doubleName="dishes"
doubleList="top == 'fruit' ? {'apple', 'orange'} : {'monkey', 'chicken'}" />
head
生成HTML的head部分。
<head>
<title>My page</title>
<s:head/>
</head>
file
生成文件输入框
<s:file name="anUploadFile" accept="text/*" />
form
生成form表单
<p/>
<s:form ... />
<p/>
hidden
生成隐藏域
<s:hidden name="foo" value="bar" />
label
生成标签
<s:label key="userName" />
optiontrans
-ferselect
生成两个列表框,可以通过中间的按钮把左边的选项移动到右边,也可以把右边的选项移动到左边。
<s:optiontransferselect
label="Favourite Cartoons Characters"
name="leftSideCartoonCharacters"
list="{'Popeye', 'He-Man', 'Spiderman'}"
doubleName="rightSideCartoonCharacters"
doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
/>
optgroup
在select中提供选项
<s:select label="My Selection"
name="mySelection"
value="%{'POPEYE'}"
list="%{#{'SUPERMAN':'Superman', 'SPIDERMAN':'spiderman'}}">
<s:optgroup label="Adult"
list="%{#{'SOUTH_PARK':'South Park'}}" />
<s:optgroup label="Japanese"
list="%{#{'POKEMON':'pokemon','DIGIMON':'digimon',
'SAILORMOON':'Sailormoon'}}" />
</s:select>
select
生成下拉框
password
密码输入框
<s:password label="%{text('password')}" name="password"
size="10" maxlength="15" />
radio
单选按钮
<s:radio label="Gender" name="male" list="#genders.genders"/>
reset
重值按钮
<s:reset value="Reset" />
submit
提交按钮
<s:submit value="OK" />
textarea
生成文本域
<s:textarea label="Comments" name="comments" cols="30" rows="8"/>
textfield
生成输入框
<s:textfield key="user" />
token
阻止表单重复提交
<s:textfield key="user" />
updownselect
创建元素能够上下移动的列表框
<s:updownselect
list="#{'england':'England', 'america':'America', 'germany':'Germany'}"
name="prioritisedFavouriteCountries"
headerKey="-1"
headerValue="--- Please Order Them Accordingly ---"
emptyOption="true" />
non-form UI标签及其用法如表2.5所示。
表2.5 non-form标签
标签名
描述
例子
actionerror
呈现错误信息
<s:actionerror />
actionmessage
呈现提示信息
<s:actionmessage />
component
创建自定义组件
<s:component template="/my/custom/component.vm"/>
div
生成HTML <div>
fielderror
输出关于输入元素的错误信息
<s:fielderror>
<s:param>field1</s:param>
<s:param>field2</s:param>
</s:fielderror>
<s:form .... >
....
</s:form>
Ajax标签包括a、autocompleter、bind、datetimepicker、div、head、submit、tabbedpanel、textarea、tree、treenode等。具体用法参考Struts 2帮助文档。
编写Action
针对每个功能可以编写1个Action,也可以多个功能共享1个Action。Action完成的主要功能包括:
u 获取用户的输入信息,这个获取的过程是由框架完成的,但是用户需要在Action中定义与用户输入表单元素名字相同的成员变量,关键是要提供对成员变量赋值的set方法,这样框架在获取用户输入信息之后会调用set方法把值赋给Action的成员变量。
u 根据用户的请求信息,调用完成业务逻辑的JavaBean。如果希望要把某些执行结果传递给模板文件(JSP、FreeMarker和Velocity等),需要在Action中定义成员变量来表示这些结果,最关键的是要定义get方法,这样在执行模版文件的时候会通过get方法来获取这些信息。
u 根据执行的结果,返回1个字符串,这个字符串决定了使用什么模板对用户进行响应。
下面是1个简单的例子。
public class LoginAction extends ActionSupport {
private String userId;
private String passwd;
// 对userId和passwd操作的setter和getter方法
public String execute() throws Exception {
if ("admin".equals(userId) && "password".equals(passwd)) {
Map session = ActionContext.getContext().getSession();
session.put("logined","true");
session.put("context", new Date());
return SUCCESS;
}
return ERROR;
}
}
注意:并不是必须继承ActionSupport,主要提供execute方法即可。
配置
通过配置文件Struts.xml对Web应用的流程进行管理,包括Action映射和Result处理,前者把请求与Action关联起来,后者把Action执行的结果与响应界面关联起来。下面是一段配置。下面是一个简单的例子。
<struts>
<package name="default" extends="struts-default">
<action name="Logon" class="mailreader2.Logon">
<result name="input">/pages/Logon.jsp</result>
<result name="cancel" type="redirectAction">Welcome</result>
<result type="redirectAction">MainMenu</result>
<result name="expired" type="chain">ChangePassword</result>
</action>
<action name="Logoff" class="mailreader2.Logoff">
<result type="redirectAction">Welcome</result>
</action>
</package>
</struts>
Struts 2中完成的主要配置如表2.6所示。
表2.6 Struts 2的主要配置信息
配置元素
例子
JavaBean
<bean type="com.opensymphony.xwork2.ObjectFactory"
name="myfactory" class="com.company.myapp.MyObjectFactory" />
常量
<constant name="struts.devMode" value="true" />
包
<package name="employee" extends="struts-default" namespace="/employee">
...
</package>
命名空间
包含
<include file="Home.xml"/>
拦截器
<interceptors>
<interceptor name="security"
class="com.company.security.SecurityInterceptor"/>
<interceptor-stack name="secureStack">
<interceptor-ref name="security"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
引用拦截器
<action name="VelocityCounter"
class="org.apache.struts2.example.counter.SimpleCounter">
<result name="success">...</result>
<interceptor-ref name="defaultComponentStack"/>
</action>
全局Result:
<global-results>
<result name="error">/Error.jsp</result>
<result name="invalid.token">/Error.jsp</result>
</global-results>
Action
Result
异常配置
在Action中使用:
<exception-mapping exception="com.company.SecurityException" result="login"/>
全局:
<global-exception-mappings>
<exception-mapping exception="java.sql.SQLException" result="SQLException"/>
<exception-mapping exception="java.lang.Exception" result="Exception"/>
</global-exception-mappings>
Struts 2提供了大量的拦截器,用户可以根据需要调用。
Struts 2的配置文件struts.xml的DTD定义如下。
<!--
Struts configuration DTD.
Use the following DOCTYPE
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
-->
<!ELEMENT struts (package|include|bean|constant)*>
<!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, default-action-ref?, default-class-ref?, global-results?, global-exception-mappings?, action*)>
<!ATTLIST package
name CDATA #REQUIRED
extends CDATA #IMPLIED
namespace CDATA #IMPLIED
abstract CDATA #IMPLIED
externalReferenceResolver NMTOKEN #IMPLIED
>
<!ELEMENT result-types (result-type+)>
<!ELEMENT result-type (param*)>
<!ATTLIST result-type
name CDATA #REQUIRED
class CDATA #REQUIRED
default (true|false) "false"
>
<!ELEMENT interceptors (interceptor|interceptor-stack)+>
<!ELEMENT interceptor (param*)>
<!ATTLIST interceptor
name CDATA #REQUIRED
class CDATA #REQUIRED
>
<!ELEMENT interceptor-stack (interceptor-ref*)>
<!ATTLIST interceptor-stack
name CDATA #REQUIRED
>
<!ELEMENT interceptor-ref (param*)>
<!ATTLIST interceptor-ref
name CDATA #REQUIRED
>
<!ELEMENT default-interceptor-ref (param*)>
<!ATTLIST default-interceptor-ref
name CDATA #REQUIRED
>
<!ELEMENT default-action-ref (param*)>
<!ATTLIST default-action-ref
name CDATA #REQUIRED
>
<!ELEMENT default-class-ref (param*)>
<!ATTLIST default-class-ref
class CDATA #REQUIRED
>
<!ELEMENT global-results (result+)>
<!ELEMENT global-exception-mappings (exception-mapping+)>
<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
<!ATTLIST action
name CDATA #REQUIRED
class CDATA #IMPLIED
method CDATA #IMPLIED
converter CDATA #IMPLIED
>
<!ELEMENT param (#PCDATA)>
<!ATTLIST param
name CDATA #REQUIRED
>
<!ELEMENT result (#PCDATA|param)*>
<!ATTLIST result
name CDATA #IMPLIED
type CDATA #IMPLIED
>
<!ELEMENT exception-mapping (#PCDATA|param)*>
<!ATTLIST exception-mapping
name CDATA #IMPLIED
exception CDATA #REQUIRED
result CDATA #REQUIRED
>
<!ELEMENT include (#PCDATA)>
<!ATTLIST include
file CDATA #REQUIRED
>
<!ELEMENT bean (#PCDATA)>
<!ATTLIST bean
type CDATA #IMPLIED
name CDATA #IMPLIED
class CDATA #REQUIRED
scope CDATA #IMPLIED
static CDATA #IMPLIED
optional CDATA #IMPLIED
>
<!ELEMENT constant (#PCDATA)>
<!ATTLIST constant
name CDATA #REQUIRED
value CDATA #REQUIRED
>
2.3实例
功能:登录。
涉及的文件有:
l Login.jsp,用于输入登录信息;
l welcome.jsp,登录之后的欢迎界面;
l loginCheck.jsp,判断用户是否登录;
l LoginAction.java,完成登录业务处理,正常情况下会调用其他业务逻辑JavaBean来完成;
l LogoutAction.java,完成退出业务处理;
l struts.xml,应用的配置文件。
下面分别介绍。
Login.jsp
源文件:Login.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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head><body>
<form action="login.action" method="post">
User id<input type="text" name="userId" /> <br/>
Password <input type="password" name="passwd" /> <br />
<input type="submit" value="Login"/>
</form>
</body>
</html>
/pages/welcome.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="ww" uri="/webwork" %>
<jsp:include page="WEB-INF/inc/loginCheck.jsp" />
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome</title>
</head>
<body>Welcome, you have logined. <br />
The attribute of 'context' in session is
<ww:property value="#session.context" />
<br /><br /><br />
<a xhref="<%= request.getContextPath() %>/logout.action">Logout</a>
<br />
<a xhref="<%= request.getContextPath() %>/logout2.action">Logout2</a>
</body>
</html>
/WEB-INF/inc/loginCheck.jsp
<%@ taglib="/webwork" prefix="ww" %>
<ww:if test="#session.login != 'true'">
<jsp:forward page="<%= request.getContextPath() %>/login.jsp" />
</ww:if>
simple.LoginAction.java
package simple;
import java.util.Date;import java.util.Map;
import javax.servlet.http.HttpSession;
import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.xwork.ActionSupport;
public class LoginAction extends ActionSupport {
private String userId;
private String passwd;
public String execute() throws Exception {
if ("admin".equals(userId) && "password".equals(passwd)) {
// HttpSession session = ServletActionContext.getRequest().getSession();
// session.setAttribute("logined","true");
// session.setAttribute("context", new Date());
// Better is using ActionContext
Map session = ActionContext.getContext().getSession();
session.put("logined","true");
session.put("context", new Date());
return SUCCESS;
}
return ERROR;
}
public String logout() throws Exception {
// HttpSession session = ServletActionContext.getRequest().getSession();
// session.removeAttribute("logined");
// session.removeAttribute("context");
Map session = ActionContext.getContext().getSession();
session.remove("logined");
session.remove("context");
return SUCCESS;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
simple.LogoutAction.java
package simple;
import java.util.Map;
import javax.servlet.http.HttpSession;
import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.xwork.ActionSupport;
public class LogoutAction extends ActionSupport {
public String execute() throws Exception {
Map session = ActionContext.getContext().getSession();
session.remove("logined");
session.remove("context");
return SUCCESS;
}
}
/WEB-INF/classes/xwork.xml
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
<xwork>
<include file="webwork-default.xml"/>
<package name="default" extends="webwork-default">
<!-- Add your actions here -->
<action name="login" class="simple.LoginAction" >
<result name="success" type="dispatcher">/pages/welcome.jsp</result>
<result name="error" type="redirect">/login.jsp</result>
</action>
<action name="logout2" class="simple.LoginAction" method="logout" >
<result name="success" type="redirect">/login.jsp</result>
</action>
<action name="logout" class="simple.LogoutAction" >
<result name="success" type="redirect">/login.jsp</result>
</action>
</package>
</xwork>
- Struts 2基础
- Struts 2基础
- Struts 2基础
- Struts 2基础入门
- Struts 2基础入门
- struts基础
- Struts基础
- Struts基础
- Struts基础
- Struts基础
- struts基础
- Struts基础
- struts基础
- struts基础
- struts基础
- struts基础
- 一、Struts 2 基础---4.Struts 2中的Action
- 一、Struts 2 基础---6.Struts 2的异常机制
- JDBC 大数据的处理
- 浙江省赛热身赛之---周赛第一场
- JAVA学习笔记(2013年03月17日)
- Stanford ML - Lecture 8 - Support Vector Machines
- 史上最最佳软件开发实践指导
- Struts 2基础
- 写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)
- <为知更新>Android内核驱动开发中的Kconfig文件结构分析(图文)
- 控制cpu的利用率
- 3.17 大数据环境下集成R语言的数据挖掘平台项目记录(一)
- ABAP 向上取整和向下取整 CEIL & FLOOR
- Android的快速开发框架 afinal
- 论文参考文献格式详细国家标准
- 如何使用Python为Hadoop编写一个简单的MapReduce程序(这个人T字还有好几篇精华的可以看)