【Java EE 学习 34】【struts2学习第一天】

一、struts2简介

    struts2是一个用来开发MVC应用程序的框架。它提供了Web应用程序开发过程中的一些常见问题的解决方案。

  1.struts2的作用域范围:三层架构当中的第一层,相当于MVC层,其出现的作用就是标准化MVC,让程序员在某个标准阿下进行程序的开发。

  2.struts2的下载:http://struts.apache.org/download.cgi#struts2324

          jar包、源码、文档一应俱全。

  3.发展历史:Struts1是世界上第一个MVC的框架,在2001年发布;Struts2不是Struts1的升级,是由WebWork发展起来的,吸收了Struts1和WebWork的优点。

  4.Struts2能够解决的问题:

    (1)页面导航活动的开始

    (2)用户输入数据的合法性验证

    (3)统一的布局

    (4)可扩展性

    (5)国际化和本地化

    (6)支持Ajax 

    (7)解决表单的重复提交问题

    ......

  5.struts2的工作原理:写到这里突然想到了王建老师,之前王健老师教我们的东西突然发现和struts2极其相似,真的非常感谢王健老师。不赘述。见之前的BaseServlet原理。

  6.struts2的第一个小项目:Hello,World!

    (1)应当加入的基础包包括:asm-3.3.jar、asm-commons-3.3.jar、asm-tree-3.3.jar、commons-fileupload-1.3.1.jar、commons-io-2.2.jar、commons-lang-2.4.jar、commons-lang3-3.2.jar、commons-logging-1.1.3.jar、freemarker-2.3.22.jar、javassist-3.11.0.GA.jar、ognl-3.0.6.jar、struts2-core-2.3.24.jar、xwork-core-2.3.24.jar    一共13个包。

    (2)修改index.jsp页面:

 1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5   <head>
 6     <meta http-equiv="content-type" content="text/html;charset=utf-8">
 7     <title>Insert title here !</title>
 8   </head>
 9   
10   <body>
11       <a href="<c:url value='/myaction/helloWorldAction.action'/>">hello,world</a>  
12   </body>
13 </html>
index.jsp

    (3)新建类:HelloWorldAction,该类实现了com.opensymphony.xwork2.Action接口。

 1 /**
 2  * 
 3  */
 4 /**
 5  * @author kdyzm
 6  *
 7  */
 8 package com.kdyzm.action;
 9 
10 import com.opensymphony.xwork2.Action;
11 
12 public class HelloWorldAction implements Action
13 {
14     @Override
15     public String execute() throws Exception {
16         System.out.println("Hello,World!");
17         return "success";
18     }
19     
20 }
HelloWorldAction.java

    (4)在src目录下新建文件struts.xml(文件名和位置不能改变)

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <!DOCTYPE struts PUBLIC
 3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
 4     "http://struts.apache.org/dtds/struts-2.3.dtd">
 5 <struts>
 6     <!-- namespace的书写必须加上/ -->
 7     <package name="firstpackage" namespace="/myaction" extends="struts-default">
 8         <action name="helloWorldAction" class="com.kdyzm.action.HelloWorldAction">
 9             <result name="success">/information/success.jsp</result>
10         </action>
11     </package>
12 </struts>
struts.xml

    (5)配置过滤器

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
 3     <filter>
 4         <filter-name>strutsFilter</filter-name>
 5         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 6     </filter>
 7     <filter-mapping>
 8         <filter-name>strutsFilter</filter-name>
 9         <url-pattern>*.action</url-pattern>
10     </filter-mapping>
11 </web-app>
web.xml

    (6)测试

      

    请求结果:

      

    (7)struts.xml配置文件详解:

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <!DOCTYPE struts PUBLIC
 3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
 4     "http://struts.apache.org/dtds/struts-2.3.dtd">
 5 <struts>
 6     <!-- namespace的书写必须加上/ -->
 7     <package name="firstpackage" namespace="/myaction" extends="struts-default">
 8         <action name="helloWorldAction" class="com.kdyzm.action.HelloWorldAction">
 9             <result name="success">/information/success.jsp</result>
