一、 Struts2概述
在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。
其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。
Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,
这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。
虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。
- 三层结构体系(来自于JavaEE规范):
表现层(页面数据显示、页面跳转调度)jsp/servlet
业务层(业务处理和功能逻辑、事务控制)-service
持久层(数据存取和封装、和2交道)dao
换句话说:
Struts2是一个表现层框架,用来简化表现层代码开发的。
而Hibernate是一个持久层框架,用来替代DBUtils来简化持久层的代码开发。
二、 入门案例_Hello World
1. 入门案例步骤
创建Web工程
导入Struts2的jar包
配置
Struts2
的前端控制器模拟页面请求,编写
hello.jsp
编写表现层Action,响应返回跳转到
result.jsp
-
根据请求与响应跳转,配置
Struts2
的核心配置文件struts.xml
- 找到
struts2-blank.war.zip
模板文件中的struts.xml
配置文件,拷贝到当前项目的src目录下
- 找到
2. 实现
2.1 创建Web工厂
2.2 导入Struts2的jar包
1. 解压下载好的Struts2压缩包,找到apps解压Struts2提供的blank模板,更改其扩展名为zip后解压即可.
2. copy其中lib包下所有jar包到当前工程,其中log4的jar包可选.
3. 这里我们不使用Struts2提供的log4j 2.x的版本,自己导入log4j 1.x的版本
2.3 配置Struts2
的前端控制器
-
Struts2
的前端控制器就是一个过滤器,在这里加载Struts2
的配置,将Servlet原先的一些重复的代码在拦截器中执行了,Struts2
的前端控制器需要在web.xml
中进行配置。
1.找到刚刚解压的struts2-blank.war.zip模板文件中的web.xml配置文件,copy其中过滤器Filter配置的那一段代码到项目中的web.xml
前端控制器的类的路径和名称:
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
具体配置如下:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.4 模拟页面请求,编写hello.jsp
a
标签,点击请求Struts2
.
这里的 hello.action 我们可以认为与 Servlet的 url-pattern 的映射路径类似,我们在struts.xml中
配置该 hello.action对应的Action. 在Struts2的Action处理请求进行响应.
<a href="${pageContext.request.contextPath }/hello.action">点我</a>
2.5. 编写表现层Action,响应返回跳转到result.jsp
- Action类是动作类,是Struts2处理请求,封装数据,响应页面的核心控制器。需要自己编写。
编写Action处理请求:(实现Action接口,实现excute方法,Struts2访问Action默认执行excute方法)
import com.opensymphony.xwork2.Action;
public class HelloAction implements Action {
@Override
public String execute() throws Exception {
//------------模拟调用业务层逻辑-------------
System.out.println("Hello Struts2....");
//---------------页面跳转------------------
return SUCCESS;
}
}
2.6. 根据请求与响应跳转,配置Struts2
的核心配置文件struts.xml
根据request请求的路径,表现层Action的响应配置
struts2.xml
的Stuts2
的核心配置文件。这个核心配置文件
struts.xml
也从Stuts2
提供的struts2-blank.war
模板中找到,将多余的标签删除留下最简单的DTD约束,package与action标签
即可。
1. 配置文件名称是struts.xml(名称必须是struts.xml)
2. 在src下引入struts.xml配置文件(配置文件的路径必须是在src的目录下)
<?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">
<!--
Struts2的核心配置文件 :
1. 建立请求与Struts2的联系,请求经过web.xml前端控制器,按照拦截器的从上而下的顺序,执行了原先Servlet中大量需要重复的代码
2. 根据struts.xml配置文件找到对应的Action
3. Action对请求做出响应,返回了一个String类型的值,我们将其称为逻辑视图,在struts.xml配置该逻辑视图对应的跳转页面
-->
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="hello" class="com.itdream.test.HelloAction">
<result name="success">/result.jsp</result>
</action>
</package>
</struts>
三、 入门案例的细节解析
1. Struts2的运行流程
前端控制器
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
它采用前端控制器模式,对用户的请求进行控制处理。在这里会默认加载Struts2的配置文件
我们通过查看源码可以知道,它会依次加载Struts2中的配置文件。
加载配置文件的顺序:
1. init_DefaultProperties()。默认的properties配置。
org/apache/struts2/default.properties :默认的配置加载项,struts2启动时加载的默认参数
2. init_TraditionalXmlConfigurations()。传统的xml配置。
struts-default.xml,struts-plugin.xml,struts.xml
struts2的传统xml配置:
struts-default.xml:struts框架启动时加载运行的框架默认配置。
struts-plugin.xml: struts框架允许插件集成。集成的插件配置。
struts.xml: 开发者的配置。我们配置的请求与Action等配置就在这里
3. init_LegacyStrutsProperties():加载常量配置struts.properties
4. init_CustomConfigurationProviders():struts启动核心类创建的提供者。
5. init_FilterInitParameters():struts加载web.xml中的配置
Interceptor拦截器【了解】
Struts2可复用的代码功能都是基于(通过)它来实现的。struts2有很多内置拦截器,用来实现不同的功能。
参考 struts-core.jar 提供 struts-default.xml 配置文件
我们看看有哪些默认的拦截器:
这些拦截器都会依次执行(按照从上倒下的顺序):
Struts.xml中的配置
位于工程的src目录下:
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="hello" class="com.itdream.test.HelloAction">
<result name="success">/result.jsp</result>
</action>
</package>
</struts>
DTD的查询和配置
1. 到struts的核心包中可以找到struts-2.3.dtd文件
2. 到xml catelog中配置离线提示
package、action、result标签
package标签:用来管理配置包配置和Action, 实现包内配置复用 (通过包继承实现 )
name : 包名,在struts容器中具有唯一性(在开发中可以用模块名称作为包名)
extends : 继承父package(中的功能),通常都继承struts-default(默认包内定义大量结果集类型和拦截器)
namespace : 名称空间用来标识一个路径,来区分不同action的访问路径。一般使用"/"
和Action标签的name和method搭配来确定访问的url
abstract:抽象。用来被其他package继承的
-----------------------------------------------------------------------
action标签 : 用来建立请求与Strtus2的Action之间的联系的。
name : 用于配置请求。
相当于Servlet中的映射路径url-pattern,通过namespace+name可以访问与它对应的Action类
class : action对应的类,全包名。该类编写了action具体业务逻辑代码。
method: action类中的方法名称,访问此action时调用的action类中的方法
-----------------------------------------------------------------------
result标签 : 结果集视图,用于配置响应,标签内的值是响应的地址。
name : 结果集(结果集视图)的名字,action会根据该名字跳转到对应的地址。
小结:namespace主要用来区分action,影响到action的访问路径。
Constant标签【会配置】
default.properties
定义了struts2
框架的大量常量,开发者可以通过改变这些常量来满足应用的需求。
要修改这些常量,可以通过自定义核心配置struts.xml
来覆盖默认的值(后加载的配置文件常量,可以对先加载配置文件进行覆盖),有如下三种方式(开启开发者模式):
-
配置
src/struts.xml
【推荐】<constant name = “struts.devMode” value=”true”/>
-
配置
src/struts.properties
struts.devModel = false
-
配置
web.xml
注意:要写在filter标签内 <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <!-- web.xml 配置常量覆盖之前的,这是最后执行的配置文件--> <init-param> <param-name>struts2.devMode</param-name> <param-value>true</param-value> </init-param>
</filter>
常用常量:
struts.i18n.encoding=UTF-8 :
相当于 request.setCharacterEncoding(“utf-8”); 解决post 请求乱码问题。
因此,在Struts2开发时,尽量使用post请求,无需关注post 乱码问题。
**struts.devMode=true :**
开发模式下使用,这样可以打印出更详细、友好的错误信息
当设置开发者模式devMode =true 会激活xml配置文件自动重新加载功能。
-----------------------------------------------------------------
struts.configuration.xml.reload=true :
修改struts.xml 配置后,无需重启服务器;配置开发者模式后自动开启
struts.i18n.reload = true :
国际化文件修改之后也不需要重启服务器。会自动加载生效。
struts.action.extension=action :
Action请求映射路径 默认扩展名
问题: http://localhost:8080/struts2_day1/hello 也可以访问 HelloAction
如果请求路径 必须以.action结尾
struts.ui.theme=xhtml :
设置页面标签显示样式
struts.enable.DynamicMethodInvocation=true :
访问Action 支持 动态方法调用
struts.multipart.maxSize=2097152 :
上传文件的大小限制
==============================================================
小结:
如果需要更改某个常量的值,在default.properties中找到变量,将名字复制到struts.xml中进行覆盖它的值。
include标签,配置文件的分离【了解】
【开发场景】
在大部分应用里,随着应用规模的增加,系统中Action的数量也会大量增加,导致struts.xml配置文件变得非常臃肿。
为了避免struts.xml文件过于庞大、臃肿,提高struts.xml文件的可读性,我们可以将一个struts.xml配置文件分解成多个配置文件,
然后在struts.xml文件中包含其他配置文件。下面的struts.xml通过<include>元素指定多个配置文件:
<!-- include标签引入其他配置文件 -->
<include file="struts2.xml"></include>
四、 Action类的编写与访问
Action类的编写
-
自定义POJO(Plain Old Java Object简单的Java对象),实际就是普通的JavaBean。
编写excute方法必须满足一下条件: public修饰符 String返回值 无参数
-
实现Action接口
Action 接口提供 execute 处理业务逻辑方法 【内置的视图名称】: Action 接口提供一组 常用的内置的逻辑视图名称: SUCCESS 成功视图 NONE 没有结果视图,用户自己生成响应数据 ERROR 错误视图 INPUT 输入视图 (数据输入非法,要求用户重新输入) LOGIN 登陆视图 (如果用户未登陆,使用登陆视图)
-
继承ActionSupport类
继承ActionSupport相当于间接实现Action接口,该类提供了更多功能,如数据校验、 国际化等, 用的最多,使用的时候需要手动覆盖execute()。
/**
* 自定义POJO
*/
public class ActionDemo1 {
public String execute() {
System.out.println("POJO。。。。。。");
return "none";
}
}
/**
* 实现Action接口
*/
public class ActionDemo2 implements Action {
@Override
public String execute() throws Exception {
System.out.println("继承了Action接口.........");
return NONE;
}
}
/**
* 继承ActionSupport类
*/
public class ActionDemo3 extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("继承了ActionSupport............");
return NONE;
}
}
Action类的访问:
在开发中,我们在一个Action类中不止一个execute方法,往往需要实现多个方法.
在struts.xml中的action标签中配置method属性即可
<action name="hello2_save" class="com.itdream.test.HelloAction2" method="save"></action>
<action name="hello2_delete" class="com.itdream.test.HelloAction2" method="delete"></action>
<action name="hello2_update" class="com.itdream.test.HelloAction2" method="update"></action>
<action name="hello2_query" class="com.itdream.test.HelloAction2" method="query"></action>
但是这样配置的话,每一个方法都要配置实在太麻烦了,因此使用通配符进行配置
<!-- 使用通配符访问Action中对应方法 -->
<!--
hello_* : 这个*代表任意字符
method属性中的 : {1} 代表 与name 属性中的第一个 * 一样 。
-->
<action name="hello2_*" class="com.itdream.test.HelloAction2" method="{1}"></action>
还有一种访问方式:动态方法访问:
在struts.xml中进行常量配置,将动态方法访问的配置改为true覆盖默认的false
<!-- 开启动态方法调用 -->
<!-- <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> -->
开启后,在配置action时,无需指定method属性:
<action name="hello2" class="com.itdream.test.HelloAction2"></action>
访问浏览器时:
http://localhost:8080/Day34_Struts2_HelloWorld/hello2!save.action
http://localhost:8080/Day34_Struts2_HelloWorld/hello2!delete.action
...................
就可以调用对应感叹号后面的方法。
五、 整合Hibernate与Struts2完成CRM查询所有客户的操作
1. 思路
- 创建Web工程
- 导入Hibernate所需jar包,数据库表,实体类,Utils工具类
- 完成Hibernate的相应配置,并测试
- 导入Struts2所需jar包,完成相应配置
- 更改menu.jsp让其请求访问Struts2的Action
- Action接收请求,处理业务逻辑返回数据转发到页面
- 修改Strurts2的配置文件
struts.xml
完成请求Struts2
的Action
的的对应及响应后的跳转
2. 搭建环境
2.1. 创建Web工程
2.2. 导入Hibernate所需jar包
1. hibernate必须jar包 : hibernate安装文件中required下的所有jar包
2. jdbc数据库驱动
3. hibernate中优化连接池的c3p0的jar包
2.3. 创建数据库表R,实体类O
R : Relational 关系型数据库
CREATE DATABASE struts2_crm;
USE struts2_crm;
CREATE TABLE `cst_customer` (
`cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` VARCHAR(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_user_id` BIGINT(32) DEFAULT NULL COMMENT '负责人id',
`cust_create_id` BIGINT(32) DEFAULT NULL COMMENT '创建人id',
`cust_source` VARCHAR(32) DEFAULT NULL COMMENT '客户信息来源',
`cust_industry` VARCHAR(32) DEFAULT NULL COMMENT '客户所属行业',
`cust_level` VARCHAR(32) DEFAULT NULL COMMENT '客户级别',
`cust_linkman` VARCHAR(64) DEFAULT NULL COMMENT '联系人',
`cust_phone` VARCHAR(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` VARCHAR(16) DEFAULT NULL COMMENT '移动电话',
PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
--------------------------------------------------------------------
O : Object 与R对应的持久化类(根据R完成)
2.4. 完成ORM框架中的M,建立持久化类与数据库表的映射关系
与实体类在同级目录下创建 类名+.hbm.xml ,这里为 Customer.hbm.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!-- 导入DTD约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 建立持久化类Customer与数据库表customer的映射 -->
<class name="com.itdream.crm.domain.Customer" table="cst_customer">
<!-- 配置持久化类标识符OID与数据库表的主键的映射关系,name和column相同省略column -->
<id name="cust_id">
<!-- 主键生成策略,native根据数据库底层自动三选1 : increment(MySQL),sequence(Oracle),hilo(Hibernate自定义的一种) -->
<generator class="native"></generator>
</id>
<!-- 配置普通属性与字段的映射 -->
<property name="cust_name"></property>
<property name="cust_user_id"></property>
<property name="cust_create_id"></property>
<property name="cust_source"></property>
<property name="cust_industry"></property>
<property name="cust_level"></property>
<property name="cust_linkman"></property>
<property name="cust_phone"></property>
<property name="cust_mobile"></property>
</class>
</hibernate-mapping>
2.5. 完成Hibernate的核心配置文件hibernate.cfg.xml
在src目录下创建hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 导入Hibernate核心配置的DTD约束 -->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--1. 基本配置 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_day02</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!--2. 与本地线程绑定 -->
<property name="hibernate.current_session_context_class">thread</property>
<!--3. Hibernate的属性 -->
<!--Hibernate的方言配置,实现了跨数据库 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 显示sql语句 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- Hibernate表格的创建方式 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--
设置隔离级别:
hibernate.connection.isolation = 4
1-Read uncommitted isolation
2-Read committed isolation
4-Repeatable read isolation
8-Serializable isolation
-->
<property name="hibernate.connection.isolation">4</property>
<!-- C3P0的供应商 -->
<property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!-- 最小连接 -->
<property name="hibernate.c3p0.min_size">5</property>
<!-- 最大连接数 -->
<property name="hibernate.c3p0.max_size">20</property>
<!-- 连接超时时长 -->
<property name="hibernate.c3p0.timeout">120</property>
<!-- 每120秒检查空闲连接 -->
<property name="hibernate.c3p0.idle_test_period">120</property>
<!-- 最大statments数量 -->
<property name="hibernate.c3p0.max_statements">120</property>
<!-- 连接用完后,每次增加的连接数 -->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!-- 每次都验证连接是否可用 -->
<property name="hibernate.c3p0.validate">false</property>
<!--4. 加载映射文件 -->
<mapping resource="com/itdream/domain/crm/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
2.6. 建立包结构,编写HibernateUtils工具类,导入log4j.properties
日志配置文件
/**
* Hibernate工具类
* 初始化SessionFactory工厂,提供获取Session对象的方法
*/
public class HibernateUtils {
//单例模式的SessionFactory,确保只有一个工厂对象
private static SessionFactory sf = null;
static {
//创建Hibernate的配置对象Configuration,并加载核心配置文件hibernate.cfg.xml
Configuration configuration = new Configuration().configure();
//创建SessionFactory工厂对象
sf = configuration.buildSessionFactory();
//程序结束销毁SessionFactory对象释放资源
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("程序结束,销毁SessionFactory");
sf.close();
}
}));
}
/**
* 获取新的Session的方法
*/
public static Session openSession() {
return sf.openSession();
}
/**
* 获取与当前线程绑定的Session对象
*/
public static Session getCurrentSession() {
return sf.getCurrentSession();
}
}
===========================================================================
log4j.properties日志配置文件 :
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout,file
2.7. copy前端页面到WebContent
包下,测试Hibernate是否成功导入成功
copycopy前端页面到```WebContent```包下,导入jstl标签库的相应jar包
@Test
//测试Hibernate是否连通
//如果数据库中建表成功代表成功
public void test() {
Session session = HibernateUtils.getCurrentSession();
}
2.8. Struts2环境搭建,添加Struts2的jar包
这里我们解压Struts2的空白模板,获得其需要的最少的jar包,13个。
由于log4j的日志jar包,之前我们已经在hibernate中已经使用了1.x的版本,这里Struts2的log4j 2.x.jar的版本我们就不需要了。
除此之外,Hibernate与Struts2有两个jar包冲突,选择最新的版本,旧版本删除
2.9. 在web.xml
中完成Struts2
的前端控制器配置
同样在空白模板struts2-blank中直接找到web.xml的文件复制其中fiter标签即可。
<!--Struts2的前端控制器配置 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
到这里环境搭建就基本完成了,接下来从页面开始完成代码操作
3. 代码实现
3.1. 修改menu.jsp
页面
<TD class=menuSmall>
<A class=style2 href="${pageContext.request.contextPath}/customer_findListCustomer.action" target="main">- 客户列表</A>
</TD>
这里让a标签点击之后,请求Struts2的Action类,Action类做出响应
3.2 编写Action类对请求做出响应
编写CustomerAction类继承ActionSupport类
public class CustomerAction extends ActionSupport {
private static final long serialVersionUID = 1L;
/**
* 查找所有Customer
*/
public String findListCustomer() {
//收到请求,调用Service业务层
CustomerService service = new CustomerServiceImpl();
//获取到了所有客户Customer数据
List<Customer> listCustomer = service.findListCustomer();
//获取到request对象将listCusomter数据存入request域
ServletActionContext.getRequest().setAttribute("list", listCustomer);
//逻辑视图转发,在struts.xml配置文件中配置对应跳转页面
return SUCCESS;
}
}
--------------------------------------------------------------
service层业务逻辑:
@Override
//获取所有客户
public List<Customer> findListCustomer() {
//获取Session
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction transaction = session.beginTransaction();
List<Customer> list = null;
try {
//业务逻辑
CustomerDAO dao = new CustomerDAOImpl();
list = dao.findListCustomer();
} catch (Exception e) {
e.printStackTrace();
//如果发生异常,Hibernate框架会帮我们处理回滚事务,无需手动回滚
//transaction.rollback();
} finally {
//最后无论如何都提交事务从而结束事务,如果发生异常就是回滚到初始状态再提交
transaction.commit();
}
//返回值
return list;
}
-------------------------------------------------------------------
dao层使用Hibernate查询 :
@Override
//获取所有客户
public List<Customer> findListCustomer() throws SQLException {
//获取与当前线程绑定的Session对象
Session session = HibernateUtils.getCurrentSession();
//获取所有客户,这里我使用Criteria进行单表查询
Criteria criteria = session.createCriteria(Customer.class);
return criteria.list();
}
3.3 struts.xml
配置请求对应的Action及响应后的跳转页面等
同样从struts2的解压包中找到sturts2-blank的模板,赋值struts.xml到项目
删除多余的标签。
留下<constant>常量标签中的 开启开发者模式,这样修改配置可以无需手动重启服务器,同时错误提示更友好
留下<package><action>标签,配置请求对应Action
<?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>
<!-- 开启开发者模式 -->
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<!-- 配置请求对应的Action -->
<action name="customer_*" class="com.itdream.web.action.CustomerAction" method="{1}">
<!-- 配置逻辑视图跳转页面 -->
<result name="success" >/jsp/customer/list.jsp</result>
</action>
</package>
</struts>
3.4 解析result.jsp页面【省略】
3.5 访问效果图
3.6 案例总结
1. 配置文件时小心出错,我在配置struts.xml配置文件的action中的result标签时,出了个错误,使用了模板中的type,其实应该用name逻辑视图对应的跳转页面
<!-- 配置逻辑视图跳转页面 -->
<result name="success" >/jsp/customer/list.jsp</result>
2. 使用action配置对应action方法时,如果没有method标签,那么Struts2默认执行execute方法。
3. 超链接上的a标签访问customer_findListCustomer.action,经过前端控制器到struts.xml中寻找customer_*的action
4. 找到这个action后,通过class找到对应的Action类,通过Method找到对应的方法.执行完Action后返回result逻辑视图
5. 返回的result再回到struts.xml中寻找该action标签下的result标签,找到对应逻辑视图需要跳转的页面进行跳转