Struts2中Action的通配符使用方法

在这篇《Struts2学习之配置单个Action多控制处理逻辑》文章中,讲到指定method属性时,列举了以下的配置代码:

 代码如下 复制代码

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />

    <package name="lee" extends="struts-default" namespace="/">
        <action name="loginAction" class="com.jellythink.practise.LoginAction" method="login">
            <result name="input">/login.jsp</result>
            <result name="error">/error.jsp</result>
            <result name="success">/success.jsp</result>
        </action>

        <action name="registAction" class="com.jellythink.practise.LoginAction" method="regist">
            <result name="regist">/regist.jsp</result>
        </action>
    </package>
</struts>

可以发现,上面配置的两个Action,有很大一部分是类似的,存在冗余的现象。在Struts2框架中,允许使用通配符的方式进行配置。下面就利用Struts2框架的这一特性对上述这段配置代码进行重构。

重构第一步

在配置<action .../>元素时,允许在指定name属性时使用模式字符串(即用“*”代表一个或多个任意字符),接下来就可以在class、method属性及<result .../>子元素中使用{N}的形式来代表前面第N个星号所匹配的子串。基于此,文章一开始的配置代码可以重构为以下这样:

 代码如下 复制代码

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />

    <package name="lee" extends="struts-default" namespace="/">
        <action name="*Action" class="com.jellythink.practise.LoginAction" method="{1}">
            <result name="input">/{1}.jsp</result>
            <result name="error">/error.jsp</result>
            <result name="success">/success.jsp</result>
        </action>
    </package>
</struts>

上面的<action name="*Action" .../>元素不是定义了一个普通Action,而是定义了一系列的逻辑Action。只要用户请求的URL是*Action.action的模式,都可以使用该Action来处理。配置该action元素时,还指定method属性,但该method属性使用了一个表达式{1},该表达式就是name属性值中第一个*的值。例如:如果用户请求的URL为loginAction.action,则调用对应的login方法;如果为registAction.action,则调用regist方法。对于<result .../>子元素中使用的/{1}.jsp也是同样的道理。

重构第二步

更多时候,我们希望action对应的class属性也可以进行模式匹配,这样的话灵活性更高。比如现在有两个Action类,分别为:com.jellythink.practise.LoginAction和com.jellythink.practise.RegistAction,这两个类分别完成登陆与注册行为。当action的name匹配到loginAction时,则对应的class则为com.jellythink.practise.LoginAction;当匹配到registAction时,则对应的clas则为com.jellythink.practise.RegistAction。按照这样的需求,上述的配置代码又可以修改为这样:

 代码如下 复制代码

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />

    <package name="lee" extends="struts-default" namespace="/">
        <action name="*_*" class="com.jellythink.practise.{1}Action" method="{2}">
            <result name="input">/{2}.jsp</result>
            <result name="error">/error.jsp</result>
            <result name="success">/success.jsp</result>
        </action>
    </package>
</struts>

在上述配置代码中,action的name属性为*_*,这需要我们在前台页面设置action的值时按照指定的规则进行设定,例如:类名_方法名。当用户请求的URL是Login_login.action的模式时,则{1}代表的值为Login,而对应的{2}代表的值为login;同理,当请求为Regist_regist.action的模式时,则{1}代表的值为Regist,而对应的{2}代表的值为regist。

通过这种方式,配置代码的灵活性更高,写法更简单。

到底使用哪个?

通过使用模式匹配的方式,就会引申出另一个问题。比如有下面这段配置代码:

 代码如下 复制代码

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />

    <package name="lee" extends="struts-default" namespace="/">
        <!--Action1-->
        <action name="*Action" class="com.jellythink.practise.{1}Action" method="{1}">
            <result name="input">/{1}.jsp</result>
            <result name="error">/error.jsp</result>
            <result name="success">/success.jsp</result>
        </action>

        <!--Action2-->
        <action name="getBookInfoAction" class="com.jellythink.practise.GetBookInfoAction">
            <result name="error">/error.jsp</result>
            <result name="success">/success.jsp</result>
        </action>

        <!--Action3-->
        <action name="*" class="com.jellythink.practise.DefaultAction">
            <result name="success">/success.jsp</result>
        </action>
    </package>