10         </action>
11     </package>
12 </struts>

      <!DOCTYPE>标签节点是需要遵循的规范,这里有一个dtd文件,我们需要遵循该dtd的标准在struts.xml文件中进行修改!

      struts标签是根节点标签;

      package标签是包标签,其name属性自定义,但是其namespace属性却是个非常重要的属性,该属性必须和index.jsp中a标签定义的完全相同才行;extends指明了继承了哪个包,这里是默认的包struts-default,该包是非常重要的包,如果没有该包,就没有了使用struts2的意义,因为该包定义了很多拦截器和结果集类型,继承了该包可以直接使用这些拦截器和结果集。

      action标签对应着处理jsp页面请求的一个方法,默认方法是Action接口的execute()方法,而class属性指明了使用的类的路径。

      result标签对应着实现了Action接口的类调用方法之后返回的结果,name属性必须和返回结果相一致,这里可以有多个result标签以应对不同的处理结果;result标签中的文本节点标志着需要转发或者重定向到某个页面的页面路径。默认的方法是转发。这些都可以查看底层源代码查看到。

    (8)小练习源代码:https://github.com/kdyzm/day34_struts_HelloWorld


二、拦截器

  1.Struts2工作的流程:客户端发起请求->Struts2过滤器拦截请求并将请求转交给Action处理->Action处理请求并返回一个字符串结果->结果集匹配,并转发或者重定向到指定的页面。

  2.图示:

    

  3.分离关注(拦截器)

    (1)什么是分离关注

      过滤器中的过滤任务很多放在一个方法中会导致方法过于庞大,可以将方法中的若干个步骤委托给若干个类来完成,这种解决方式就是分离关注,过滤器负责调用这些类。

  4.拦截器举例

    (1)处理Cookies的拦截器(处理web中的cookies)

    (2)令牌拦截器(处理表单重复提交)

    (3)参数拦截器

    (4)文件上传拦截器

    (5)i18n拦截器(处理国际化)

      ......

      自定义拦截器

  5.过滤器和拦截器的异同

    相同点:都起拦截作用

    不同点:

      (1)作用范围不同。过滤器属于J2EE的规范,在所有web工程中都可以使用;拦截器是struts2框架独有的,离开了struts2框架,拦截器将不能使用,拦截器是依赖于Struts2框架的。

      (2)完成的功能不同。过滤器负责解析xml,拦截请求的路径;其他拦截功能交给拦截器处理。

      (3)执行顺序不同。先执行过滤器,再执行拦截器。

  6.struts-default.xml文件概述

    (1)struts-default.xml文件的位置:位于struts2-core-x.x.x.jar下。

    (2)里面的核心内容是包名为struts-default的包

    <package name="struts-default" abstract="true">

      abstract="true"表示该包是抽象的,也就是说该包的作用就是让其它包继承的,该包中没有<result></result>标签。

    (3)package中定义了结果集类型,用<result-type>标签表示。

    (4)package包中主体是拦截器的定义和相关配置,使用标签<interceptors>来表示。

    (5)interceptor标签:声明拦截器,name属性是拦截器名称,唯一;class属性指明了拦截器类的完整路径。

<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>

    (6)interceptor-stack标签:定义拦截器栈的标签。可以将其看成一个集合。其拦截顺序是从上到下。name属性指明了该拦截器的名称。其中有一个比较特殊的拦截器栈:defaultStack,该拦截器栈是默认的拦截器栈。但并非是因为名字的原因,这实际上是经过配置得到的。见default-interceptor-ref标签。

    (7)default-interceptor-ref标签:指定默认的拦截器栈。

  7.有两个配置文件:struts-default.xml和struts.xml两个配置文件,那么那个配置文件优先生效?

    在org.apache.struts2.dispatcher.Dispatcher类中定义了一个常量:DEFAULT_CONFIGURATION_PATHS

 /**
     * Provide list of default configuration files.
     */
    private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";

    该常量定义了将要加载的配置文件,以及加载的顺序,后者的配置将会覆盖前者的配置,后者的配置优先生效。


三、struts2的基本配置

  1.struts2中action的访问路径由两部分组成:包的命名空间+action的名称。

    例如之前例子中使用的路径:/myaction/helloWorldAction.action,其中/myaction是命名空间,helloWorldAction是action名字。

    struts.xml文件中配置的package标签的属性namespace的值应当和/myaction匹配,所谓匹配,并不一定是要完全相同,这是后话;

    package标签下的节点action,其name属性值必须是helloWorldAction。

  2.action的后缀名必须是.action吗

    .action的后缀名是通过配置得到的,该配置允许使用.action后缀名,也允许使用不带后缀名的访问

    怎么查看该配置文件:在struts2-core-x.x.x.jar包下,找到org.apache.struts2包,在该包下有default.properties配置文件,该配置文件下有该键值对:

