首页 > 代码库 > struts2的通配符与动态方法调用

struts2的通配符与动态方法调用

1、Action标签中的method属性

我们知道action默认的执行的方法是execute方法,但是一个action只执行一个方法我们觉得有点浪费,我们希望在一个action中实现同一模块的不同功能。怎么办呢?

思考:

           我们是否可以在execute()方法中添加一个判断,然后根据该判断选择我们执行的方法呢?我想struts2也是这样干的。不过是在execute之前的方法中进行的,判断的依据不是通过参数,而是通过取读配置文件或者其他得到的。

 

Struts2在Action中为我们提供了这样的一个属性:method,使用method属性可以指定我们希望执行的自定义方法。

 

    <!--              struts2框架运行时,默认执行action类中的execute方法              在action标签里面的method属性:指定的是要执行的action类中的哪个方法         -->        <!--<action name="bookAction" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>

 

我们的自定义方法有什么规范吗?

例子:

 

/*     *自定义方法     *        由public来修饰     *        必须是String返回类型     *        不能传参数     *        方法名自定义     *    总之,一句话:除了方法名与execute()不一样,其他所有的内容都一样      */    public String add() throws Exception{        System.out.println("bookAction ****** add");        return "add";    }

 

2、通配符的使用

         我们又发现,当多个action都指向同一个action的某一个方法的时候,我们就需要定义好多action,但这些action的代码几乎一致。这时候,我们想?应该如何优化呢。

         Struts2中提供了一种解决工具,通配符”*”.

简单例子:

         需求1:

  

        通配符映射示例(1):<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/a_add.do">通配符示例(1)</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/b_add.do">通配符示例(1)</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/c_add.do">通配符示例(1)</a><br/>    <br/>    <br/>

 

 原方案:

 

<action name="a_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>        <action name="b_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>        <action name="c_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>

 

通配符方式:

        

<!--              *,就是通配符,匹配的是不一样的内容,表示任意一字符串        -->        <!--<action name="*_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>

 

 

需求2:(这里不同点不仅仅是Action名了,结果也有变化)

        

    通配符映射示例(2):<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_add.do">图书</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/UserAction_add.do">用户</a><br/>    <br/>    <br/>

 

原方案:

        

<!--<action name="BookAction_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>                <action name="UserAction_add" class="cn.itcast.pattern.UserAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/UserAction.jsp</result>        </action>

 

通配符方式:

        

<!--             以上的两个Action配置可以改写                 {1}:表示匹配通配符匹配的第一个字符串            这个action会与前面的name为*_add的冲突        -->        <action name="*_add" class="cn.itcast.pattern.{1}" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/{1}.jsp</result>        </action><!--        

 

 

需求3:前面的基础上,方法也有变化

        

    通配符映射示例(3):<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_add.do">图书添加</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_delete.do">图书删除</a><br/>    <br/>    <br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/UserAction_add.do">用户添加</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/UserAction_delete.do">用户删除</a><br/>    <br/>    <br/>

 

原方案:

        

<action name="BookAction_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="add">/pattern/BookAction.jsp</result>        </action>        <action name="BookAction_delete" class="cn.itcast.pattern.BookAction" method="delete">            <result name="success">/pattern/success.jsp</result>        </action>        <action name="UserAction_add" class="cn.itcast.pattern.UserAction" method="add">            <result name="add">/pattern/UserAction.jsp</result>        </action>        <action name="UserAction_delete" class="cn.itcast.pattern.UserAction" method="delete">            <result name="success">/pattern/success.jsp</result>        </action>

 

通配符方式:

        

<!-- 以上的配置可以改成 -->        <!--              {2}匹配的就是*通配符匹配的第二个子串            {0}匹配的是通配符的整个串        -->        <action name="*_*" class="cn.itcast.pattern.{1}" method="{2}">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/{1}.jsp</result>        </action>

 

Ok,总结一下:

         “*”是struts2中的通配符

