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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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="${pageContext.request.contextPath }/pattern/a_add.do">通配符示例(1)</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/b_add.do">通配符示例(1)</a><br/>
    <a href="${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="${pageContext.request.contextPath }/pattern/BookAction_add.do">图书</a><br/>
    <a href="${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="${pageContext.request.contextPath }/pattern/BookAction_add.do">图书添加</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction_delete.do">图书删除</a><br/>
    <br/>
    <br/>
    <a href="${pageContext.request.contextPath }/pattern/UserAction_add.do">用户添加</a><br/>
    <a href="${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="${pageContext.request.contextPath }/pattern/BookAction!add.do">图书添加</a><br/>
    <a href="${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="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="<%=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="styles.css">
    -->

  </head>
  
  <body>
    访问BookAction_add测试action标签中的method属性<br/>
    <a href="${pageContext.request.contextPath }/pattern/bookAction.do">测试</a><br/>
    <br/>
    <br/>
    
    通配符映射示例(1):<br/>
    <a href="${pageContext.request.contextPath }/pattern/a_add.do">通配符示例(1)</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/b_add.do">通配符示例(1)</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/c_add.do">通配符示例(1)</a><br/>
    <br/>
    <br/>
    
    通配符映射示例(2):<br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction_add.do">图书</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/UserAction_add.do">用户</a><br/>
    <br/>
    <br/>
    通配符映射示例(3):<br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction_add.do">图书添加</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction_delete.do">图书删除</a><br/>
    <br/>
    <br/>
    <a href="${pageContext.request.contextPath }/pattern/UserAction_add.do">用户添加</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/UserAction_delete.do">用户删除</a><br/>
    <br/>
    <br/>
    动态方法调用示例:<br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction!add.do">图书添加</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction!delete.do">图书删除</a><br/>
    <br/>
    <br/>
    通配符示例(4):<br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction_add.do">图书添加</a><br/>
    <a href="${pageContext.request.contextPath }/pattern/BookAction_delete.do">图书删除</a><br/>
    <br/>
    <br/>
   全局result:<br/>
   <a href="${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="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的通配符与动态方法调用的主要内容,如果未能解决你的问题,请参考以下文章

Struts2系列:通配符和动态方法调用

Struts2 Action中动态方法调用通配符的使用

struts2的动态方法调用(DMI)和通配符映射

第三章Struts2 Action中动态方法调用通配符的使用

Struts2.5动态方法调用action和使用通配符访问action

Struts2.5的DMI与新增的SMI