1. Struts2的演化史
先有servlet后有jsp,jsp只是把servlet简化了
2004年出现了struts1(Apache),它解决了什么问题,就是咱们刚才这些问题
1)写了action
3) 写了中控servlet
3)增加了ActionForm来封装表单的参数,这样不用再写枯燥的request.getParameter(“”),而实现自动封装,自动类型转换。
Struts1流行了5、6年后,就落伍了,逐渐被struts2所替代。
接下来webwork就做了两件非常牛的事,
1)使action完全和servlet容器松耦合了
2)使用属性驱动和模型驱动获取页面表单中的数据
3)还利用拦截器的概念解决了一个方法过于复杂,做的相当漂亮,这个也是学习struts2的最重要的一个内容。很多后续的框架都模拟它这点。
doGet(){
用户注册
用户头像图片上传
验证表单
权限的验证
注册
}
Webwork出来,apache眼红了。当时webwork逐渐在绽放光辉,struts1逐渐在衰落。结果Apache老谋深算,干脆把webwork和struts1结合起来,推出了struts2。struts2融合了struts1和webwork的特点。现在struts2也已经有快10年了。目前mvc这个框架已经遇到发展瓶颈了,想再有技术上的突破已经很难了。
框架封装的越好,它的灵活性越差,灵活性越高,它的稳定性越低。
2003年struts2不是有个致命漏洞吗?听过这事没?严重到什么程度呢?一个连接直接让服务器宕机。为什么呢?那就是struts2在这方面太灵活了。
2. Struts2的第一个例子
2.1. 第一步:创建一个Web工程struts2
2.2. 第二步:导入jar包
struts-2.3.15.3-all.zip
struts2-blank.war是个最简单的例子,它下面有最基础的jar包和依赖包
序号 | JAR包 | 说明 |
1 | asm-3.3.jar | 动态代理 |
2 | asm-commons-3.3.jar | 动态代理 |
3 | asm-tree-3.3.jar | 动态代理 |
4 | commons-fileupload-1.3.jar | 文件上传 |
5 | commons-io-2.0.1.jar | 文件IO |
6 | commons-lang3-3.1.jar | 公用工具 |
7 | commons-logging-1.1.3.jar | 公用日志 |
8 | freemarker-2.3.19.jar | 模板 |
9 | javassist-3.11.0.GA.jar | 动态代理 |
10 | log4j-1.2.17.jar | Log4j日志 |
11 | ognl-3.0.6.jar | ognl表达式 |
12 | struts2-core-2.3.15.3.jar | struts2核心包 |
13 | xwork-core-2.3.15.3.jar | xwork核心包 |
将这些包拷贝到项目的lib目录下
2.3. 第三步:编写web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>struts2</display-name>
<filter>
<filter-name>StrutsFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>StrutsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
8行代码是不就搞定了,这个类里干了太多的事情
2.4. 第四步:编写action
package struts2;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
public String execute(){
System.out.println("hello LoginAction");
return SUCCESS;
}
}
可以看出这个action是不没有request,response这两个参数了,说明什么,struts2是不实现了和servlet容器完全解耦。
2.5. 第五步:编写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>
<package name="struts2" namespace="/" extends="struts-default">
<action name="loginAction" method="execute" class="struts2.LoginAction">
<result>/index.jsp</result>
</action>
</package>
</struts>
2.6. 第六步:部署测试
http://localhost/struts2/loginAction.action
针对上面的例子进行详细的解析
3. Struts.xml配置文件
源码方法跟踪
这个过程如果觉得难以理解,光记结果就行。
可以看到最终struts2加载了3个文件,最后一个就是struts.xml
上图为struts配置文件加载流程
注意:
1)struts.xml必须放在classpath的根目录下
2)名称不能改变,这样当struts2启动时,就自动加载了根目录下的struts2.xml配置文件
3)因为整个加载过程写在filter的init方法中,所以tomcat启动时就将该文件加载了。
4. 详解package
假设一个项目有成百个上千个action,你琢磨下,都放在这一个配置文件中,那一下堆积了3000多行,那让你找一个action,容易吗?没法找了,是吧。
怎么办?如果能跟java类一样,加个包路径来区分,该多好的。
Strust2支持这个功能,利用package来分模块。
name属性为包的名称,是唯一的,继承时使用。
namespace命名空间,url访问时的路径。
http://localhost/struts2/a/b/c/loginAction.action
先找struts2/a/b/c下的action,如果找不到,则查找上一层/struts2/a,再找不到再找上一层,直到找到,如果最上层找不到,则报错。
注意:只要命名空间加一层,最后跳转到相应的jsp以后,也会加上相应的路径。
5. 详解action
Action元素代表一个类,name属性和url相对应。
Class为类的全名(限定名),class属性可以不写
Class名不写,就会找com.opensymphony.xwork2.ActionSupports
但注意这样写有好处吗?当然没有,这不就真正执行自定义的action的业务处理了。
extends属性是struts2中非常巧妙的的一个设计,这样就形成了xml的继承
则只需ActionSupport的execute方法,而该方法什么都没做。仅仅返回了一个SUCCESS字符串。
典型的模板设计模式应用。起什么作用?子类继承时实现,这样子类到底做什么,完全由子类自己控制,这样代码就非常灵活了。
6. Result代表一种结果集
name和action中某个方法的返回值要一样,不写时默认为SUCCESS
type代表结果集的类型,不写时默认为dispatcher
struts-default.xml文件中定义了很多返回type
<result-type
name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult"
default="true"/>
Type属性不写,则默认和struts-default中的结果集类型中的default=”true”的结果集保持一致。默认是dispatcher。这就是转发,struts2对它包装了下。
Result标签中的内容就是要转发到的页面。
Result的name属性可以不写,默认值为”success”
总结:可以看到struts.xml文件,通过package来分模块,同时还可以继承;通过action可以配置模块下的类。每个action可以配置对应的action和result。
这个结构比之前的任何一个框架都先进,struts1也有action但它没有package,特别包的继承机制。发明还是很有难度和技术含量的。