</struts>

问题是,如果客户端请求的URL是getBookInfoAction.action,那么到底匹配哪个Action呢?对于Struts2框架来说,规则是这样的:

如果请求URL是getBookInfoAction.action,如果struts.xml文件中有名为getBookInfoAction的Action配置,则一定由该Action来处理用户请求
如果struts.xml文件中没有名为getBookInfoAction的Action配置,则搜寻name属性值能匹配getBookInfoAction的Action,例如name为Action或,*Action并不会比*更优先匹配getBookInfoAction的请求,这取决于这两个Action定义的先后顺序

例子

1、 ActionMethod:Action执行的时候并不一定要执行execute方法,可以在配置文件中配置action的时候用“method”属性来指定执行哪个方法,也可以在url地址中动态指定(动态方法调用DMI)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="user" extends="struts-default" namespace="/user">
        <action name="userAdd" class="com.bjsxt.struts2.user.action.UserAction" method="add">
            <result>/user_add_success.jsp</result>
        </action>
        <action name="user" class="com.bjsxt.struts2.user.action.UserAction">
            <result>/user_add_success.jsp</result>
            <result name="delete">/user_delete_success.jsp</result>
        </action>
    </package>
</struts>

Index.jsp页面的内容:

 代码如下 复制代码
<?xml version="1.0" encoding="GB18030" ?>
<%@ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding="GB18030"%>
<% String context = request.getContextPath(); %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030" />
<title>Insert title here</title>
</head>
<body>
     <a href="<%=context %>/user/userAdd">添加用户</a><br />
     <a href="<%=context %>/user/user!add">添加用户</a><br />
     <a href="<%=context %>/user/user!delete">删除用户</a><br />
</body>
</html>

UserAction的内容:

 代码如下 复制代码
package com.bjsxt.struts2.user.action;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
     public String add() {
         return SUCCESS;
     }
     public String delete(){
         return "delete";
     }   
}

2、 使用通配符
Strtus.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="actions" extends="struts-default" namespace="/actions">
        <action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">
            <result>/Student{1}_success.jsp</result>
        </action>
       
        <action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
            <result>/{1}_{2}_success.jsp</result>
        </action>
    </package>
</struts>

Action的内容:

 代码如下 复制代码
public class CourseAction extends ActionSupport {
     public String add() {
         return SUCCESS;
     }
     public String delete() {
         return SUCCESS;
     }
}
public class StudentAction extends ActionSupport {
     public String add() {
         return SUCCESS;
     }
     public String delete() {
         return SUCCESS;
     }
}
public class TeacherAction extends ActionSupport {
     public String add() {
         return SUCCESS;
     }
     public String delete() {
         return SUCCESS;
     }
}

Index.jsp页面的内容:

 代码如下 复制代码
<?xml version="1.0" encoding="GB18030" ?>
<%@ page language="java" contentType="text/html; charset=GB18030"
     pageEncoding="GB18030"%>
<%String context = request.getContextPath();%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
     <head>
         <meta http-equiv="Content-Type" content="text/html; charset=GB18030" />
         <title>Insert title here</title>
     </head>
     <body>
         使用通配符,将配置量降到最低<br />
         <a href="<%=context%>/actions/Studentadd">添加学生</a>
         <a href="<%=context%>/actions/Studentdelete">删除学生</a><br />
         不过,一定要遵守"约定优于配置"的原则<br />
         <a href="<%=context%>/actions/Teacher_add">添加老师</a>
         <a href="<%=context%>/actions/Teacher_delete">删除老师</a>
         <a href="<%=context%>/actions/Course_add">添加课程</a>
         <a href="<%=context%>/actions/Course_delete">删除课程</a>
     </body>
</html>

相应的jsp页面有:
Course_add_seccess.jsp
Course_delete_success.jsp
Teacher_add_seccess.jsp
Teacher_delete_success.jsp
Studentadd_success.jsp
Studentdelete_success.jsp

总结

在日后的工作中,使用这样的技巧来重构代码,会带来很多好处,比如配置代码更加精简了,更加容易管理和维护了,更加容易读懂了等等。如果你说你不想用这些东西,那也好,至少你需要知道有这么个东西的存在,好让你去读懂别人写的代码。