{1},{2}…等分别代表通配符匹配的第n个字符串

其实{0}这种写法也存在,比嗾使所有通配符匹配的字符串的拼接

 

3、动态方法调用

我们前面使用通配符的方式可以通过链接调用同一个action的不同方法,其实struts2还有一种方式可以达到前面的效果,那就是动态方法调用。

 

如何执行动态方法调用?

         首先,对链接的url有要求。例如:

        

   动态方法调用示例:<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction!add.do">图书添加</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction!delete.do">图书删除</a><br/>    <br/>    <br/>

 

格式为…./namespace+actionName+!+methodName

 

对应的action:

 

<!--              动态方法调用:                页面中请求连接:namespace+actionName+"!"+执行方法名                在struts.xml文件中,不用配置method属性,而是通过页面的链接动态执行指定方法                动态方法调用,不经常使用,经常使用的是通配符                动态方法调用,默认是开启状态                 关闭 动态方法调用 :                    <constant name="struts.enable.DynamicMethodInvocation" value=http://www.mamicode.com/"false" />        -->        <action name="BookAction" class="cn.itcast.pattern.BookAction">            <result name="add">/pattern/BookAction.jsp</result>        </action>

 

4、全局result

前面的例子可以发现,我们的result name=”success”执行的代码都是一样的,那么为什么我们不可以将它封装起来呢?一劳永逸。

Struts2中提供了一个标签:<global-result>,它可以设置全包的结果类型

例子:

 

<!-- 我们在这里的result中的name=success多次调用,都是同样的结果,我们希望一劳永逸,可以在package下配置全局结果 -->        <!-- 配置全局结果类型,当然如果action中配置了优先执行action中的 -->        <!--              局部结果类型和全局结果类型的作用范围:                局部的:作用于某个action                全局的:作用于某个package        -->        <global-results>            <result name="success">/pattern/successGlobal.jsp</result>        </global-results>

 

5、action的一个小特点:多实例,线程安全

         这个只是简单了解一下,我们可以在action中重写一下无参构造,可以发现,每一次调用该action,都会执行该action中构造方法的内容

 

 

上面用的部分素材:

