struts2教程(完全版)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Yaio 4
一、准备工作及实例 4
1.解压struts-
2.1.6-all.zip 4
2.六个基本包 4
3.初识struts2配置文件 4
(1).web.xml文件 4
(2).struts.xml文件 4
(3).struts.properties(参default.properties) 4 (4)struts-default.xml 5
(5)其它配置文件 5
4.让MyEclipse提示xml信息 5
5.如何使用alt+/提示 5
6.实例 5
7.开启struts2自带的开发模式常量 7
8.vo传参模式 8
9.ModerDriven传参模式(不建议采用) 8
10.为什么要使用struts2代替struts1.x 9
二、struts.xml配置及例程 9
1.配置文件的优先级 9
2.配置形式 9
3.package配置相关 10
4.分工合作include:指定多个配置文件 12
5.tomcat认证访问 12
6.初识拦截器 13
7.Action中的method属性 15
8.使用ForwardAction实现页面屏蔽。
17
8.使用default-Action配置统一访问 17
小结Action 18
9.使用通配符 18
10.使用0配置:ZERO Annotation 19
11.Result配置详解 19
12.异常处理 24
三、在Action获取Scope对象 25
方式一、与Servlet解耦合的非IOC方式 25
方式二、与Servlet解耦合的IOC方式 27 方式三、与Servlet耦合的非IOC方式 27 方式四、与Servlet耦合的IOC方式 28
四、OGNL与ValueStack(VS) 29
1.值栈入门 29
2.OGNL入门 31
3.普通方法访问 31
4.静态方法访问 31
5.默认类Math的访问 32
6.调用普通类的构造方法 32
7.集合对象初步 32
8.集合对象进阶 33
9.N语法top语法 34
10.获取Stack Context中的信息 35
11.总结$ # %的区别 35
12.总结OGNL[重点] 35
五、拦截器 36
1.概述strust2中的拦截器 36
2.自定义拦截器 37
方式一,实现Interceptor接口。
37
方式二、继承AbstractInterceptor抽象类 38 方式三、继承MethodFilterInteceptor类 38
3.使用来MethodFilterInterceptor灵活拦截 41
4.使用默认的execAndWait拦截器 42
5. TokenInterceptor防止表单重复提交。
44
6.使用拦截器实现权限验证 46
7.拦截器中的注解 48
8.使用PreResultListener实现回调 50
六、使用标签 52
1.基础表单标签 52
2.单选按钮和复选框: 52
3.三种方式实现下拉列表 52
4.二级联动 54
5.其它表单标签 57
6.其它常用标签的使用(代码参名为“补充”的文件夹下的tag.jsp) 59
七、国际化 60
1.action级别下的国际化 60
2.配置package的资源文件 63
3.app级别的资源文件 63
4.使用资源文件的原理 63
5.选择使用资源文件 64
八、验证机制 65
1.基于手工编码的校验 65
简析校验流程: 69
2.基于XML配置形式的校验 69
九、文件上传下载(了解) 71
1. 上传实例 71
2.下载实例 74
十、类型转换 75
1.基于Action的直接属性转换 75
2.基于Action的间接属性vo转换 76
十一、注解配置 77
十二、总结本教程对struts2的基本知识进行了一些说明,关于struts2的更多详细内容应参看struts2的官方文档及提供的app实例。
下面对struts2的基本执行流程作一简要说明,此流程说明可以结合官方提供的struts2结构图来看: 78
Yaio
一、准备工作及实例
1.解压struts-
2.1.6-all.zip
apps目录:struts2自带的例子程序
docs目录:官方文档。
lib 目录:存放所有jar文件。
Src 目录:源文件存放地
2.六个基本包
struts2-core-2.1.6.jar :开发的核心类库
freemarker-2.3.13.jar :struts2的UI标签的模板使用freemarker编写commons-logging-1.0.4.jar :日志包
OGNL-2.6.11.jar :对象图导航语言,通过它来读写对象属性
xwork-2.1.2.jar :xwork类库,struts2在其上进行构建
commons-fileupload-1.2.1.jar:文件上传组件,2.1.6版本后必须加入此jar包
特别需要说明的是目前strust2的最新版本是struts-2.1.6,它作为2.1.X 的正式版。
特别要注意导入commons-fileupload-1.2.1.jar包,在此jar包中包含了RequestContext类,如果不导入该jar包将会报异常。
3.初识struts2配置文件
(1).web.xml文件
主要完成对StrutsPrepareAndExecuteFilter的配置(在以前的版本中是对FilterDispatcher配置,新版本同样支持用FilterDispatcher配置),它的实质是一个过滤器,它负责初始化整个Struts框架并且处理所有的请求。
这个过滤器可以包括一些初始化参数,有的参数指定了要加载哪些额外的xml配置文件,还有的会影响struts框架的行为。
除了StrutsPrepareAndExecuteFilter外,Struts 还提供了一个ActionContexCleanUp类,它的主要任务是当有其它一些过滤器要访问一个初始化好了的struts框架的时候,负责处理一些特殊的清除任务。
(2).struts.xml文件
框架的核心配置文件就是这个默认的struts.xml文件,在这个默认的配置文件里面我们可以根据需要再包括其它一些配置文件。
在通常的应用开发中,我们可能想为每个不同的模块单独配置一个struts.xml文件,这样也利于管理和维护。
这也是我们要配置的主要文件。
(3).struts.properties(参default.properties)
在Struts框架使用了很多属性,我们可以通过改变这些属性来满足我们的需求。
要改变这些属性,只需在struts.properties文件中指定属性的key和value 即可。
属性文件可以放在任何一个包含在classpath中的路径上,但是通常我们都把它放在/WEB-INF/classes目录下面。
我们可以在struts-default.properties 文件中找到一个属性的列表。
(4)struts-default.xml
此文件是struts2框架默认加载的配置文件,它定义了struts2一些核心bean和拦截器,它会自动包含(included)到struts.xml文件中(实质是通过
<package extends="struts-default">),并为我们提供了一些标准的配置。
我们可以在struts2-core.jar中找到这个文件。
(5)其它配置文件
velocity.properties,struts-default.vm,struts-plugin.xml
4.让MyEclipse提示xml信息
当我们在编写struts.xml时,发现eclipse并不会给出帮助提示,那是因为MyEclipse默认并不支持struts2,所以我们需要手工导入dtd以支持提示。
步骤:[window][preferences][MyEclipse][Files and Editors][XML][xml Catelog]然后在右边点add添加:location为dtd文件所在的位置(struts-2.0.dtd文件struts2-core-2.1.6.jar中可以得到),KeyType选择URI,Key为struts-
2.0.dtd文件中文档声明的内容(),在struts.xml文件中也有此key值。
5.如何使用alt+/提示
在MyEclipse6.5中,默认的提示为Ctrl+Space,而它会与我们的输入法切换冲突,使提示失效。
找到key,先取消Content Assist命令的绑定,再用
“alt+/”来绑定。
6.实例
步骤一,新建myStruts2项目,并导入struts2的六个基本jar包。
步骤二,建立LoginAction文件,主要代码如下:
package com.asm;
import com.opensymphony.xwork2.Action;
public class LoginAction implements Action {
private String username;
private String password;
...省略get/set方法
public String execute() throws Exception {
if (username.equals("struts2")) {
return "loginSuccess";
} else {
return "loginFailure";
}
}
}
说明:实现了Action接口,主要是为了保证execute的正确定义,其实我们也可以不实现此接口,只要能保证execute方法书写的正确书写(方法名,返回值)。
步骤三,在struts.xml文件中注册LoginAction。
此配置文件要放在src目录下,实质就是成为classpath环境变量下的文件。
主要代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"">
<struts>
<package name="myFirst" namespace="/" extends="struts-default">
<action name="login" class="com.asm.LoginAction">
<result name="loginSuccess">/success.jsp</result>
<result name="loginFailure">/failure.jsp</result>
</action>
</package>
</struts>
说明:package后面会有详细说明。
action元素中的name属性值指定了此action 所指定的请求路径为“login.action”。
后面login.jsp中的<form action=...>属性值就会参照此name属性。
步骤四、提供jsp页面
login.jsp主要代码:
<body>
<form action="<%=request.getContextPath()%>/login.jsp"
method="post">
户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="login">
</form>
</body>
failure.jsp主要代码
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<html>
<body>
登录失败,错误的用户名:<s:property value="username"/><br>
<a href="<%=request.getContextPath()%>/login.jsp">返回</a>
</body>
</html>
说明:使用了标签库,在struts2中使用标签库非常简单,只需要像上面那样导入标签库便可以使用所有的struts2的所有标签
success.jsp主要代码
<body> 登录成功!</body>
步骤五、配置web.xml。
完成核心监听器注册。
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4"
xmlns=""
xmlns:xsi=""
xsi:schemaLocation=":///xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>struts2</filter-name>
<!-- <filter-
class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
-->
<filter-
class> org.apache.struts2.dispatcher.ng.filter.StrutsPr epareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
说明:注释掉的部分为以前2.1.4版本中用的核心filter类。
StrutsPrepareAndExecuteFilter类的init方法将会读取类路径下默认的配置文件struts.xml,并以javabean形式存放在内存中,以后struts2对用户的每次请求将使用内存中数据,而不是重读struts.xml文件。
步骤六、发布测试。
简要分析执行流程:
当输入login.jsp访问jsp页面填写完相关信息并提交给login.action时,它会首先被在web.xml中配置的过滤器监听到,过滤器会去查找strust.xml文件,并结合namespace查找名为login的action,查找到此action便交给其处理,LoginAction内部会执行execute方法,并返回结果result(result也是参照的struts.xml中action下的result配置)。
关于表单传参,主要是参照的action 中的方法名,而非属性名。
7.开启struts2自带的开发模式常量
在以前的开发中,当修改一些配置时总是不能及时地更新到服务器,我们总会重新部署或重启来更新改变的内容,在struts2中可以通过一个常量来达到此目的。
即在struts.xml中的<struts>元素下增加如下内容:<constant
name="struts.configuration.xml.reload" value="true" /> 这样配置后,当配置文件修改保存时就会及时更新到服务器中。
其它一些常量:
<!-- 指定WEB应用的编码集,相当于调用
HttpServletRequest.setCharacterEncodint方法,如果使用了velocity或freemarker,它也用于指定输出的编码格式 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 指定请求后缀为.action,指定多个请求后缀用逗号分隔 -->
<constant name="struts.action.extension" value="action" />
<!--设置浏览器是否缓存静态内容,建议:开发阶段关闭,运行时开启 -->
<constant name="struts.serve.static.browserCache" value="false" />
<!--当struts.xml配置文件修改后,系统是否重新加载该文件,开发阶段打开此功能 -->
<constant name="struts.configuration.xml.reload" value="true" />
<!-- 开发提示:出错时打印更详细的信息-->
<constant name="struts.devMode" value="true" />
<!-- 指定请求的后缀可以是.do或.action -->
<constant name="struts.action.extension" value="do,action" />
注意:在struts2.1.6版本中存在一个bug:即配置了
struts.i18n.encoding常量也不能解决中文乱码问题,原因是此版本在获取请求参数后才调用了setCharacterEncoding()方法进行编码设置。
解决此bug的方法是配置一个filter,并在doFilter方法中增加如下代码:
request.setCharacterEncoding(“UTF-8”); 在以后的2.1.8版本中解决了此问题及2.1.6中存在的其它bug,建议新项目使用2.1.8版本。
8.vo传参模式
Copy上面的myStruts2项目,改名为myStruts2Vo项目。
作如下修改:在LoginAction中有两个字段:username,password。
把此两个属性重构到
er类中,然后在LoginAction中提供User对象及相应的get/set 方法。
现在需要注意的是在login.jsp中会有如下的修改:
户名:<input type="text" name="ername"><br>
密码:<input type="password" name="user.password"><br>
关键就是改掉name属性值。
其它基本无变动。
后话:假如此此User对象并不能和Model层的相应对象完全对应,我们还应借助此User对象在Action中构建出Model层的相应对象,这样,在exectue方法中便能通过构建的Model对象作为参数与Model层交互。
9.ModerDriven传参模式(不建议采用)
Copy上面的myStruts2Vo项目,改名为myStruts2Model项目。
重点是修改LoginAction,修改后的主要内容如下:
package com.asm;
import er;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ModelDriven;
public class LoginAction implements Action, ModelDriven<User> {
private User user = new User();
public String execute() throws Exception {
if (user.getUsername().equals("struts2")) {
return "loginSuccess";
} else {
return "loginFailure";
}
}
public User getModel() {
return user;
}
}
说明:它实现了ModelDriven接口,并使用了泛性机制(必须),因此要求jdk1.5以上。
现在需要注意的是在login.jsp中name属性值为User中两个字段,和第一个实例一样。
说明:此方式一般不会使用,在此略作了解。
10.为什么要使用struts2代替struts1.x
(1)struts2的execute方法中的参数不会依赖于servletAPI,实现了也servlet解耦,是一种无侵入式的设计。
(2)struts2提供了拦截器,利用拦截器可以进行AOP编程,实现权限拦截等功能。
(3)struts2提供了类型转换器,我们可以很容易地对请求参数转换成需要的类型。
(4)提供了同种表现层技术支持,如JSP、freeMarker、velocity等
(5)可以对指定的方法进行校验,可以轻松地实现表单校验功能
(6)提供了全局范围、包范围和action范围的国际化资源文件管理实现。
二、struts.xml配置及例程
1.配置文件的优先级
在struts2中一些配置(比如常量)可以同时在struts-default.xml(只读性),strtus-plguin.xml(只读性),struts.xml,struts.properties和web.xml文件中配置,它们的优先级逐步升高,即是说后面的配置会覆盖掉前面相同的配置。
2.配置形式
下面以对struts.i18n.encoding=UTF-8的配置为例进行说明:
在struts.xml配置形式如下:
<constant name="struts.i18n.encoding" value="gbk"></constant>
在struts.properties的配置形式如下:
struts.i18n.encoding=UTF-8
在web.xml中配置如下:
<filter>
<filter-name>struts2</filter-name>
<filter-
class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExec uteFilter
</filter-class>
<init-param>
<param-name>struts.i18n.encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
说明:官方声称配置了此常量可以解决中文乱码问题,但实事上并不能达到目的,在前面的三个项目中,如果我们在表单中输入中文,其结果是会出现乱码。
解决此问题参看[一.7的注意]。
这是struts2.1.6中的一bug,它的下一版2.1.8已解决此问题。
3.package配置相关
下面我们建立struts2package项目来进行package相关测试:
链接地址
说明:在上面的配置文件中所用到的Test1Action和Test2Action这两个Action都只是继承了com.opensymphony.xwork2.ActionSupport类,而ActionSupport默认返回的就是“success”,所以当点击上面的链接分别转到了forward目录下的test1.jsp和test2.jsp。
下面重点来看这个package元素的namespace属性及action的name属性,它们共同定义了action所映射到的实质文件。
上图展示了链接地址和action的对应关系,所以当我们要想访问一个action所关联到的jsp文件时,应该用namespace+action的name 关于它的内容测试可以参考struts2package项目。
补充:通常情况下,action元素的name是属性值是不能出现“/”的,所以希望通过action中name属性来实现多级映射,需要在sturts.xml中增加如下属
性:
<constant name="struts.enable.SlashesInActionNames" value="true"/> 这样配置后就可以再action的name元素中使用“/”了。
比如:
<package name="tt3" extends="struts-default">
<action name="test3/test3" class="com.asm.Test3Action">
<result name="success">/forward/test3.jsp</result>
</action>
</package>
然后输入<a href="<%=path%>/test3/test3.action">test3</a><br>链接地址就可以访问了
强调:namespace默认值“”,即不配置namespace属性。
它的意思是:如果action不能进行完整路径匹配,则会来此namespace下进行匹配,比如:.../test/test/test.action,如果参照namespace及action的name不能找到也之完全对应的action,它会再到依次追溯到上级目录中查找,即是说它会以…/test/test.action这样的路径来对应namespace和action的name进行查找。
如果返回到最终的目录仍找不到,它就会到namespace="/"对应的包下查找名为test的action,如果仍找不到,它就会去默认的namespace下查找名为test的action,如果找到则执行此action。
另外,namespace也可以配置成
namespace="/"。
它代表配置为项目的根。
总结action的名称探索顺序:完全对应、逐步追溯到上级目录查找、"/"下查找、默认namespace下查找。
为什么要提出namespace,主要是避免多人共同开发项目出现名字冲突。
如果不使用namespace,多个人所写的action中可能出现重名的现象,这样当项目合并时就会出现冲突。
而有了namespace可以在项目开发时由项目经理给每一个人分不同的namespace,这样每个开发人员只需要保证自己所写的action不同名即可。
namespace引发的链接问题:当我们为action配置了namespace时,访问此action的形式总会是如下形式:.../webappname/xxx/yyy/ActionName.action 而当此action成功执行跳转到某个jsp页面时,如想在此jsp页面写链接,一定要写绝对路径,因为相对路径是相对.../webappname/xxx/yyy/,而如果以后我们修改了action的namespace时,相对路径又要变,所以链接不能写成相对路径。
以
下介绍绝对路径的写法:通常用myeclipse开发时建立一个jsp文件,默认总会有如下内容:
<%
String path = request.getContextPath();
String basePath =
request.getScheme()+"://"+request.getServerName()+":"+request.getServerP ort()+path+"/";
%>
我们写绝对路径可以参此内容。
还可以参<head>下的<base
href="<%=basePath%>"> 来完成绝对路径的书写。
4.分工合作include:指定多个配置文件
比如让jack来单独开发一个action,在jack.xml中的配置文件为:
<struts>
<package name="jack" namespace="/jack" extends="struts-default">
<action name="test4" class="com.asm.Test4Action">
<result name="success">/forward/test4.jsp</result>
</action>
</package>
</struts>
然后在struts.xml文件中增加如下内容:<include
file="jack.xml"></include> 它实质就是把jack.xml中的<package>及其内容写进struts.xml中的<struts>根元素下。
链接:<a href="<%=path %>/jack/test4.action">test4</a> 这样便可以访问到了forward目录下的test4.jsp了。
5.tomcat认证访问
接上例:namespce的作用除了在前面提到的避免协同开发名字冲突外,还为认证提供一个条件。
比如jack开发的东西所关联到的页面需要权限才能被访问。
由于多为tomcat中的内容,下面只列出步骤。
步骤一,tomcat的conf目录下tomcat-users.xml内容如下:
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="jack" password="jack" roles="admin,manager"/>
<user username="tom" password="tom" roles="manager"/>
</tomcat-users>
步骤二,在web.xml中增加如下内容:
<security-constraint>
<web-resource-collection>
<web-resource-name>jack</web-resource-name>
<url-pattern>/jack/*</url-pattern>
<http-method>POST</http-method>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>input authentication message</realm-name> </login-config>
这样配置完成后,当我们访问.../jack中的任何内容都会要求输入密码认证信息,认证时输入tomcat-users.xml配置的admin权限的用户名和密码即可访问(这里就只有jack用户名可以访问)
6.初识拦截器
拦截器能在action被调用之前和被调用之后执行一些“代码”。
Struts2框架的大部分核心功能都是通过拦截器来实现的,如防止重复提交、类型转换、对象封装、校验、文件上传、页面预装载等等,都是在拦截器的帮助下实现的。
每一个拦截器都是独立装载的(pluggable),我们可以根据实际的需要为每一个action配置它所需要的拦截器。
在myStruts2项目下,重新对配置文件作如下修改:
<package name="myFirst" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="timer"
class="com.opensymphony.xwork2.interceptor.TimerInterceptor" />
<interceptor
name="params"
class="com.opensymphony.xwork2.interceptor.P arametersInterceptor" />
</interceptors>
<action name="login" class="com.asm.LoginAction">
<interceptor-ref name="timer"></interceptor-ref>
<interceptor-ref name="params"></interceptor-ref>
<result name="loginSuccess">/success.jsp</result>
<result name="loginFailure">/failure.jsp</result>
</action>
</package>
首先在package中定义了两个拦截器,然后在login action中引用了这两个拦截器,需要说明的是这里使用的拦截器都是系统自带的拦截器。
其实在extends 所继承的struts-default中就包含了很多拦截器,也包括我们这里所用的拦截器,但如果在此action中不使用params拦截器,将会报空指针错,因为params 拦截器的作用是传递表单参数,如果不使用此拦截器就不能在action中得到表单参数,所以引用时会报空指针错。
虽然extends继承的strust-default自带有params拦截器,但是当我们自己引用了拦截器时,继承struts-default将不会再为我们分配默认的拦截器(有点类似构造器),但是我们仍然可以通过
<interceptor-ref name="defaultStack"/>来继续使用struts-defalut的拦截器。
补充:由于上面的package继承于struts-default,而我们这里所用到的timer和params都是在struts-defalut中定义过,所以即使我们在
<interceptors>中没有定义过这两个拦截器,也可以直接在action中引用。
使用</interceptor-stack>组合多个拦截器:比如我们想把上面的params和timer这两个拦截器组合:
<interceptor-stack name="timer_param">
<interceptor-ref name="timer" />
<interceptor-ref name="params" />
</interceptor-stack>
然后再在action引用<interceptor-ref n ame="timer_param"/>”,效果和分别引用两个是一样的。
其实我们使用strtus-default中的<interceptor-ref name="defaultStack"/>也是使用interceptor-stack方式。
7.Action中的method属性
在struts1.x中我们知道通过继承DispatchAction可以实现把多个Action 进行统一操作,在struts2中实现action的统一操作也很简单。
我们以crud操作为例,把crud集中到一个Action中。
步骤一、建立CRUDAction,内容如下:
package com.asm;
import com.opensymphony.xwork2.ActionSupport;
public class CRUDAction extends ActionSupport {
public String add() {
return "success";
}
public String del() {
return "success";
}
public String update() {
return "success";
}
public String query() {
return "success";
}
}
步骤二、配置此Action,为了清晰明了,专为此Action,建立一个配置文件crud.xml,主要内容如下:
<struts>
<package name="crud" extends="struts-default" namespace="/crud"> <action name="add" class="com.asm.CRUDAction" method="add">
<result name="success">/crud/addSuccess.jsp</result>
</action>
<action name="del" class="com.asm.CRUDAction" method="del">
<result name="success">/crud/delSuccess.jsp</result>
</action>
<action name="update" class="com.asm.CRUDAction" method="update">
<result name="success">/crud/updateSuccess.jsp</result>
</action>
<action name="query" class="com.asm.CRUDAction" method="query">
<result name="success">/crud/querySuccess.jsp</result>
</action>
</package>
</struts>
分析:上面的method方法的值来源于CRUDAction中方法的名字,这样当我们访问上面的每一个Action时,它实质是和method指定的方法关联上。
步骤三、把crud.xml配置文件并入struts.xml中,只需增加如下代码:
<include file="jack.xml"></include>
步骤四、编写相应的jsp页面,在此略去crud文件夹下的四个跳转jsp页面(addSuccess.jsp等),重点是crud.jsp页面。
内容如下:
<html>
<%
String path=request.getContextPath();
%>
<body>
<a href="<%=path %>/crud/add.action">添加数据</a><br>
<a href="<%=path %>/crud/del.action">删除数据</a><br>
<a href="<%=path %>/crud/query.action">查询数据</a><br>
<a href="<%=path %>/crud/update.action">修改数据</a><br>
</body>
</html>
步骤五、发布测试。
补充扩展,动态调用DMI:不使用method实现统一.我们在crud.xml中增加如下内容:
<action name="op" class="com.asm.CRUDAction">
<result name="success">/crud/op.jsp</result>
</action>
然后再在crud.jsp中定义如下链接:
<a href="<%=path %>/crud/op!add.action">添加数据</a><br>
<a href="<%=path %>/crud/op!del.action">删除数据</a><br>
<a href="<%=path %>/crud/op!query.action">查询数据</a><br>
<a href="<%=path %>/crud/op!update.action">修改数据</a><br>
注意查看上面的链接地址,它们都是针对op action,然后再加地上“!
+CRUDAction中相应的方法名”,最后再写上.action即可以访问到统一页面
op.jsp。
这样做虽然能减少页面,但是由于它们实质用到的是同一个Action,所以这就意味着我们要使用的拦截器相同,相同的跳转result。
实际中这种方式很少使用,在此略作了解。
如果不想使用动态方法调用,我们可以通过常量来关闭,即在struts.xml中增加如下配置:
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
扩展2:在CRUDAction中使用do。
举例:我们在CRUDAction中增加一个新的方法,内容如下:
public String doMain(){
return "success";
}
然后再在在crud.xml中增加如下内容:
<action name="main" class="com.asm.CRUDAction" method="main">
<result name="success">/crud/main.jsp</result>
</action>
注意:配置中method属性值是doMain中去掉do后M小写。
然后再在crud.jsp中增加如下链接:
<a href="<%=path %>/crud/main.action">main页面</a><br>
随后便可以访问到.../crud/main.jsp页面了。
8.使用ForwardAction实现页面屏蔽。
我们在jsp页面之间写链接总会是.../xxx.jsp,而如果我们想屏蔽掉具体的jsp,只需要所jsp页面配置成一个ForwardAction即可实现。
示例如下:在根目录下有一个index.jsp主页,我们strtus.xml中作如下配置:
<package name="def" extends="struts-default">
<action name="forward">
<result >/index.jsp</result>
</action>
</package>
说明:如果没有未action指定class,默认就是ActionSupport类,如果没有为action指定method属性,则默认执行execute方法,如果没有指定result 的name属性,默认值为success。
知道了这些再结合ActionSupport的源码就不难理解实现转发的原理了。
随后再在前面第7点扩展中用到的op.jsp中增加如下代码:
<a href="<%=request.getContextPath()%>/forward.action">forward</a>
最后再测试访问op.jsp,在op.jsp中页面中直接点链接便可以跳到
index.jsp,观察地址栏发现此时跳到index页面是进行的服务器跳转,如果我们在上面的配置中的result增加type属性变成<result
type="redirect">/index.jsp</result>,实现的跳转就是客户端跳转。
补充:像这种forward形式的action实质是执行的ActionSupport 这个Action。
因此配置它的result可以参看此类的api文档,比如它常用的result name有:success、login、input等。
8.使用default-Action配置统一访问
default-action-ref,当访问没有找到对应的action时,默认就会调用default-action-ref指定的action.同样在上面的package中增加如下内容:
<default-action-ref name="error"></default-action-ref>
<action name="error">
<result>/other/error.jsp</result>
</action>
上面一段内容就是说当我们访问的action不能被找到时便指向名为error的action中去,接着我们在下面配置了这个error Action。
但是要注意,一个package内只配置一个<default-action-ref>,如果配置多个,就无法预测结果了. 此时我们只要输入.../myStruts2/luanFangWen.action这样的形式,它就会去访问这个默认的<default-action-ref>,通常我们会为它配置一个错误页面,以提示用户访问的页面不存在。
在web开发中,我们还可以把这个默认的action访问配置成主页,这样当用户访问一些不存在的action时,总会跳到主页上去。
通过此配置,只要是访问一个不存在的action便会转向到.../other目录下的error.jsp页面。
但是如果访问是其它的不存在资源则仍是报tomcat所标识的404错误,我们可以在web.xml中作如下配置:
<error-page>
<error-code>404</error-code>
<location>/other/404error.jsp</location>
</error-page>。