起源
Struts2采用另一个MVC框架WebWork的核心设计,是WebWork的一个升级,而不是Struts1的升级,是Struts的下一代产品。它吸收了Struts1的部分优点,建立了一个WebWork和Struts1的MVC架构。Struts2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与Servlet API完全脱离开,所以Struts2可以理解为WebWork的更新产品。
架构
MVC设计模式的3个关注点:模型、视图和控制器。在Struts2中,它们分别通过action,result,StrutsPrepareAndExecuteFilter实现。
1、控制器:StrutsPrepareAndExecuteFilter
作用:将请求映射到动作
StrutsPrepareAndExecuteFilter是一个Servlet过滤器,它检查每一个传入请求,决定哪个动作来处理这个请求。只需要告诉框架哪个URL需要映射到哪个动作即可。
2、模型:Action
作用:是应用程序的内部状态,这个状态由数据模型和业务逻辑共同组成。
3、视图:Result
作用:结果向浏览器返回页面
调用流程
橙色是过滤器链,所有的请求都要经过Filter链的处理。
浅蓝色是Struts2的核心部分,Struts2中已经做好的功能,实际开发中不需要动它们。
浅绿色是Struts2的拦截器。Struts2提供了很多默认的拦截器,可以完成日常开发的绝大部分工作;当然,也可以自定义拦截器,用来实现具体业务需要的功能。
浅黄色由开发人员创建的,包括struts.xml、Action、Template,是每个使用Struts2来进行开发的人员都必须会的。
1、客户端初始化一个指向Servlet容器的请求;
2、这个请求经过一系列的过滤器(Filter),接着StrutsPrepareAndExecuteFilter被用,StrutsPrepareAndExecuteFilter询问ActionMapper来决定这个请求是否需要调用某个Action;
3、如果ActionMapper决定需要调用某个Action,StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy;ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类;
4、ActionProxy创建一个ActionInvocation的实例。ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
5、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是一个需要被表示的JSP或者FreeMarker的模版。
登录实例
1、配置文件web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<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>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
2、struts配置文件struts.xml(放在src下)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- 需要继承struts-default包,这样就拥有最基本的功能 -->
<package name="struts2" extends="struts-default" >
<action name="login" class="com.bjpowernode.struts2.LoginAction">
<result name="success">/login_success.jsp</result>
<result name="error">/login_error.jsp</result>
</action>
</package>
</struts>
包:必须继承
3、Action
即使转向,也包含数据接收(用get、set方法),相当于struts1中的ActionForm
注:有默认方法execute(),返回的必须是字符串
public class LoginAction {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
//必须有Action,并且返回值为String
public String execute() throws Exception{
if("admin".equals(username) && "admin".equals(password)){
return "success";
}else{
return "error";
}
}
}
4、界面
index
</head>
<body>
<a href="login.jsp" >登录</a>
</body>
</html>
登录:
<body>
<form action="login.action">
用户名:<input type="text" name="username"><br>
密 码:<input type="text" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
成功:
<body>
**,登录成功!
</body>
</html>
失败:
</head>
<body>
登录失败
</body>
</html>
结果:
核心对象
StrutsPrepareAndExecuteFilter是核心控制器,负责接收所有请求
ActionMapper提供了HTTP请求与action执行之间的映射
Action:负责处理单个特定请求
ActionInvocation:真正调用并执行Action,它拥有一个Action实例和这个Action所依赖的拦截器实例。
Result:是不同视图类型的抽象封装模型,不同的视图类型会对应不同的Result实现,Struts2中支持多种视图类型,比如Jsp,FreeMarker等。
Interceptor(拦截器):拦截器是一些无状态的类,拦截器可以自动拦截Action,它们给开发者提供了在Action运行之前或Result运行之后来执行一些功能代码的机会。
优点
大量的拦截器
基于插件的框架
支持多种视图
基于POJO易于测试
更加模块化
Struts VS Struts2
struts2在actionServlet与Action间加入了代理,代理与action间加入了一些服务(拦截).
1、Action
类
Struts1必须继承Action类;Struts2可以不继承
线程安全
Struts1是单实例,存在线程安全问题;
Struts2是多实例,没有线程安全问题;
对Servlet API依赖
Struts1的Action需要依赖
Struts2的Action可不依赖
可测试性
Struts1的Action测试性不好,因为需要容器支持(因为依赖于Servlet API)
Sturts2的Action测试性好,可直接写一个单元测试完成,因为Struts2的Action是一个POJO对象
执行控制
Struts1固定不变的,模块中的Action必须共享一个生命周期
Struts2通过拦截器,可以改变执行流程,灵活配置
2、ActionForm
数据收集
Struts1通常使用ActionForm收集数据,而ActionForm需要继承,使ActionForm的复用率降低。若项目复杂需要建立很多ActionForm不好维护,但好处在于使得手机和控制进行了很好的分离。
Struts2可不使用ActionForm来收集数据,直接让Action来收集数据,但也可以采用类似ActionForm方式来收集数据。
类型转换
Struts1中对ActionForm的类型转换采用commons-beanutils工具,而定义完成一个转换器,将对所有的ActionForm起作用,不能针对单独一个ActionForm起作用。
Struts2使用OGNL进行类型转换,功能更强大,可以针对某个类型进行配置
校验
Struts1采用覆盖ActionForm中的validate()方法或采用验证框架commons validator来验证
Struts2支持使用覆盖validate()方法来完成验证,也支持验证框架xWork来验证
3、表达式语言
Struts1中通常使用JSTL
Struts2可使用功能更加强大的表达式语言OGNL
小结
以上只是简单的从宏观上介绍了一下Struts的架构、调用流程等等,真正很好地理解还需要在以后项目中多去发现和总结。