时间: 2024-07-30 16:20:05

Struts2中Action的通配符使用方法的相关文章

Struts2中Action接收参数的方法

Struts2中Action接收参数的方法主要有以下三种: 1.使用Action的属性接收参数:     a.定义:在Action类中定义属性,创建get和set方法:     b.接收:通过属性接收参数,如:userName:     c.发送:使用属性名传递参数,如:user1!add?userName=Magci: 2.使用DomainModel接收参数:     a.定义:定义Model类,在Action中定义Model类的对象(不需要new),创建该对象的get和set方法:    

Struts2中Action中是否需要实现Execute方法_java

今天有朋友问我Struts2中Action必须实现execute方法吗?顺利的回答出来了. 其实分两种情况: 1)如果你的Action类是继承自ActionSupport或是BaseAction的话,确切的说是重写了execute方法,ActionSupport里的默认实现就是返回"success"视图.因此,你可以不实现execute方法,只要你的struts.xml里有"success"对应的result即可. <action name="doR

struts2中action中的方法无故被提交两次

问题描述 struts2中action中的方法无故被提交两次 import java.io.UnsupportedEncodingException; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.hsp.book.domain.Book;import com.hsp.book.service.BookService;import c

struts2.0-ssh struts2中 action执行两次

问题描述 ssh struts2中 action执行两次 1 排除重复提交的可能 2 点击页面中的超链接,action 执行两次:但在地址栏中输出地址,action只执行了一次(这个让我很震惊!) 3 执行的action 方法名为add(), 不存在get默认执行的情况 解决方案 struts2 action执行两次的原因struts2 中action执行两次的问题struts2 json插件执行原理 action执行两次 解决方案二: 这个肯定是你代码出错了,你应该把使用的界面代码贴出来 解决

input视图-Struts2中action出现错误返回input的机制

问题描述 Struts2中action出现错误返回input的机制 2C 当action出现错误后,如何返回的input?通过哪个类返回的?希望大神们说的尽量详细点,先谢过了! 解决方案 链接:http://pan.baidu.com/s/1nuUL6OD 密码:igtz 解决方案二: return ""input"";或者return Action.Input;就OK了呀然后返回的就是input 如果你说的是显示错误信息的话调用addFieldError()方法时

javaweb-关于struts2中action层的问题

问题描述 关于struts2中action层的问题 今天公司要我把实体entity复制一份,写在一个类中,查出来的数据通过BeanUtils.copyProperties放在复制的那个类中,action不实现modelDriven,而是get/set复制的这个类.前面这些只是今天遇到的,大概说一下. 主要想问的是,公司那边不让写这一句: 那我查到的东西,怎么在jsp页面写呢?我唯一能想到的是在action中写一个List属性,get/set.不过我觉得这样好麻烦,他为什么不让使用这一句呢?我搞不

struts2中Action到底是什么,怎么理解

问题描述 struts2中Action到底是什么,怎么理解 1.配置完web.xml 2.创建视图页面login.jsp 3.创建业务控制器LoginAction类 (解释说:创建业务控制器LoginAction类,该类为程序的Action类) 4.配置LoginAction类 (解释说:当Action处理完客户端请求后返回一个字符串,没个字符串对应一个视图) 那么这个Action到底是什么,是一个类吗?怎么理解它,它和用于标签的有什么区别. 解决方案 首先,你了解Servlet么?Servle

struts2中action和field级别错误处理

在struts2中,一般的action都继承ActionSupport这个类,可以重写public void validate()来进行数据校验,对应提示信息来说一般有两个比较常用的方法就是this.addFieldError("field name","error message"); 和 this.addActionError("error message");两个方法. 由于在ActionSupport这个类实现了ValidationAwa

关于struts2中action参数传递的问题

问题描述 我的action返回一个值后会转发到jsp页面,在jsp页面中代码如下:<s:propertyvalue="#parameters.id[0]"/>请问我在action中要怎么用代码设置,能在jsp中接受到,原来在servlet中代码如下:RequestDispatcherrd=request.getRequestDispatcher("/student/createInteract.jsp?id="+id);rd.forward(reques