### Used by the DefaultActionMapper
### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do
### The blank extension allows you to match directory listings as well as pure action names
### without interfering with static resources, which can be specified as an empty string
### prior to a comma e.g. struts.action.extension=, or struts.action.extension=x,y,z,,
struts.action.extension=action,,

    通过注释我们可以知道,后缀名可以通过该字段来配置,两个,表示可以不使用后缀名来制定action后缀,如果允许多个后缀名,则每个后缀名之间使用,来隔开。如

struts.action.extension=action,jnlp,do

  3.action的搜索顺序

    (1)例如获得请求路径的URL为:http://localhost:8080/actionDemo/path1/path2/path3/helloWorldAction.action

    (2)在struts.xml文件中,首先寻找namespace为/path1/path2/path3的命名空间,如果找不到,则寻找/path1/path2的命名空间,如果还是找不到,则寻找/path1的命名空间,如果还是找不到,则到默认的命名空间中寻找。默认的命名空间为/,如果不写namespace属性,则默认该属性为值为/。如果在默认的命名空间中还是找不到,则直接报错。页面提示找不到Action。

    (3)例子:

       正常情况下:<a href="<c:url value='/myaction/helloWorldAction.action'/>">hello,world</a>  访问成功

       两种特殊情况:<a href="<c:url value='/myaction/x/helloWorldAction.action'/>">hello,world</a>  这种情况也可以访问成功;

       但是这种情况下就会访问失败了:<a href="<c:url value='/x/myaction/helloWorldAction.action'/>">hello,world</a>  

      

  4.struts2中的各项默认配置

    (1)如果没有给action指定class属性,那么会默认使用com.opensymphony.xwork2.ActionSupport类。在struts.xml文件中的最后一项配置对该项加以说明了。

<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

    通常在编写Action类的时候,会对该类进行扩展。

    (2)如果没有给action标签指定method属性,那么会默认使用调用类中的execute()方法。

    (3)如果没有给result标签配置name属性,那么会默认使用默认的name属性name="success"

    (4)如果没有找到相对应的Action,系统会抛出异常,可以进行配置,当找不到指定的Action的时候使用默认的Action。关键的是使用/命名空间和default-action-ref标签。

<package name="default-package" namespace="/" extends="struts-default">
        <default-action-ref name="errorAction"></default-action-ref>
        <action name="errorAction" class="com.kdyzm.test.helloworld.HelloWorldAction">
            <result name="success">
                <param name="location">
                    /information/success.jsp
                </param>
            </result>
        </action>
    </package>

      配置找不到系统资源的时候自动跳转主页:暂定

  5.struts.xml文件中的常量定义。

    struts2中的常量可以在struts.xml中定义也可以在struts.properties中定义。

    (1)struts.xml中配置常量的方法

<constant name="" value=""></constant>

      举例:如需要配置action访问的后缀名,则需要如此这般配置

<constant name="struts.action.extension" value="do,www,,"></constant>

      但是配置完成的时候应当注意有可能需要改变web.xml文件中的过滤器配置。

    (2)struts.properties文件中修改常量的方法:在class路径下创建一个struts.properties文件,在该文件中添加常量的修改,如

struts.action.extension=do,www,,

    (3)一个常量可以在多个文件中配置,所以我们需要掌握struts2中加载常量的搜索顺序。

        struts-default.xml

        struts-plugin.xml

        struts.xml

        struts.properties(这个需要自己动手创建,在class路径下,即src目录下创建)

        web.xml

      如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值

  6.struts2中常用的常量介绍

      下面介绍得这些常量都可以在struts.properties文件中找到。

    (1)struts.i18n.encoding=UTF-8

      指定默认的编码集,作用于HttpServletRequest的setCharacterEncoding方法和freemarker、velocity的输出。

    (2)struts.action.extension=action,,略

    (3)struts.serve.static.browserCache=false

      设置浏览器是否缓存静态内容,默认值为true(生产阶段使用),开发阶段最好设置为false。

    (4)struts.i18n.reload=true

      配置当国际化资源文件被修改的时候重新加载该国际化资源文件。默认值是false(不重新加载),true为重新加载。

    (5)struts.configuration.xml.reload=true

      配置当struts.xml文件被修改的时候是否重新加载该文件,默认值是false(不重新加载),true为重新加载

    (6)struts.devMode=true

      是否开启开发模式,默认值是false(不开启),如果开启的话会自动将struts.i18n.reload和struts.configuration.xml.reload置为true,这样就不需要手动开启(4)(5)了。

