Struts2执行流程
1、简单执行流程,如下所示:
在浏览器输入请求地址,首先会被过滤器处理,然后查找主配置文件,然后根据地址栏中输入的/hello去每个package中查找为/hello的namespace,然后在包下寻找名为HelloAction的action,反射创建控制器HelloAction对象,调用method指定的方法hello,拿到返回值“success”,去result的配置节找success对应的页面(hello.js),呈现给用户。
2、Struts的架构,具体参考这里
Struts2配置详解
struts2的配置文件的加载顺序
每次从客户端发送请求到服务器都要先经过Struts的核心过滤器StructsPrepareAndFilter,这个过滤器有两个功能:预处理和执行。在预处理中主要就是来加载配置文件的。对应的是过滤器中的init方法,而执行是用来执行一组拦截器完成部分功能的,对应的是过滤器的doFilter方法。所以我们需要查询过滤器的init方法。
根据上面的代码,可以得出配置文件的加载顺序如下:
标红的配置文件都可以修改Struts的常量的值,后加载配置文件中常量的值会将先加载的配置文件中常量的值给覆盖。
struts2核心配置
Struts2框架的核心配置文件时Struts.xml文件,该文件主要用来配置Action和请求的对应关系。
1、package的配置
Struts2框架的核心组件是Action和拦截器,它使用包来管理Action和拦截器。每个包就是多个Action、多个拦截器、多个拦截器引用的集合。
package元素用于定义包配置,每个package元素定义了一个包配置。package元素的常用属性。入表所示。
<!-- package:将Action配置封装.就是可以在Package中配置很多action. name属性: 必须指定,给包起个名字,起到标识作用.随便起.不能其他包名重复. namespace属性:给action的访问路径中定义一个命名空间,namespace与action标签的name属性共同决定了访问路径。 namespace有如下三种配置: 默认名称空间:namespace="" 根名称空间:"/" 带名称的空间:namespace="/demo1" extends属性: 继承一个指定包,extends属性值必须是另一个包的name属性,但通常都设置为struts-default, 这样该包中的action就具备了Struts框架默认的拦截器等功能。 abstract属性:包是否为抽象的; 标识性属性.标识该包不能独立运行.专门被继承 --> <package name="hello" namespace="/hello" extends="struts-default" > </package>
2、Action的配置
Action映射是框架中的基本“工作单元”,Action映射就是将一个请求的URL映射到一个Action类,当一个请求匹配某个Action名称时,框架就使用这个映射来确定如何处理请求。
在Struts.xml文件中,通过<action>元素对请求的Action和Action类进行配置。
<action>元素中共有4个属性,如下所示:
<!-- action元素:配置action类 name属性: 决定了Action访问资源名. class属性: action的完整类名 method属性: 指定调用Action中的哪个方法来处理请求 --> <action name="HelloAction" class="cn.itheima.a_hello.HelloAction" method="hello" > <!-- result元素:结果配置 name属性: 标识结果处理的名称.与action方法的返回值对应. type属性: 指定调用哪一个result类来处理结果,默认使用转发. 标签体:填写页面的相对路径 --> <result name="success" type="dispatcher" >/hello.jsp</result> </action>
struts2常量配置
Struts2的这些常量大多数在默认的配置文件中已经配置好,但根据用户需求的不同,可以修改这些常量值,修改的方法就是在配置文件对常量进行重新配置。
Struts常量配置共有3中方式,分别如下:
1、在struts.xml文件中使用<constant>元素配置常量,最常用的方式。
<!-- i18n:国际化. 解决post提交乱码 --> <constant name="struts.i18n.encoding" value="UTF-8"></constant> <!-- 指定反问action时的后缀名 http://localhost:8080/struts2_day01/hello/HelloAction.do --> <constant name="struts.action.extension" value="action"></constant> <!-- 指定struts2是否以开发模式运行 1.热加载主配置.(不需要重启即可生效) 2.提供更多错误信息输出,方便开发时的调试 --> <constant name="struts.devMode" value="true"></constant>
2、在struts.properties文件中配置常量。
struts.i18n.encoding=UTF8
3、在web.xml文件中通过<init-param>元素配置常量。<init-param>必须放在<filter>标签下。
Struts所支持的常量数量众多,在Struts-core-2.3.24.jar压缩文件的org/apache/struts2路径下有一个default.properties文件,该文件里为Struts2的所有常量都指定了默认值。Struts2中也支持分模块开发的配置。默认只加载WEB-INF/classes下的struts.xml,文件,所以其他的需要引入。
<!-- 引入其他struts配置文件 --> <include file="cn/itheima/b_dynamic/struts.xml"></include> <include file="cn/itheima/c_default/struts.xml"></include>
分模块的struts.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> <!-- 配置动态方法调用是否开启常量 默认是关闭的,需要开启 --> <constant name="struts.enable.DynamicMethodInvocation" value="false"></constant> <package name="dynamic" namespace="/dynamic" extends="struts-default" > <!-- 动态方法调用方式2:通配符方式 使用{1} 取出第一个星号通配的内容 --> <action name="Demo1Action_*" class="cn.itheima.b_dynamic.Demo1Action" method="{1}" > <result name="success" >/hello.jsp</result> </action> </package> </struts>
动态方法调用
由于每个action类中都会有很多方法,比如增删改查方法,如果每个方法都配置一个action的话太麻烦了,所以可以配置动态方法调用。
比如:
package cn.itheima.b_dynamic; //动态方法调用 public class Demo1Action { public String add(){ System.out.println("添加用户!"); return "success"; } public String delete(){ System.out.println("删除用户!"); return "success"; } public String update(){ System.out.println("修改用户!"); return "success"; } public String find(){ System.out.println("查找用户!"); return "success"; } }
方式一、开启常量方式:
访问时采用如下方式:
这种方式不常用,不利于SEO。
方式二、通配符方式:
访问时采用如下形式:
默认值
<package name="default" namespace="/default" extends="struts-default" > <!-- 找不到包下的action,会使用Demo2Action作为默认action处理请求 --> <default-action-ref name="Demo2Action"></default-action-ref> <!-- method属性:execute --> <!-- result的name属性:success --> <!-- result的type属性:dispatcher 转发 --> <!-- class属性:com.opensymphony.xwork2.ActionSupport --> <action name="Demo2Action" > <result >/hello.jsp</result> </action> </package>
Action类的书写方式
//方式1: 创建一个类.可以是POJO //POJO:不用继承任何父类.也不需要实现任何接口. //使struts2框架的代码侵入性更低. public class Demo3Action { }
import com.opensymphony.xwork2.Action; //方式2: 实现一个接口Action // 里面有execute方法,提供action方法的规范. // Action接口预置了一些字符串.可以在返回结果时使用.为了方便 public class Demo4Action implements Action { @Override public String execute() throws Exception { return null; } }
import com.opensymphony.xwork2.ActionSupport; //方式3: 继承一个类.ActionSupport // 帮我们实现了 Validateable, ValidationAware, TextProvider, LocaleProvider . //如果我们需要用到这些接口的实现时,不需要自己来实现了. public class Demo5Action extends ActionSupport{ }