之前在第一个示例中,使用到的Acrtion是没有继承任何方法的,仅仅提供一个execute的方法和返回字符串值,那么就目前的主流开发来说,用到的关于Struts2的Action还是必须要继承ActionSupport的,从而能够更方便的操作CURD的操作,这一点跟struts中使用DispactherAction有些相似。
具体示例
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>index page</title>
</head>
<body>
<a href="msg/delete.action">删除</a>
<a href="msg/findbyid.action">查找</a>
<a href="msg/update.action">更新</a>
<a href="msg/add.action">新增</a>
</body>
</html>
注意看下这里的href中连接都是多加了msg
success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>Success Page</title>
</head>
<body>
<font color="blue" size="7">${msg}</font>
</body>
</html>
继承自ActionSupport的MsgAction.java
package com.javacrazyer.action;
import com.opensymphony.xwork2.ActionSupport;
public class MsgAction extends ActionSupport {
private static final long serialVersionUID = -805771504597006480L;
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String add(){
msg="新增成功";
return SUCCESS;
}
public String delete(){
msg="删除成功";
return SUCCESS;
}
public String update(){
msg="更新成功";
return SUCCESS;
}
public String findbyid(){
msg="查找成功";
return SUCCESS;
}
}
src/struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<!-- 请求参数的编码方式 -->
<constant name="struts.i18n.encoding" value="UTF-8"/>
<!-- 指定被struts2处理的请求后缀类型。多个用逗号隔开 -->
<constant name="struts.action.extension" value="action,do,go,xkk"/>
<!-- 当struts.xml改动后,是否重新加载。默认值为false(生产环境下使用),开发阶段最好打开 -->
<constant name="struts.configuration.xml.reload" value="true"/>
<!-- 是否使用struts的开发模式。开发模式会有更多的调试信息。默认值为false(生产环境下使用),开发阶段最好打开 -->
<constant name="struts.devMode" value="false"/>
<!-- 设置浏览器是否缓存静态内容。默认值为true(生产环境下使用),开发阶段最好关闭 -->
<constant name="struts.serve.static.browserCache" value="false" />
<!-- 指定由spring负责action对象的创建
<constant name="struts.objectFactory" value="spring" />
-->
<!-- 是否开启动态方法调用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<!-- Struts2中使用包来管理一组Action -->
<!-- package的属性
name: 指定包名。要唯一。方便于其它包的继承。
extends: 指定要继承的包名。一般是struts-default
namespace: 指定命名空间。不指定时,使用默认命名空间,默认命名空间为""
abstract: 指定是否为抽象包。抽象包中不能有Action的配置。
-->
<package name="mystruts" extends="struts-default" namespace="/msg">
<!-- action标签用来注册一个Action.常用属性
name: action的名字,用于匹配请求URI。必须的。不能出现"/"
class: 指定Action处理类的全限定名。未指定时,默认是ActionSupport。而ActionSupport的execute() 方法默认处理就是返回一个success字符串。
method: 指定要调用的处理方法.不指定时,默认调用execute方法
converter: 指定本Action类要使用到的转换器的全限定名
-->
<action name="*" class="com.javacrazyer.action.MsgAction" method="{1}">
<!-- result配置结果映射
name:指定结果的逻辑名。
type: 指定跳转的方式。默认是值dispatcher,表示请求分派。常用还有:redirect(重定向), freemarker(使用模板技术解析目标资源)
-->
<result name="success" >/success.jsp</result>
</action>
</package>
</struts>
上面说到result的配置跳转方式可以为两种,那么如果我配置成这种
<result name="success" type="redirect">/msg1.jsp?id=${id}</result>
这个id呢,就是MsgAction的属性,那么在msg1.jsp中,我们可想而知,id的值肯定是取不到的,关于为什么取不到值可以看看我之前写过的文章,有介绍重定向和请求分派的区别
相对于一般只需要pakage和action配置的struts.xml来说,这里我们在上面配置了更多信息,具体可根据喜好来选择,不过上面提到建议打开的实际项目中还是要配置上的
关于package中的namespace一直都是很多人非常头疼的配置,关键是不知道为什么要配置这个,并且配置有什么作用。
Action的请求URL由两部分组成:包的命名空间+Action的名称
如:<package ... namespace="/msg"> <action name="add"..></action></package>
最匹配的路径:http://server:port/appName/msg/add.action
下一步搜索的是:http://server:port/appName/add.action
那么为了验证这一句话,我们将index.jsp中的href中的msg都去掉
<a href="delete.action">删除</a>
<a href="findbyid.action">查找</a>
<a href="update.action">更新</a>
<a href="add.action">新增</a>
结果发现执行就报错There is no Action mapped for namespace / and action name update.
对于这个错误只要将namespace去掉就不会报错
也就是说验证了红色字体部分的是对的,得出的结论就是:凡是在package中配置了namespace的[假如值是'/msg']那么WEB页面对应的链接必须包含这个msg即:http://server:port/appName/msg/xx.action
接下来我们还有一个问题,如果struts.xml中配置了两个package呢,URL将匹配哪个?
在上面的struts.xml中最下方新增下面这段代码
<package name="yourstruts" extends="struts-default" namespace="/msg">
<action name="*" class="com.javacrazyer.action.MsgAction2" method="{1}">
<result name="success" >/success.jsp</result>
</action>
</package>
发现这段代码与第一个pakage的唯一区别就是名字不同,里面的action配置形式也完全一样,这样的话到底执行哪个Action呢?
MsgAction2.java
package com.javacrazyer.action;
import com.opensymphony.xwork2.ActionSupport;
public class MsgAction2 extends ActionSupport {
private static final long serialVersionUID = -805771504597006480L;
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String add(){
msg="新增成功2";
return SUCCESS;
}
public String delete(){
msg="删除成功2";
return SUCCESS;
}
public String update(){
msg="更新成功2";
return SUCCESS;
}
public String findbyid(){
msg="查找成功2";
return SUCCESS;
}
}
执行后发现结果执行的是MsgAction2.java这个类,如果交换两个package的配置顺序,那么执行结果是会执行原来的MsgAction.java.
由上面的结果我们得出又一个结论,那就是:在struts.xml中,对于多个package配置,如果其配置的namespace相同,extends相同,唯独name不同,并且里面配置的类形式都为
<action name="*" class="xxAction" method="{1}">
唯独class值不同,那么实际上匹配到的Action会是按从上到下顺序中,最下面的那个package中的action
至于成功页面中为什么${msg}能直接取出来Action中配置的属性[Action的属性知道吧,就是匹配表单元素信息的,所以Struts2的Action还是具有优势的],我会在接下来的文章中详细讲解