Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开。
Struts2框架提供的功能支持:
- 1、请求数据自动封装
- 2、文件上传和下载
- 3、对国际化功能的简化
- 4、数据效验功能
- 5、ajax的支持
- 6、防止表单的重复提交
一、MVC设计模式
MVC全名是Model View Controller,即是是模型-视图-控制器,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
- Model(模型)
- 是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
- View(视图)
- 是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
- Controller(控制器)
- 是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
MVC 分层有助于管理复杂的应用程序,可以在一个时间内专门关注一个方面。可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。
二、第一个struts2案例
(一)struts2工作原理
先了解一下,整个struts2执行的过程。
1、用户发送请求到服务器
2、FilterDispatcher 查看请求,会将请求转发给ActionMapper,ActionMapper负责识别当前的请求是否需要Struts2做出处理。
3、如果ActionMapper需要处理该请求,FilterDispatcher把请求的处理交给ActionProxy
4、ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类
5、ActionProxy创建一个ActionInvocation实例,Action完整的调用过程都是由ActionInvocation对象负责
6、同样,配置的拦截器做任何后期处理,如果需要的话
7、然后execute方法返回结果(Result),将结果返回给用户
(二)引入相关jar包
相关jar包可以在maven公库中找到。
我这次使用的是以下 的版本:
引入jar包后,我们可以看到以下几个核心jar包:
1、 struts2-core-2.1.8.1.jar Struts 2框架的核心类库
2、xwork-core-2.1.6.jar XWork类库,Struts 2在其上构建
3、ognl-2.7.3.jar (Object Graph Navigation Language), 通过其读写对象的属性
4、freemarker-2.3.15.jar : Struts 2的UI标签的模板使用FreeMarker编写
5、commons-logging-1.1.x.jar ASF出品的日志包,Struts 2框架使用这个日志
6、commons-fileupload-1.2.1.jar 文件上传组件,2.1.6版本后需要加入此文件
7、commons-io-1.3.2.jar 上传文件依赖的jar包
(三)在web.xml配置struts2引擎过滤器
web.xml配置文件是一个J2EE的配置文件,决定如何处理元素的HTTP请求由servlet容器。这个文件为任何Web应用程序提供了一个切入点。 Struts2 应用程序的入口点,将是一个部署描述符(web.xml)中定义的过滤器。因此,我们将定义在web.xml中的FilterDispatcher是类的项。需要创建的文件夹的WebContent/ WEB-INF下web.xml文件。
在struts2中,struts框架是通过拦截器来启动的。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<filter>
<filter-name>struts2Filter</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
<!--
假如struts.xml文件没有配置在src下,则需要配置一个参数,其值为该文件的路径。
如果配置在src下,则不需要配置。
<param>
<param-name>config</param-name>
<param-value>/struts2/src/main/resources/struts.xml</param-value>
</param>
-->
</filter>
<filter-mapping>
<filter-name>struts2Filter</filter-name>
<!--
请注意,我们Struts 2的过滤器映射为/*, /*.action这意味着所有的请求将被struts的过滤器解析。
-->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
拦截器和过滤器的区别
1、拦截器是基于Java的反射机制的,而过滤器是基于函数回调
2、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
3、拦截器可以访问action上下文、值栈里的对象,而过滤器不能
4、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
(四)struts.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- Struts2 把各种 Action 分门别类地组织成不同的包. 可以把包想象为一个模块. 可以定义多个package,一个package内可以定义 多个actioin 。
属性介绍:
namespace 属性是可选的, 当定义多个package时,需要给出不同的 namespace,来区分不同的package。例如,namespace = "/package1" ,则访问其中的Action类则的uri为 /projectName/package1/userAction
extends="struts-default" 沿用了默认的过滤器。
package 元素通常要对 struts-default.xml 文件里定义的 struts-default 包进行扩展. struts-default包是由struts内置的,它定义了struts2内部的众多拦截器和Result类型。Struts2很多核心的功能都是通过这些内置的拦截器实现。
-->
<package name="action" extends="struts-default">
<!-- action 元素嵌套在 package 元素内部, 它表示一个 Struts请求
name 为映射路径 在浏览器通过该映射路径来访问Action类。
class Action类包名+类名
-->
<action name="userAction" class="org.struts2.action.UserAction">
<!-- result 元素告诉 struts 在完成动作后把控制权转交到哪里. result 元素(的name 属性)对应着 Action 方法的返回值. 因为动作方法在不同情况下可能返回不同的值, 所以同一个 action 元素可能会有多个 result 元素
name属性:result 元素的 name 属性建立 <result> 和 Action 方法返回值之间的映射关系。name 属性的默认值为 “success”
type 属性:负责指定结果类型. type 属性的默认值为 dispatcher(转发)
-->
<!-- 而下面 action的结果是,当Action类返回的结果是 success 时,则转发到success.jsp页面 -->
<result name="success" type="dispatcher">/success.jsp</result>
</action>
</package>
</struts>
(五)编写Action类
Action动作是Struts2框架的核心。浏览器提交的请求将被映射到一个特定的动作,它提供了对请求处理逻辑。
1、自定义普通类
Action类可以自己编写,一般需要编写execute方法,因为struts默认调用该方法。
package org.struts2.action;
public class UserAction{
//execute会被struts2调用处理请求
//返回succes就是对应我们之前在 struts.xml文件配置的 <result> 元素,将会转发到success.jsp页面
public String execute(){
System.out.println("成功处理请求..");
return "success";
}
}
2、实现Action接口
Action接口中,定义了execute方法,预定义的一系列的字符串常量,用于返回一些预定的result。
//字符串常量:
SUCCESS="success"
NONE="none"
ERROR="error"
INPUT="input"
LOGIN="login"
package org.struts2.action;
import com.opensymphony.xwork2.Action;
public class UserAction inplements Action{
@Override
public String execute() throws Exception{
System.out.println("成功处理请求..");
return SUCCESS;
}
}
3、继承ActionSupport类(推荐使用)
ActionSupport类本身实现了Action接口。还实现了其他几个接口,提供更多的功能。
- 1、Validateabble 接口:提供validate()方法为Action增加验证功能
- 2、Validateaware 接口:提供方法保存和恢复Action或field级的错误信息
- 3、TextProvider 接口:提供获取本地信息文本的功能
- 4、LcaleProvider 接口:提供getLocale()方法来获取本地信息
package org.struts2.action;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("成功处理请求..");
return SUCCESS;
}
}
我们可以运行一下,直接请求 userAction ,则就会直接转发到 succes.jsp页面。
可以看到后天输出:
二、Action类功能
(一)获取提交参数(通过反射机制)
struts2提供了更加方便的方式来获取,浏览器提交的参数。会通过反射机制,自动向 Action 类 与提交参数同名的 成员变量 注入值。
1、获取基本数据类型
页面表单提交参数:
<form action="userAction1">
<!--
想要struts帮我们自动在 action 类获取提交参数,以下提交参数必须同名。
-->
<input type="text" name="userName"/>
<input type="password" name="password"/>
<input type="submit" value="登陆"/>
</form>
Action类:
public class UserAction extends ActionSupport{
//struts2会自动帮我们将提交参数注入到同名的 Action类的成员变量中
//①在Action定义公共属性,属性名与参数名一致
public String userName;
//②在Action中定义私有属性,属性名与参数名一致。并提供setter方法。(推荐使用)
private String password;
public void setPassword(String password){
this.password = password;
}
@Override
public String execute() throws Exception {
System.out.println("用户名:"+userName+",密码:"+password);
return null;
}
}
2、获取自定义封装类
页面表单提交参数:
<form action="userAction1">
<!--
想要向Action类的中 的自定义类成员变量 自动注入值,需要 名字.变量
例如Action类中 有User类的成员变量 user ,则需要注入为 user.userName
-->
<input type="text" name="user.userName"/>
<input type="password" name="user.password"/>
<input type="submit" value="登陆"/>
</