技术分享
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags" %><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href=http://www.mamicode.com/"<%=basePath%>">        <title>My JSP test.jsp starting page</title>        <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href=http://www.mamicode.com/"styles.css">    -->  </head>    <body>    访问BookAction_add测试action标签中的method属性<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/bookAction.do">测试</a><br/>    <br/>    <br/>        通配符映射示例(1):<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/a_add.do">通配符示例(1)</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/b_add.do">通配符示例(1)</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/c_add.do">通配符示例(1)</a><br/>    <br/>    <br/>        通配符映射示例(2):<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_add.do">图书</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/UserAction_add.do">用户</a><br/>    <br/>    <br/>    通配符映射示例(3):<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_add.do">图书添加</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_delete.do">图书删除</a><br/>    <br/>    <br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/UserAction_add.do">用户添加</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/UserAction_delete.do">用户删除</a><br/>    <br/>    <br/>    动态方法调用示例:<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction!add.do">图书添加</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction!delete.do">图书删除</a><br/>    <br/>    <br/>    通配符示例(4):<br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_add.do">图书添加</a><br/>    <a href=http://www.mamicode.com/"${pageContext.request.contextPath }/pattern/BookAction_delete.do">图书删除</a><br/>    <br/>    <br/>   全局result:<br/>   <a href=http://www.mamicode.com/"${pageContext.request.contextPath}/pattern/BookAction_find.do">图书查找</a><br/>      </body></html>
test.jsp
技术分享
package cn.itcast.pattern;import com.opensymphony.xwork2.ActionSupport;public class BookAction extends ActionSupport {        @Override    public String execute() throws Exception {        System.out.println("bookAction ****** execute");        return "success";    }    /*     * 在struts2框架中,action是多实例的     */    public BookAction(){        System.out.println("bookAction 的构造方法");    }    /*     *自定义方法     *        由public来修饰     *        必须是String返回类型     *        不能传参数     *        方法名自定义     *    总之,一句话:除了方法名与execute()不一样,其他所有的内容都一样      */    public String add() throws Exception{        System.out.println("bookAction ****** add");        return "add";    }        public String delete() throws Exception{        System.out.println("bookAction ****** delete");        return "success";    }        public String find() throws Exception{        System.out.println("bookAction ****** find");        return "success";    }        public String update() throws Exception{        return "success";    }}
BookAction.java
技术分享
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"    "http://struts.apache.org/dtds/struts-2.3.dtd"><struts>     <package name="pattern" namespace="/pattern" extends="struts-default">              <!-- 我们在这里的result中的name=success多次调用,都是同样的结果,我们希望一劳永逸,可以在package下配置全局结果 -->        <!-- 配置全局结果类型,当然如果action中配置了优先执行action中的 -->        <!--              局部结果类型和全局结果类型的作用范围:                局部的:作用于某个action                全局的:作用于某个package        -->        <global-results>            <result name="success">/pattern/successGlobal.jsp</result>        </global-results>                 <!--              struts2框架运行时,默认执行action类中的execute方法              在action标签里面的method属性:指定的是要执行的action类中的哪个方法         -->        <!--<action name="bookAction" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>                <action name="a_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>        <action name="b_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>        <action name="c_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>                -->        <!-- 以上的配置可以改写如下: -->        <!--              *,就是通配符,匹配的是不一样的内容,表示任意一字符串        -->        <!--<action name="*_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>                        -->                <!--<action name="BookAction_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/BookAction.jsp</result>        </action>                <action name="UserAction_add" class="cn.itcast.pattern.UserAction" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/UserAction.jsp</result>        </action>                -->        <!--             以上的两个Action配置可以改写                 {1}:表示匹配通配符匹配的第一个字符串            这个action会与前面的name为*_add的冲突        -->        <action name="*_add" class="cn.itcast.pattern.{1}" method="add">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/{1}.jsp</result>        </action><!--                        <action name="BookAction_add" class="cn.itcast.pattern.BookAction" method="add">            <result name="add">/pattern/BookAction.jsp</result>        </action>        <action name="BookAction_delete" class="cn.itcast.pattern.BookAction" method="delete">            <result name="success">/pattern/success.jsp</result>        </action>        <action name="UserAction_add" class="cn.itcast.pattern.UserAction" method="add">            <result name="add">/pattern/UserAction.jsp</result>        </action>        <action name="UserAction_delete" class="cn.itcast.pattern.UserAction" method="delete">            <result name="success">/pattern/success.jsp</result>        </action>                -->        <!-- 以上的配置可以改成 -->        <!--              {2}匹配的就是*通配符匹配的第二个子串            {0}匹配的是通配符的整个串        -->        <action name="*_*" class="cn.itcast.pattern.{1}" method="{2}">            <result name="success">/pattern/success.jsp</result>            <result name="add">/pattern/{1}.jsp</result>        </action>                        <!--              动态方法调用:                页面中请求连接:namespace+actionName+"!"+执行方法名                在struts.xml文件中,不用配置method属性,而是通过页面的链接动态执行指定方法                动态方法调用,不经常使用,经常使用的是通配符                动态方法调用,默认是开启状态                 关闭 动态方法调用 :                    <constant name="struts.enable.DynamicMethodInvocation" value=http://www.mamicode.com/"false" />        -->        <action name="BookAction" class="cn.itcast.pattern.BookAction">            <result name="add">/pattern/BookAction.jsp</result>        </action>                                <action name="BookAction_find" class="cn.itcast.pattern.BookAction" method="find">        </action>                        </package>    </struts>
struts_pattern.xml

 

  

 

struts2的通配符与动态方法调用