JavaWeb 之 Struts2 快速入门

Struts2 快速入门。


Struts2 框架的概述


Struts2 框架由来

  • Struts2Struts1 的下一代产品,是在 struts1WebWork 的技术基础上进行了合并的全新的 Struts2 框架。

  • 其全新的 Struts2 的体系结构与 Struts1 的体系结构差别巨大。

  • Struts2WebWork 为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与 ServletAPI 完全脱离开,所以 Struts2 可以理解为 WebWork 的更新产品。

  • 虽然从 Struts1Struts2 有着太大的变化,但是相对于 WebWorkStruts2 的变化很小。

Struts2 设计模型

Struts2 是一个基于 MVC 设计模式的 Web 层框架

  • MVC 和 JavaEE 的三层结构

  • MVC 设计模式:是由一些网站的开发人员提出来的(Model View Controller

  • JavaEE 三层结构:SUN 公司为 EE 开发划分的结构

常见的Web层的框架

  • Struts1

  • Struts2

  • Webwork

  • SpringMVC

Web层框架的特点

  • 都是一个特点,前端控制器模式

  • 记住:前端控制器(核心的控制器)

  • Struts2 框架前端的控制器就是 过滤器


Struts2 快速入门


环境准备

创建 WEB 项目

编写 JSP 的页面,编写超链接,点击超链接发送请求,请求服务器,让服务器的方法去执行!!

1
2
<h3>Struts2的入门程序</h3>
<a href="${ pageContext.request.contextPath }/hello.action">Struts2入门程序</a>

下载 Struts2 的开发包

解压struts-2.3.24-all.zip包

  • 解压后会看到有包和一些文件,大家需要掌握包相关的信息

apps – Struts2 框架提供了一些应用
libs – Struts2 框架开发的 jar 包
docs – Struts2 框架开发文档
src – Struts2 框架源码

引入需要开发的 jar 包

  • Struts2 框架的开发 jar 包非常多,但是不是所有都是必须要引入的,有一些必须要导入的 jar 包,这些 jar 包可以从 Struts2 框架提供的应用中找到。
  • 可以打开 apps 目录,然后找到 struts2-blank.war 应用。war 包和 zip` 包的压缩格式是一样的,所以可以修改后缀名,解压。
  • 找到解压后的应用,打开 WEB-INF/lib 目录下所以的 jar 包。复制到工程中,就可以了。

配置 Struts2 的前端控制器

注意:这一步是必须要做的操作,这是 Struts2 核心的控制器。

  • Struts2 的前端控制器就是一个过滤器,那么过滤器相关知识咱们都学习过,需要在 web.xml 中进行配置。
  • 前端控制器的类的路径和名称:org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  • 具体配置如下
1
2
3
4
5
6
7
8
<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>

编写 Action 类

Action 类是动作类,是 Struts2 处理请求封装数据响应页面核心控制器。需要自己编写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Struts2 框架都是用 Action 类处理用户的请求
*/
public class HelloAction {
/**
* Action 类中的方法签名是有要求的,必须这么做
* public 共有的
* 必须有返回值,必须 String 类型
* 方法名称可以是任意的,但是不能有参数列表
*/
public String sayHello(){
System.out.println("Hello Struts2!");
return "OK";
}
}

编写 Struts 的配置文件

  1. 配置文件名称是 struts.xml(名称必须是 struts.xml

  2. src 下引入 struts.xml 配置文件(配置文件的路径必须是在 src 的目录下)

  3. 配置如下

1
2
3
4
5
6
7
8
9
10
11
12
<?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="default" namespace="/" extends="struts-default">
<!--配置 Action-->
<action name="hello" class="com.renkaigis.action.HelloAction" method="sayHello"/>
</package>
</struts>

编写跳转

1
2
3
4
5
6
7
8
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="hello" class="com.renkaigis.action.HelloAction" method="sayHello">
<!--配置跳转的页面,路径的写法。在 Struts2 框架中,不管是转发还是重定向,都不用写项目名-->
<result name="OK">/demo1/success.jsp</result>
</action>
</package>
</struts>

总结 Struts2 执行流程

执行的流程

  • 编写的页面,点击超链接,请求提交到服务器端。

  • 请求会先经过 Struts2 的核心过滤器(StrutsPrepareAndExecuteFilter

过滤器的功能是完成了一部分代码功能
就是一系列的拦截器执行了,进行一些处理工作。
可以在 struts-default.xml 配置文件中看到有很多的拦截器。

  • 拦截器执行完后,会根据 struts.xml 的配置文件找到请求路径,找到具体的类,通过反射的方式让方法执行。

总结

  • JSP页面 –> StrutsPrepereAndExecuteFilter过滤器 –> 执行一系列拦截器(完成了部分代码) –> 执行到目标 Action –> 返回字符串 –> 结果页面(result) –> 页面跳转

Struts2 框架配置文件加载的顺序

Struts2 框架的核心是 StrutsPrepareAndExecuteFilter 过滤器

该过滤器有两个功能

  • Prepare – 预处理,加载核心的配置文件
  • Execute – 执行,让部分拦截器执行

StrutsPrepareAndExecuteFilter 过滤器会加载哪些配置文件呢?

通过源代码可以看到具体加载的配置文件和加载配置文件的顺序

  • init_DefaultProperties(); – 加载 org/apache/struts2/default.properties
  • init_TraditionalXmlConfigurations(); – 加载 struts-default.xml,struts-plugin.xml,struts.xml
  • init_LegacyStrutsProperties(); – 加载自定义的 struts.properties
  • init_CustomConfigurationProviders(); – 加载用户自定义配置提供者
  • init_FilterInitParameters() ; – 加载 web.xml

重点了解的配置文件

  • default.properties – 在 org/apache/struts2/ 目录下,代表的是配置的是 Struts2 的常量的值
  • struts-default.xml – 在 Struts2 的核心包下,代表的是 Struts2 核心功能的配置(Bean、拦截器、结果类型等)
  • struts.xml – 重点中的重点配置,代表 WEB 应用的默认配置,在工作中,基本就配置它就可以了!!(可以配置常量)
  • web.xml – 配置前端控制器(可以配置常量)

注意:

  • 前 3 个配置文件是 struts2 框架的默认配置文件,基本不用修改。

  • 后 3 个配置文件可以允许自己修改 struts2 的常量。但是有一个特点:后加载的配置文件修改的常量的值,会覆盖掉前面修改的常量的值。

总结(重点掌握的配置文件)

  • 先加载 default.properties 文件,在 org/apache/struts2/default.properties 文件,都是常量。

  • 又加载 struts-default.xml 配置文件,在核心的 jar 包最下方,struts2 框架的核心功能都是在该配置文件中配置的。

  • 再加载 struts.xml 的配置文件,在 src 的目录下,代表用户自己配置的配置文件

  • 最后加载 web.xml 的配置文件

  • 后加载的配置文件会覆盖掉之前加载的配置文件(在这些配置文件中可以配置常量)

注意一个问题

哪些配置文件中可以配置常量?

  • default.properties – 默认值,是不能修改的!!

  • struts.xml – 可以配置,开发中基本上都在该配置文件中配置常量

  • struts.properties – 可以配置,基本不会在该配置文件中配置

  • web.xml – 可以配置,基本不会在该配置文件中配置

  • 后加载的配置文件会覆盖掉之前加载的配置!!


struts.xml 配置文件


基本标签

<package> 标签

如果要配置 <Action> 的标签,那么必须要先配置 <package> 标签,代表的包的概念

包含的属性:

  • name – 包的名称,要求是唯一的,管理 action 配置
  • extends – 继承,可以继承其他的包,只要继承了,那么该包就包含了其他包的功能,一般都是继承 struts-default
  • namespace – 名称空间,一般与 <action> 标签中的 name 属性共同决定访问路径(通俗话:怎么来访问 action),常见的配置如下

    namespace=”/“ – 根名称空间
    namespace=”/aaa” – 带有名称的名称空间

  • abstract – 抽象的。这个属性基本很少使用,值如果是 true,那么编写的包是被继承的

<action> 标签

代表配置 action 类,包含的属性

  • name – 和 <package> 标签的 namespace 属性一起来决定访问路径的
  • class – 配置 Action 类的全路径(默认值是 ActionSupport 类)
  • method – Action 类中执行的方法,如果不指定,默认值是 execute

<result> 标签

action类中方法执行,返回的结果跳转的页面

  • name – 结果页面逻辑视图名称
  • type – 结果类型(默认值是转发,也可以设置其他的值)

Struts2 配置常量

Struts2 框架中的哪些配置文件中配置常量?

struts.xml(必须要掌握,开发中基本上就在该配置文件中编写常量)

1
* <constant name="key" value="value"></constant>

web.xml

  • StrutsPrepareAndExecuteFilter 配置文件中配置初始化参数

  • 注意:后加载的配置的文件的常量会覆盖之前加载的常量!!

需要了解的常量

  • struts.i18n.encoding=UTF-8 – 指定默认编码集,作用于 HttpServletRequest 的 setCharacterEncoding 方法
  • struts.action.extension=action,, – 该属性指定需要 Struts 2 处理的请求后缀,该属性的默认值是 action,即所有匹配 *.action 的请求都由 Struts2 处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开
  • struts.serve.static.browserCache=true – 设置浏览器是否缓存静态内容,默认值为 true (生产环境下使用),开发阶段最好关闭
  • struts.configuration.xml.reload=false – 当 struts 的配置文件修改后,系统是否自动重新加载该文件,默认值为 false(生产环境下使用)
  • struts.devMode = false – 开发模式下使用,这样可以打印出更详细的错误信息

指定多个struts的配置文件(了解)

  1. 在大部分应用里,随着应用规模的增加,系统中 Action 的数量也会大量增加,导致 struts.xml 配置文件变得非常臃肿。

为了避免 struts.xml 文件过于庞大、臃肿,提高 struts.xml 文件的可读性,我们可以将一个 struts.xml 配置文件分解成多个配置文件,然后在 struts.xml 文件中包含其他配置文件。

  1. 可以在 <package> 标签中,使用 <include> 标签来引入其他的 struts_xx.xml 的配置文件。例如:
1
2
3
4
<struts>
<include file="struts-part1.xml"/>
<include file="struts-part2.xml"/>
</struts>
  1. 注意注意注意(重要的事情说三遍):
1
<include file="com/renkaigis/demo2/struts-part1.xml"/>

Action 类的三种写法

Action类就是一个POJO类

  • 什么是 POJO 类,POJO(Plain Ordinary Java Object)简单的 Java 对象,简单记:没有继承某个类,没有实现接口,就是 POJO 的类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 是 POJO 类:没有任何继承和实现
*/
public class Demo1Action {
/**
* execute 是默认方法
* return null; 不会进行跳转
*/
public String execute(){
System.out.println("Demo1Action 是一个 POJO 类…");
return null;
}
}

配置文件:

1
2
<!--POJO 类的方式-->
<action name="demo1Action" class="com.renkaigis.action1.Demo1Action"/>

Action 类可以实现 Action 接口

Action 接口中定义了 5 个常量,5 个常量的值对应的是 5 个逻辑视图跳转页面(跳转的页面还是需要自己来配置),还定义了一个方法,execute 方法。

需要掌握5个逻辑视图的常量

  • SUCCESS – 成功
  • INPUT – 用于数据表单校验.如果校验失败,跳转 INPUT 视图
  • LOGIN – 登录
  • ERROR – 错误
  • NONE – 页面不转向
1
2
3
4
5
6
7
8
9
10
11
/**
* 实现 Action 接口,Action 是框架提供的接口
*/
public class Demo2Action implements Action {

@Override
public String execute() throws Exception {
System.out.println("Demo2Action 实现了 Action 的接口…");
return SUCCESS;
}
}

配置文件:

1
2
3
4
<!--实现 Action 接口的方式-->
<action name="demo2Action" class="com.renkaigis.action1.Demo2Action">
<result name="success">/demo1/success.jsp</result>
</action>

Action 类可以去继承 ActionSupport 类

(开发中这种方式使用最多)

1
2
3
4
5
6
7
8
9
10
/**
* 编写 Action 类继承 ActionSupport 类,ActionSupport 类已经实现了 Action 和一些其他的接口
*/
public class Demo3Action extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("Demo3Action 继承了 ActionSupport 类…");
return NONE;
}
}

配置文件:

1
2
<!--继承 ActionSupport 类的方式-->
<action name="demo3Action" class="com.renkaigis.action1.Demo3Action"/>

Action 的访问

传统的配置方式

通过 <action> 标签中的 method 属性,访问到 Action 中的具体的方法。

  • 传统的配置方式,配置更清晰更好理解!但是扩展需要修改配置文件等!

具体的实例如下:

  • 页面代码
1
2
3
<H3>传统的配置文件的方式</H3>
<a href="{pageContext.request.contextPath}/saveCust.action">保存客户</a>
<a href="{pageContext.request.contextPath}/updCust.action">修改客户</a>
  • 配置文件的代码
1
2
3
<!--传统方式-->
<action name="saveCust" class="com.renkaigis.action2.CustomerAction" method="save"/>
<action name="updCust" class="com.renkaigis.action2.CustomerAction" method="update"/>
  • Action 的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 编写客户的 Action 类
*/
public class CustomerAction extends ActionSupport {

public String save() {
System.out.println("保存客户…");
return NONE;
}

public String update() {
System.out.println("修改用户…");
return NONE;
}
}

通配符的访问方式

(访问的路径和方法的名称必须要有某种联系)

通配符就是 * 代表任意的字符

  • 使用通配符的方式可以简化配置文件的代码编写,而且扩展和维护比较容易。

具体实例如下:

  • 页面代码
1
2
3
<H3>通配符配置文件的方式</H3>
<a href="{pageContext.request.contextPath}/linkman_save.action">保存联系人</a>
<a href="{pageContext.request.contextPath}/linkman_update.action">修改联系人</a>
  • 配置文件代码
1
2
3
4
<!--通配符的方式-->
<action name="linkman_*" class="com.renkaigis.action2.LinkmanAction" method="{1}">
<result name="saveOK">/demo2/success.jsp</result>
</action>
  • Action 的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 使用联系人来测试通配符
*/
public class LinkmanAction extends ActionSupport {
public String save() {
System.out.println("保存联系人…");
return "saveOK";
}

public String update() {
System.out.println("修改联系人…");
return NONE;
}
}
  • 具体理解:在 JSP 页面发送请求,http://localhost:9090/demo2/linkman_save.action,配置文件中的 linkman_* 可以匹配该请求,* 就相当于变成了 addmethod 属性的值使用 {1} 来代替,{1} 就表示的是第一个 * 号的位置!!所以 method 的值就等于了 add,那么就找到 Action 类中的 add 方法,那么 add 方法就执行了!

动态方法访问的方式

(有的开发中也会使用这种方式)

  • 如果想完成动态方法访问的方式,需要开启一个常量,struts.enable.DynamicMethodInvocation = false,把值设置成 true

  • 注意:不同的 Struts2 框架的版本,该常量的值不一定是 true 或者 false,需要自己来看一下。如果是 false,需要自己开启。

  • struts.xml 中开启该常量。

1
2
<!-- 开启动态方法访问 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>

具体实例如下:

  • 页面的代码
1
2
3
<H3>动态方法访问的方式</H3>
<a href="{pageContext.request.contextPath}/user!save.action">保存用户</a>
<a href="{pageContext.request.contextPath}/user!update.action">修改用户</a>
  • 配置文件代码
1
2
<!--配置动态方法访问-->
<action name="user" class="com.renkaigis.action2.UserAction"/>
  • Action的类的代码
1
2
3
4
5
6
7
8
9
10
11
public class UserAction extends ActionSupport {
public String save() {
System.out.println("保存用户…");
return NONE;
}

public String update() {
System.out.println("修改用户…");
return NONE;
}
}

总结

Struts2 框架主要以下几个步骤:

编写 web.xml 前端控制器

1
2
3
4
5
6
7
8
<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>

编写 struts.xml 配置文件

1
2
3
4
5
<package name="" namespace="/" extends="struts-default">
<action name="" class="com.renkaigis.action2.LinkmanAction" method="{1}">
<result name="saveOK">/demo2/success.jsp</result>
</action>
</package>

编写 Action 类

  • 一般继承 ActionSupport

  • <action> 访问配置一般使用 通配符 的方式:

name="user_*" method="{1}"