Struts2是一种基于MVC模式的轻量级Web框架,它自问世以来,就受到了广大Web开发者的关注,并广泛应用于各种企业系统的开发中。目前掌握Struts2框架几乎成为Web开发者的必备技能之一。
先讲Struts2框架之前,我们得知道JavaEE一共有三层架构,如下:
接下来,我就来解释什么是Struts2,可从度娘上看到如下文字:
从以上这段话中可得出如下两点结论:
在介绍Struts2之前,先来罗里吧嗦说一下Struts1。Struts1是最早的基于MVC模式的轻量级的Web框架,它能够合理的划分代码结构,并包含验证框架、国际化框架等多种实用工具框架。但是随着技术的进步,Struts1的局限性也越来越多的暴露出来。为了符合更加灵活、高效的开发需求,Struts2框架应运而生。
Struts2是Struts1的下一代产品,是在Struts1和WebWork技术的基础上进行合并后的全新框架(WebWork是由OpenSymphony组织开发的,致力于组件化和代码重用的J2EE Web框架,它也是一个MVC框架)。虽然Struts2的名字和Struts1相似,但其设计思想却有很大不同。实质上,Struts2是以WebWork为核心的,它采用拦截器的机制来处理用户的请求。这样的设计也使得业务逻辑控制器能够与Servlet API完全脱离开,所以Struts2可以理解为WebWork的更新产品。Struts2拥有优良的设计和功能,其优势具体如下:
上面列举的就是Struts2的一系列技术优势,只需对它们简单了解即可,在学习了后面的知识后,会慢慢对这些技术优势有更好的理解和体会。
Web层框架都会有一个特点,那就是它们都是基于前端控制器模式设计的。这话咋说,什么又是前端控制器模式呢?我们来看下图,在图中传统方式的开发,有一次请求就会对应一个Servlet。这样会导致出现很多Servlet。
而Struts2将所有的请求都先经过一个前端控制器,在前端控制器中实现框架的部分功能,剩下具体操作要提交到具体的Action中。既然所有的请求都会经过前端控制器,那么用什么来实现前端控制器呢?过滤器就是最好的一个实现方式,因为所有的请求都可以被过滤器拦截,然后就能在过滤器中实现部分的功能。所以Struts2的前端控制器也是由过滤器来实现的。
了解这些之后,我们来进行一个Struts2的快速入门,来感受一下Struts2的优势吧!
Struts2的官网是:https://struts.apache.org/,你可以到官网去下载Struts2的开发包。笔者在这里使用的是struts-2.3.24这个版本的Struts2,下载好了以后需要进行解压。
解压Struts2的开发包,你可以看到解压后的目录结构:
为了让大家对每个目录的内容和作用有一定的了解,接下来针对这些目录进行简单介绍,具体如下:
有了Struts2的开发包,接下来我们就可以进行Struts2的开发了。
首先,需要我们创建一个Web工程,例如struts2_demo01,并引入相关的Jar包,那引入哪些Jar包呢?将struts-2.3.24框架目录中的lib文件夹打开,得到Struts2开发中可能用到的所有Jar包(此版本有107个Jar包),实际的开发中,我们根本不用引入这么多的Jar包。
要进行Struts2最基本的开发,可以参考struts-2.3.24中的apps目录下的一些示例代码,其中struts2-blank.war是一个Struts2的空的工程,我们只需要将struts2-blank.war解压后进入到WEB-INF下的lib中查看,就能看到以下的这些Jar包。
这些包就是Struts2基本的开发包了,那么这些包都是些什么含义呢?Struts2项目依赖的基础Jar包说明如下:
从表中可以看出,此版本的Struts2项目所依赖的基础Jar包共13个。Struts2根据版本的不同所依赖的基础Jar包可能不完全相同,不过基本上变化不大,读者可以视情况而定。
需要注意的是,通常使用Struts2的Web项目并不需要利用到Struts2的全部Jar包,因此没有必要一次将Struts2的lib目录下的全部Jar包复制到Web项目的WEB-INF/lib路径下,而是根据需要,添加相应的Jar包。
现在,Struts2的基本Jar包已经引入完成了,Struts2项目的开发都是从页面发起请求到服务器,再由服务器处理请求,最后响应回页面,所以,接下来我们就从页面开始进行Struts2的开发吧!
在WebContent目录下创建一个demo01目录,并在该目录下新建一个demo01.jsp页面,该页面的内容为:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
head>
<body>
<h1>Struts2的入门h1>
<h3><a href="${pageContext.request.contextPath }/hello.action">Struts2的入门a>h3>
body>
html>
在src下创建一个com.meimeixia.struts2.demo01包,并在该包下新建一个HelloAction的类。在这个类中编写一个公有的,返回值为String类型的方法,这个方法的名称叫做execute,且该方法没有任何参数(因为这个方法最终要被反射执行)。
package com.meimeixia.struts2.demo01;
/**
* Struts2的入门的Action类
* @author liayun
*
*/
public class HelloAction {
/*
* 提供一个方法:
* 1. 方法的方法签名是固定的、公有的,返回值类型是String类型,方法名是execute,在这个方法中不能传递参数
*
*/
public String execute() {
System.out.println("HelloAction执行了.....");
return "success";
}
}
对于Servlet来说,每次访问Servlet的时候,都会执行Servlet里面的service()方法,而对于Action来说,每次访问Action的时候,默认执行Action里面名称为execute的方法。注意:创建方法的要求是方法不能有参数。Action类编写好了以后,Struts2框架如何识别它就是一个Action呢?接下来,我们就需要对Action类进行配置了。
这个时候,我们还需要观察apps目录中的示例代码,在WEB-INF的classes目录下,有一个名称为struts.xml的文件,这个文件就是Struts2的配置文件。我们在开发中需要将struts.xml文件引入到工程的src下,因为src下的内容发布到Web服务器就在WEB-INF下的classes中了。首先将struts.xml中的原有内容删除掉,然后配置上自己编写的Action类就可以了,该文件里面的具体标签,我们会在后面的地方详细介绍。
<struts>
<package name="demo01" extends="struts-default" namespace="/">
<action name="hello" class="com.meimeixia.struts2.demo01.HelloAction">
<result name="success">/demo01/success.jspresult>
action>
package>
struts>
从以上文件中可知,咱还得在WebContent/demo01目录下创建一个success.jsp页面。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
head>
<body>
<h1>跳转成功页面!h1>
body>
html>
至此,Action类已经配置好了,配置好了以后大家思考一下,现在是否可以执行呢?其实现在还不行,因为之前我们介绍过,Web层的框架都有一个特点就是基于前端控制器的模式,这个前端控制器是由过滤器实现的,所以我们还需要配置Struts2的核心过滤器,而这个过滤器的名称是StrutsPrepareAndExecuteFilter。
Struts2框架要想执行,所有的请求都需要经过这个前端控制器(核心过滤器),所以得配置这个核心过滤器,因为这个过滤器完成了框架的部分功能。接下来,我们对该过滤器进行配置,我们打开web.xml文件,在web.xml文件中进行如下配置:
<filter>
<filter-name>struts2filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
filter>
<filter-mapping>
<filter-name>struts2filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
至此,我们便可在浏览器地址栏中输入地址http://localhost:8080/struts2_demo01/demo01/demo01.jsp进行访问,点击页面中的超链接,就能成功跳转到如下页面。
到这里,Struts2的入门案例已经编写完成了,下面我来总结下Struts2的整个执行流程。
从客户端发送请求过来,先经过前端控制器(也即核心过滤器,StrutsPrepareAndExecuteFilter),过滤器中执行一组拦截器(这组拦截器就会完成部分功能代码),到底哪些拦截器执行了呢?在Struts2中定义了很多拦截器,在其默认栈中的拦截器会得到执行(这个我们可以通过断点调试的方式测试),拦截器执行完成以后,就会执行目标Action,在Action中返回一个结果视图,根据result的配置进行页面的跳转。如果用图来表示,那么就是下面这样子的。
以上就是Struts2的大致上的执行流程,我觉得我已经画的够清晰了,如果您认为上图不完整,可参考官网提供的图:
通过前面的学习,我们已对Struts2框架有了一定的了解,但是对于各个知识点的细节,还需要进一步地学习。接下来,我将针对Struts2中struts.xml文件的配置等内容进行详细的讲解。在学习具体详细的配置之前,要对Struts2的配置文件的加载顺序有一定的了解,这样对后面学习Struts2的配置都是有帮助的。
每次从客户端发送请求到服务器都要先经过Struts2的核心过滤器(StrutsPrepareAndExecuteFilter),这个过滤器有两个功能:预处理和执行。在预处理中主要就是来加载配置文件的,对应的是过滤器中的init方法,而执行是用来执行一组拦截器完成部分功能的,对应的是过滤器的doFilter方法。所以我们如果要去了解Struts2的配置文件的加载顺序,那么我们需要查阅过滤器的init方法。
在init方法中,调用了init的initDispatcher方法来加载配置文件,进入到该代码中:
我们会发现这个方法又调用了dispatcher的init方法,进入init方法内部:
根据上面的代码我们可以得出配置文件的加载顺序,如下:
前三个配置文件我们不用关心,是Struts2内部的配置文件,我们无法修改,能修改的文件就是struts.xml、struts.properties、web.xml这三配置文件。这三个配置文件都可以修改Struts2的常量的值,要记住的是,后加载配置文件中常量的值会将先加载的配置文件中常量的值给覆盖掉。知道了这些知识点,下面我们就可以来看Struts2的详细配置了。
Struts2框架的核心配置文件是struts.xml文件,该文件主要用于配置Action和请求的对应关系。Struts2框架的核心组件是Action和拦截器,它使用包来管理Action和拦截器,每个包就是多个Action、多个拦截器、多个拦截器引用的集合。在struts.xml文件中,package元素用于定义包配置,每个package元素定义一个包配置,package元素的常用属性,如下图所示。
表中就是package元素的常用属性,其中,在配置包时,必须指定name属性,就是包的标识,没有具体的含义,理论上可以随便写,只要在一个项目中不重名即可;除此之外,还可以指定一个可选的extends属性,extends属性必须是另一个包的name属性值,但属性值通常都设置为struts-default,这样该包中的Action就具有了Struts2框架默认的拦截器等功能了;其实,Struts2还提供了一种所谓的抽象包(用于其他包的继承),抽象包不能包含Action定义。为了显示指定一个包是抽象包,可以为该package元素增加abstract="true"属性。最后,在package中还有namespace(名称空间)的配置,namespace属性与action标签中的name属性共同决定了访问路径,namespace有如下三种配置:
温馨提示:在一个配置文件中可以有多个package标签,但是package标签中的name属性值不能相同。
Action映射是框架中的基本"工作单元"。Action映射就是将一个请求的URL映射到一个Action类中,当一个请求匹配某个Action名称时,框架就使用这个映射来确定如何处理请求。在struts.xml文件中,通过
元素对请求的action和Action类进行配置。其中,
元素中共有4个属性,这4个属性的说明如下表所示。
其中name属性和package标签中的namespace属性共同决定了访问路径,class属性对应的是Action类的全路径,method属性指定了执行Action的那个方法,默认是execute方法。
温馨提示:在一个package标签里面可以写多个action标签,但是action标签的name属性值不能一样。如:
<package name="demo1" extends="struts-default" namespace="/">
<action name="user" class="com.meimeixia.struts2.demo01.UserAction">
<result name="ok">/user.jspresult>
action>
<action name="person" class="com.meimeixia.struts2.demo01.PersonAction">
<result name="success">/person.jspresult>
action>
package>
Action类的方法是有返回值的,配置返回值之后,可跳转到不同的页面中。result标签里面的name属性值即是Action类里面的方法的返回值。如:
<result name="success">/person.jspresult>
在一个action标签里面可写多个result标签,但要注意result标签的name属性值不能相同。
基本的Struts2的配置我们已经了解了,在实际的开发中我们需要大量地用到Struts2的常量,接下来,我们就来学习一下Struts2常量的配置。
Struts2的这些常量大多在默认的配置文件中就已经配置好,但根据用户需求的不同,开发的要求也不同,可能需要修改这些常量值,修改的方法就是在配置文件中对常量进行重新配置。Struts2常量的配置共有3种方式,分别如下:
元素配置常量;
元素配置常量。为了让大家更好地掌握这3种Struts2常量配置的方式,接下来我会分别对它们进行讲解。
在struts.xml文件中通过
元素配置常量,是最常用的方式。在struts.xml文件中通过
元素来配置常量时,需要指定两个必填的name和value属性:
在struts.xml文件中配置的示例代码如下:
在上述文件中,咱配置了常量struts.i18n.encoding和struts.devMode,用于指定Struts2应用程序的默认编码集为UTF-8,并使用开发模式。值得一提的是,struts.properties文件能配置的常量都可以在struts.xml文件中使用
元素来配置。注意:我还须对struts.i18n.encoding这个常量作进一步的解释。这个常量封装了一个功能,如若将其值置为UTF-8,使用Struts2的Action类得到表单的提交数据(并且表单提交方式是post),那么提交中文时的中文乱码问题使用这个常量就能帮我们处理了,而不需要自己手动设置编码方式。
在struts.properties文件中配置常量。struts.properties文件是一个标准的properties文件,其文件格式为key-value对,即每个key对应一个value,key表示的是Struts2框架中的常量,而value则是其常量值。在struts.properties文件中配置常量的方式,具体如下所示:
### 设置默认编码集为UTF-8
struts.i18n.encoding=UTF-8
### 设置action请求的扩展名为action或者没有扩展名
struts.action.extension=action,,
### 设置不使用开发模式
struts.devMode=false
### 设置不开启动态方法调用
struts.enable.DynamicMethodInvocation=false
在上述代码片段中,等于号左边的是key,右边的是每个key对应的value,另外,代码片段中以"###"开头的表示的是properties文件中的注释信息,用于解释说明。需要注意的是,和struts.xml文件一样,struts.properties文件也应存放于WEB-INF/classes路径下。
在web.xml文件中通过初始化参数配置常量。在web.xml文件中配置核心过滤器StrutsPrepareAndExecuteFilter时,可通过初始化参数来配置常量。通过
元素的
子元素指定,每个
元素可以配置一个Struts2常量。在web.xml文件中通过初始化参数配置常量方式,具体如以下代码片段所示:
在上述web.xml文件中,当配置StrutsPrepareAndExecuteFilter时,还可通过
子元素来配置struts.i18n.encoding常量,指定其值为UTF-8。需要注意的是,在web.xml文件中配置常量时,
标签必须放在
标签下。
Struts2所支持的常量数量众多,在struts2-core-2.3.24.jar压缩文件的org/apache/struts2路径下有一个default.properties文件,该文件为Struts2的所有常量都指定了默认值,读者可以通过查看该文件来了解Struts2所支持的常量。之前,我们就已经介绍过了Struts2的配置文件的加载顺序,后加载的配置文件的常量的值会覆盖先加载的配置文件中常量的值,所以这个地方大家一定要注意。还有,在实际的开发中我们更习惯使用struts.xml文件来修改Struts2的常量。
在实际开发中会有一个问题,就是如果一个项目是团队开发的,也就是很多人开发的,那么团队中的很多人就都需要去修改struts.xml文件,最后在项目整合的时候就会很麻烦,而Struts2中的分模块开发(Struts2提供了
标签来支持分模块开发的配置)刚好就解决了这个问题。
元素用来在一个struts.xml配置文件中包含其他的配置文件,包含配置体现的是软件工程中的"分而治之"原则。Struts2允许将一个配置文件分解成多个配置文件,从而提高配置文件的可读性。Struts2默认只加载WEB-INF/classes下的struts.xml文件,但一旦通过多个xml文件来配置Action,就必须通过struts.xml文件来包含其他配置文件。为了让大家更直观地理解如何在struts.xml文件中进行包含配置,接下来通过一段示例代码来说明,具体如下:
<struts>
<include file="struts-shop.xml">include>
<include file="struts-user.xml">include>
<include file="struts-shoppingcart.xml">include>
<include file="com/meimeixia/action/struts-product.xml">include>
struts>
从上面内容可以看到,struts.xml文件包含了4个配置文件,这4个配置文件都包含在
元素中。配置
元素时,指定了一个必须的file属性,该属性指定了被包含配置文件的文件名。上述
元素的file属性中,前3个没有指定文件所在路径时,表示该文件在项目的src路径下,如果配置文件在具体的包中,那么引入配置文件时,需要包含文件所在包的路径。需要注意的是,每一个被包含的配置文件都得是标准的Struts2配置文件,一样包含DTD信息、Struts2配置文件的根元素等信息。通过将Struts2的所有配置文件都放在Web项目的WEB-INF/classes路径下,struts.xml文件包含了其他的配置文件,在Struts2框架自动加载struts.xml文件时,完成加载所有的配置信息。
在Struts2的应用开发中,Action作为框架的核心,实现对用户请求的处理,所以Action类也被称为是业务逻辑控制器。一个Action类代表一次请求或调用,每个请求的动作都对应于一个相应的Action类,一个Action类是一个独立的工作单元。也就是说,用户的每次请求,都会转到一个相应的Action类里面,由这个Action类来进行处理。简而言之,Action就是用来处理一次用户请求的对象。
实现Action控制类共有3种方式,也就是说Action类的编写方式共有3种方式。接下来,我会分别对它们进行讲解。
在Struts2中,Action可以不继承特殊的类或不实现任何特殊的接口,仅仅是一个POJO,POJO全称Plain Ordinary Java Object(简单的Java对象),只要是具有一部分getter/setter方法的那种类,就可以称作是POJO。一般在这个POJO类中,要有一个公共的无参的构造方法(采用默认的构造方法就可以)和一个execute()方法。
execute()方法的要求为:
也就是说,满足上述要求的POJO都可算作是Struts2的Action实现。
为了让用户开发的Action类更规范,Struts2提供了一个Action接口,用户在实现Action控制类时,可以实现Struts2提供的这个Action接口,Action接口定义了Struts2的Action处理类应该实现的规范。
从上述代码中可以看出,Action接口位于com.opensymphony.xwork2包下。这个接口里只定义了一个execute()方法,该接口的规范规定了Action处理类应该包含一个execute()方法,该方法返回一个字符串。除此之外,该接口还定义了5个字符串常量,它们的作用是统一execute()方法的返回值。
由于Xwork的Action接口简单,为开发者提供的帮助较小,所以在实际开发过程中,Action类很少直接实现Action接口,通常都是从ActionSupport类继承。
ActionSupport类本身实现了Action接口,是Struts2中默认的Action接口的实现类,所以继承ActionSupport就相当于实现了Action接口。ActionSupport类还实现了Validateable、ValidationAware、TextProvider、LocaleProvider以及Serializable等接口,来为用户提供更多的功能。还有,ActionSupport类中提供了许多的默认方法,这些默认方法包括获取国际化信息的方法、数据校验的方法以及默认的处理用户请求的方法等。实际上,ActionSupport类是Struts2默认的Action处理类,如果让开发者的Action类继承该ActionSupport类,则会大大简化Action的开发。
Action的类已经会编写了,如果要运行这个Action,可以通过前面的配置来完成,但是之前的方式有一个缺点,就是多次请求不能对应同一个Action,因为在实际的开发中,一个模块的请求通常由一个Action类来处理就好了,否则便会造成Action类过多。现在要处理的问题就是要让一个模块的操作都提交到一个Action中。其实,
标签中就有一个method属性,通过该属性的配置就能让Action中指定的某个方法执行。
首先,在WebContent/demo02目录下新建一个demo01.jsp页面,页面中的内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
head>
<body>
<h1>Action的访问h1><br/>
<h3>通过method的方式h3><br/>
<a href="${pageContext.request.contextPath }/userFind.action">查询客户a><br/>
<a href="${pageContext.request.contextPath }/userUpdate.action">修改客户a><br/>
<a href="${pageContext.request.contextPath }/userDelete.action">删除客户a><br/>
<a href="${pageContext.request.contextPath }/userSave.action">保存客户a><br/>
body>
html>
然后,在src目录下新建一个com.meimeixia.struts2.demo03包,并在该包下创建一个UserAction。
package com.meimeixia.struts2.demo03;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
public String find() {
System.out.println("查询用户......");
return NONE;
}
public String update() {
System.out.println("修改用户......");
return NONE;
}
public String delete() {
System.out.println("删除用户......");
return NONE;
}
public String save() {
System.out.println("保存用户......");
return NONE;
}
}
接着,就要在struts.xml文件中配置以上Action类了,这里我们采用Struts2中分模块开发的配置。
struts.xml
<struts>
<constant name="struts.action.extension" value="action" />
<include file="com/meimeixia/struts2/demo03/struts-demo03.xml">include>
struts>
struts-demo03.xml
<struts>
<package name="demo03" extends="struts-default" namespace="/">
<action name="userFind" class="com.meimeixia.struts2.demo03.UserAction" method="find">action>
<action name="userUpdate" class="com.meimeixia.struts2.demo03.UserAction" method="update">action>
<action name="userDelete" class="com.meimeixia.struts2.demo03.UserAction" method="delete">action>
<action name="userSave" class="com.meimeixia.struts2.demo03.UserAction" method="save">action>
package>
struts>
最后,如果真使用这种方式的话,我们会发现,同一个Action类就被配置了很多次,只是修改了后面的method属性的值。那么能不能配置简单化呢?也就是一个Action类,只配置一次就好了。这个时候我们就需要使用通配符的配置方式了。
首先,将demo01.jsp页面中的内容修改为:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
head>
<body>
<h1>Action的访问h1><br/>
<h3>通过method的方式h3><br/>
<a href="${pageContext.request.contextPath }/userFind.action">查询客户a><br/>
<a href="${pageContext.request.contextPath }/userUpdate.action">修改客户a><br/>
<a href="${pageContext.request.contextPath }/userDelete.action">删除客户a><br/>
<a href="${pageContext.request.contextPath }/userSave.action">保存客户a><br/>
<h3>通过通配符的方式h3>
<a href="${pageContext.request.contextPath }/product_find.action">查询商品a><br/>
<a href="${pageContext.request.contextPath }/product_update.action">修改商品a><br/>
<a href="${pageContext.request.contextPath }/product_delete.action">删除商品a><br/>
<a href="${pageContext.request.contextPath }/product_save.action">保存商品a><br/>
body>
html>
然后,在com.meimeixia.struts2.demo03包下新创建一个ProductAction。
package com.meimeixia.struts2.demo03;
import com.opensymphony.xwork2.ActionSupport;
public class ProductAction extends ActionSupport {
public String find() {
System.out.println("查询商品......");
return NONE;
}
public String update() {
System.out.println("修改商品......");
return NONE;
}
public String delete() {
System.out.println("删除商品......");
return NONE;
}
public String save() {
System.out.println("保存商品......");
return NONE;
}
}
接着,就要在struts.xml文件中配置以上Action类了,这里我们依然采用Struts2中分模块开发的配置(struts.xml文件中的内容不要动,只须修改被包含的struts-demo03.xml文件中的内容即可)。
<struts>
<package name="demo03" extends="struts-default" namespace="/">
<action name="userFind" class="com.meimeixia.struts2.demo03.UserAction" method="find">action>
<action name="userUpdate" class="com.meimeixia.struts2.demo03.UserAction" method="update">action>
<action name="userDelete" class="com.meimeixia.struts2.demo03.UserAction" method="delete">action>
<action name="userSave" class="com.meimeixia.struts2.demo03.UserAction" method="save">action>
<action name="product_*" class="com.meimeixia.struts2.demo03.ProductAction" method="{1}">action>
package>
struts>
在
的name属性值中使用的*
号代表任意字符,method属性值中的{1}代表name属性值中的出现的第一个*
号所代替的字符。这个时候,我们就只配置一个Action类就可以了。
元素的name属性值就被设置成了product_save,相应地,method属性值就被设置成save了;
元素的name属性值就被设置成了product_update,相应地,method属性值也被设置成update了。最后,使用通配符是开发中最常用的方式。
首先,将demo01.jsp页面中的内容修改为:
然后,在com.meimeixia.struts2.demo03包下新创建一个CustomerAction。
package com.meimeixia.struts2.demo03;
import com.opensymphony.xwork2.ActionSupport;
public class CustomerAction extends ActionSupport {
public String find() {
System.out.println("查询客户......");
return NONE;
}
public String update() {
System.out.println("修改客户......");
return NONE;
}
public String delete() {
System.out.println("删除客户......");
return NONE;
}
public String save() {
System.out.println("保存客户......");
return NONE;
}
}
接着,就要在struts.xml文件中配置以上Action类了,这里我们依然采用Struts2中分模块开发的配置(struts.xml文件中的内容不要动,只须修改被包含的struts-demo03.xml文件中的内容即可)。
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true">constant>
<package name="demo03" extends="struts-default" namespace="/">
<action name="userFind" class="com.meimeixia.struts2.demo03.UserAction" method="find">action>
<action name="userUpdate" class="com.meimeixia.struts2.demo03.UserAction" method="update">action>
<action name="userDelete" class="com.meimeixia.struts2.demo03.UserAction" method="delete">action>
<action name="userSave" class="com.meimeixia.struts2.demo03.UserAction" method="save">action>
<action name="product_*" class="com.meimeixia.struts2.demo03.ProductAction" method="{1}">action>
<action name="customer" class="com.meimeixia.struts2.demo03.CustomerAction">action>
package>
struts>
动态方法访问在Struts2中默认是不开启的,如果想要使用需要先去开启struts.enable.DynamicMethodInvocation这个常量。
最后,如果你在浏览器地址栏中输入地址http://localhost:8080/struts2_demo01/demo02/demo01.jsp进行访问,点击页面中的超链接,就能看到浏览器地址栏中访问路径的写法。