### when set to true, Struts will act much more friendly for developers. This
### includes:
### - struts.i18n.reload = true
### - struts.configuration.xml.reload = true
### - raising various debug or ignorable problems to errors
###   For example: normally a request to foo.action?someUnknownField=true should
###                be ignored (given that any value can come from the web and it
###                should not be trusted). However, during development, it may be
###                useful to know when these errors are happening and be told of
###                them right away.
struts.devMode = false

    (7)struts.ui.theme=simple

      视图主题,默认的是xhtml

    (8)struts.objectFactory=spirng

      和spring集成的时候指定由spring负责action对象的创建,默认值是spring。

    (9)struts.enable.DynamicMethodInvocation=true

      设置struts2是否支持动态方法调用,默认值是false(禁用动态方法调用),如果需要开启动态方法调用,则需要设置为true

    (10)struts.multipart.maxSize=2097152

      设置上传文件的大小的上限。

  7.指定多个struts配置文件。

    在大多部分的应用中,随着应用规模的增加,系统中的Action数量也会大量增加,导致struts.xml配置文件变得异常臃肿。为了避免struts.xml配置文件变得过于庞大、臃肿,我们可以将一个struts.xml文件分割称为多个配置文件,然后在struts.xml配置文件中包含其他配置文件。通过<include>配置文件可以达到该效果。

    include标签包含有一个file属性,该属性指明了配置文件的位置,一般将该配置文件放在某个包中,file的属性值的写法和导入包的方法差不多,但是需要将.改成/

    使用方法示例:

<include file="com/kdyzm/test/hello_struts.xml"></include>

    使用该标签的好处就是便于管理,在团队开发中比较有效。


四、结果类型

  1.每个action方法都将会返回一个String类型的值,Struts将根据这个值来决定响应什么结果。

  2.每个Action声明都必须包含有数量足够多的result元素,每个result元素分别对应着action方法中的一个返回值。

  3.result元素可以有下面两个属性

    (1)name属性:结果的名字,必须和Action方法的返回值相匹配,默认值是success

    (2)type属性:响应结果的类型,默认值是dispatcher

  4.有哪些结果集类型,通过struts-default.xml文件可以查看到。

<result-types>
            <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
            <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
            <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
            <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
            <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
            <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
            <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
            <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
            <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
            <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
            <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
        </result-types>

    注意name为dispatcher的那一栏,最后有一个default属性,也就是说默认的结果集类型是dispatcher,该结果集类型表示将会以转发的方式跳转到指定的页面,这样request对象中的数据就不会丢失了。

  5.dispatcher结果集类型是最常见的结果集类型,也是struts2框架中默认使用的结果集类型。

    (1)该结果类型有一个location参数,它是一个默认参数,在result标签中使用param标签,标签属性name值使用上location是标准的结果集定义的方法。

      也就是说,一下的下发也是可以的,而且是推荐写法:

       <result name="success">
                <param name="location">
                    /resultTestAction/answer1.jsp
                </param>
            </result>

      name=location:     该配置将会调用ServletDispathcerResult的父类StrutsResultSupport中的setLocation()方法,传递的字符串"location"代表该类中的一个属性名, 最终会将转向页面的url传递给location属性:

      

源代码实现查看:org.apache.struts2.dispatcher.ServletDispatcherResult极其父类StrutsResultSupport中的源代码。

    (2)综上所得,可以得到结论,即StrutsResultSupport使用setLocation方法得到转发的页面url,然后ServletDispatcherResult类中的响应方法进行页面的转发。

      关于ServletDispathcerResult怎样进行转发的请查看源代码。

  6.结果类型redirect:重定向到指定的资源

    接收的参数:location:用来指出重定向的目的地

          parse:用来指出是否把location参数的值视为一个OGNL表达式来解释,默认值是true。

  7.结果类型redirectAction:结果类型将相应重定向到另外一个Action。

    接收的参数:actionName:指定目的地动作的名字,它是默认属性

          namespace:指定目的地动作的命名空间。如果没有配置该参数,Struts会把当前Action所在的命名空间作为“目的地”的命名空间

    关于底层代码,查看struts-default.xml文件中的响应结果类型选项对应的class值。

    值得一提的是该结果类型使用的底层的重定向方法实际上和6中的重定向完全相同,都是java Web中使用的重定向方法。


五、通配符映射

  1.问题的提出:一个Web应用可能有成百上千个action声明,如果一一映射到struts.xml文件,则文件将会变得极其臃肿。可以使用struts提供的通配符映射机制将多个彼此相似的映射关系简化为一个映射关系。

  2.通配符映射规则:

    (1)若找到多个匹配,没有通配符的那个将会胜出

    (2)若指定的动作不存在,struts将会尝试将这个URL和任意一个包含着通配符*的动作名及进行匹配。

    (3)若strus找到的匹配选项不止一个,那么struts找到的最后一个匹配选项将会胜出。

    (4)被通配符匹配到的URI字符串的字串可以用{1},{2}来引用。{1}匹配第一个字串,{2}匹配第二个字串,{0}匹配整个URI

    (5)可以匹配零个或者多个字符,但是不包括/字符,如果想要把/字符包括在里面,需要使用"",如果需要对某个字符进行转义,需要使用。

  3.通配符映射实例1:*通配符测试

    (1)新建Action:PatternTestAction

package com.kdyzm.p02.patternDemo;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class PatternTestAction extends ActionSupport{
    private static final long serialVersionUID = 1L;
    @Override
    public String execute() throws Exception {
        HttpServletRequest request=ServletActionContext.getRequest();
        String url=request.getRequestURI();
        System.out.println(url);
        return "success";
    }
}

      这里的Action一旦有客户端请求访问就会立即将请求的页面地址的uri打印出来。

    (2)新建自己的struts.xml文件:在和PatternTestAction类同一个目录下新建一个自己的struts配置配置文件:pattern_struts.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE struts PUBLIC
 3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
 4     "http://struts.apache.org/dtds/struts-2.3.dtd">
 5 <struts>
 6     <package name="pattern_struts" namespace="/mypattern" extends="struts-default">
 7         <action name="*_pattern" class="com.kdyzm.p02.patternDemo.PatternTestAction">
 8             <result name="success">
 9                 <param name="location">
10                     /pattern/only.jsp
11                 </param>
12             </result>
13         </action>
14     </package>
15 </struts>

      注意第7行中的name的书写方式,*将会匹配所有,包括测试页面中的a、b、c,凡是Action名字其后缀名为_pattern的Action都将会被匹配。

     (3)jsp请求页面:

<%@ page isELIgnored="false" language="java" import="java.util.*" pageEncoding="utf-8" 
    contentType="text/html; charset=utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- 该页面用于使用通配符的测试 -->
<html>
  <head>
    <title>Insert title here !</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
  </head>
  
  <body>
    测试1:*通配符的使用<br/>
    <a href="<c:url value='/mypattern/a_pattern.action'/>">访问1</a><br/>
    <a href="<c:url value='/mypattern/b_pattern.action'/>">访问2</a><br/>
    <a href="<c:url value='/mypattern/c_pattern.action'/>">访问3</a><br/>
  </body>
</html>

    (4)运行结果:单击下面的是三个按钮,查看结果

      

      三个结果全都是:

      

      控制台打印的结果:

      

  4.通配符映射实例2:

    分析:上一个例子中所有的请求都由一个类中的一个方法来处理了,但是有可能的情况下,会发生请求中的action名字不相同,需要调用的类不相同,需要调用的方法也不相同,这时候就需要灵活的使用{1},{2},{3}等来进行匹配了,尽量少的在配置文件中少些action了。


六、动态方法调用

  1.一句话概括动态方法调用:通过url动态调用Action中的方法

  2.如果Action中存在多个方法的时候,我们可以使用!+方法名的形式动态调用其方法

  3.启用或者禁用动态方法调用的形式(struts.xml文件中):

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

  4.使用动态方法的核心:

    (1)使用!连接Action和调用的方法,如:

<a href="<c:url value='/dynamic/dynamicMethod!add.action'/>">调用add方法!</a>

     /dynamic是命名空间;dynamicMethod是将要访问的action的名字;!是连接action和add方法的关键符号;add是访问的方法;.action是后缀名。

    (2)自定义的struts.xml配置文件中的action标签不能包含method属性,也就是说method属性不能写。

    (3)action标签下多个result元素对应着响应不同的方法,并根据不同的方法跳转到不同的页面。

  5.实例:struts_dynamicMethod.xml配置文件

<?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="dynamicPackage" namespace="/dynamic" extends="struts-default">
        <action name="dynamicMethod" class="com.kdyzm.p03.dynamicMethod.DynamicMethodAction">
            <result name="success"><param name="location">/dynamicMethod/result.jsp</param></result>
            <result name="addok"><param name="location">/dynamicMethod/addok.jsp</param></result>
            <result name="deleteok"><param name="location">/dynamicMethod/deleteok.jsp</param></result>
        </action>
    </package>
</struts>

    DynamicMethodAction.java文件:(Action)

package com.kdyzm.p03.dynamicMethod;

import com.opensymphony.xwork2.ActionSupport;

public class DynamicMethodAction extends ActionSupport {
    private static final long serialVersionUID = 1L;
    @Override
    public String execute() throws Exception {
        System.out.println("调用了execute默认方法!");
        return "success";
    }
    public String add()throws Exception{
        System.out.println("调用了add方法!");
        return "addok";
    }
    public String delete()throws Exception{
        System.out.println("调用了delete方法!");
        return "deleteok";
    }
}

    发起请求的jsp页面:

<%@ page isELIgnored="false" language="java" import="java.util.*" pageEncoding="utf-8" 
    contentType="text/html; charset=utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- 请求页面! -->
<html>
  <head>
    <title>Insert title here !</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
  </head>
  
  <body>
    <a href="<c:url value='/dynamic/dynamicMethod!execute.action'/>">调用默认方法!</a>
    <a href="<c:url value='/dynamic/dynamicMethod!add.action'/>">调用add方法!</a>
    <a href="<c:url value='/dynamic/dynamicMethod!delete.action'/>">调用delte方法!</a>
  </body>
</html>

    响应请求的页面:

 1 <%@ page isELIgnored="false" language="java" import="java.util.*" pageEncoding="utf-8" 
 2     contentType="text/html; charset=utf-8" %>
 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 5 <!-- 响应页面! -->
 6 <html>
 7   <head>
 8     <title>Insert title here !</title>
 9     <meta http-equiv="content-type" content="text/html;charset=utf-8">
10   </head>
11   
12   <body>
13     这里是默认显示页面!
14   </body>
15 </html>
result.jsp
 1 <%@ page isELIgnored="false" language="java" import="java.util.*" pageEncoding="utf-8" 
 2     contentType="text/html; charset=utf-8" %>
 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 5 <html>
 6   <head>
 7     <title>Insert title here !</title>
 8     <meta http-equiv="content-type" content="text/html;charset=utf-8">
 9   </head>
10   
11   <body>
12     添加成功!
13   </body>
14 </html>
addok.jsp
 1 <%@ page isELIgnored="false" language="java" import="java.util.*" pageEncoding="utf-8" 
 2     contentType="text/html; charset=utf-8" %>
 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 5 <html>
 6   <head>
 7     <title>Insert title here !</title>
 8     <meta http-equiv="content-type" content="text/html;charset=utf-8">
 9   </head>
10   
11   <body>
12     删除成功!
13   </body>
14 </html>
deleteok.jsp

    运行结果:

    

    依次单击三个链接,分别显示三个页面:

    

    后台打印输出:

    


七、补充

  1.可以使用<global-result>标签定义一个全局结果。

     <global-results>
            <result name="error">
                /error/error.jsp
            </result>
        </global-results>

    当Action中的返回结果和当前action标签中所有的result元素都不匹配的时候就会查找全局result,即global-results,如果Action的返回结果和全局result相匹配的话就会按照全局result进行跳转。

  千万注意:一定是和Action返回的字符串匹配的时候才会使用全局result,如果都不匹配就报错。

  2.struts2采用了多例模式,也就是说,每次请求相同的Action,都会创建对应的实例,可以通过构造方法来验证。

  

 1 package com.kdyzm.p03.dynamicMethod;
 2 
 3 import com.opensymphony.xwork2.ActionSupport;
 4 
 5 public class DynamicMethodAction extends ActionSupport {
 6     private static final long serialVersionUID = 1L;
 7     public DynamicMethodAction() {
 8         System.out.println("新的实例产生了!");
 9     }
10     @Override
11     public String execute() throws Exception {
12         System.out.println("调用了execute默认方法!");
13         return "error";
14     }
15     public String add()throws Exception{
16         System.out.println("调用了add方法!");
17         return "addok";
18     }
19     public String delete()throws Exception{
20         System.out.println("调用了delete方法!");
21         return "deleteok";
22     }
23 }
DynamicMethodAction
原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/4783702.html