Struts2框架

来源:互联网 发布:大数据的前沿技术培训 编辑:程序博客网 时间:2024/05/16 13:49
Struts框架
概念:轻量级的MVC框架,主要解决了请求分发的问题,重心在控制层和表现层。低侵入性,与业务代码的耦合度很低。Struts2实现了MVC,并提供了一系列API,采用模式化方式简化业务开发过程。是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。主要是采用Servlet和JSP技术来实现的. 能充分满足应用开发的需求,简单易用,敏捷迅速. 功能:基于MVC的充当了其中的试图层和控制器。
Struts2是基于Struts1和Webwork,以Webwork(支持更多表现层)为核心的。
Struts1:只支持jsp表现层,不支持Freemarker和velocity;与servlet API耦合严重;属于侵入式设计。
Struts2鼓励基于M2模式(MVC设计模式)来开发程序--Web应用程序中通过前端控制器来实现MVC应用程序的模型。它是框架的表现层,是对MVC构架的具体实现:
1, 视图层(V)2, 控制层(C)3, 模型层(M)
与Servlet对比
优点:业务代码解耦,提高开发效率
缺点:执行效率偏低,需要使用反射、解析XML等技术手段,结构复杂
不同框架实现MVC的方式
Servlet:

Spring:

Struts2:


关于Struts 2对Struts1的技术改进
主要表现在如下几个方面:
 在Action的实现方面
Struts1要求必须统一扩展自Action类,而Struts2中可以是一个POJO。
 线程模型方面
Struts1的Action是单实例的,一个Action的实例处理所有的请求。Struts 2的Action是一个请求对应一个实例(每次请求时都新new出一个对象),没有线程安全方面的问题。
 Servlet依赖方面
Struts1的Action依赖于Servlet API,比如Action的execute方法的参数就包括request和response对象。这使程序难于测试。Struts2中的Action不再依赖于Servlet API,有利于测试,并且实现TDD。
 封装请求参数
Struts1中强制使用ActionForm对象封装请求的参数。Struts2可以选择使用POJO类来封装请求的参数,或者直接使用Action的属性。
 表达式语言方面
Struts1中整合了EL,但是EL对集合和索引的支持不强,Struts2整合了OGNL(Object Graph NavigationLanguage)。
 绑定值到视图技术
Struts1使用标准的JSP,Struts2使用“ValueStack”技术。
 类型转换
Struts1中的ActionForm基本使用String类型的属性。Struts2中使用OGNL进行转换,可以更方便的使用。
Struts1中支持覆盖validate方法或者使用Validator框架。Struts2支持重写validate方法或者使用XWork的验证框架。
 Action执行控制的对比
Struts1支持每一个模块对应一个请求处理,但是模块中的所有Action必须共享相同的生命周期。Struts2支持通过拦截器堆栈为每一个Action创建不同的生命周期。

Struts2使用
web.xml:配置struts2的核心控制器FilterDispatcherFilterDispatcher用来拦截客户端请求并把请求转发到相应的Action类来处理。(只要web应用加载了FilterDispatcher就可以获得整个struts2框架所提供的服务)。 
struts.xml: struts2框架的配置文件,主要用于配置业务逻辑控制器Action以及Action result的定义、Bean配置、常量配置、包配置和拦截器配置。resultname属性值与Action的返回值相对应。(也可用struts.properties
1.使用步骤
    导入Struts2核心jar
    在web.xml配置前端控制器filter
    <filter>
<filter-name>Struts2</fileter-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>
 
      2.创建struts.xml(格式可以参考核心包根路径下的DTD文件,struts-default.xml
    编写控制器Action
-方法是public
-返回值为String类型(返回值与struts.xml->action->resultname属性匹配,即根据此返回值找到对应result)
-参数列表为空
    创建JSP页面
配置struts.xml
     <struts>
 <!--
package:包,用于对Action进行封装
name:包名,根元素下可以有多个包,彼此不能重名
extends:继承,用于指定继承的包,相当于将继承包下的配置信息复制到当前包
namespace:命名空间,用于规定Action的访问路径,必须“/”开头 -->
     <packagename="test01" namespace="/test01" extends="struts-default">
<!—
action:业务控制器,用于注册业务控制器组件
name:action名称,用于规定Action的访问路径
class:业务控制器组件,用于指定业务控制器对应的类
method:方法,用于指定访问当前action时要调用的方法
*请求URL:http://ip:port/projectName/namespace/ActionName.action -->
 <actionname="hello" class="test01.konrad.action.HelloAction" method="execute">
         <!—
         result:输出组件,用于转发、重定向、直接输出
         name:名称,一个action下可以有多个result,彼此不能重名
         默认值转发,元素内设置转发的页面-->
           <resultname="success">
             /hello.jsp
           </result>
         </action>
      </package>
</struts>
    可能在这里还会有些人看不懂流程,我用代码的方式来讲解流程问题
     写HelloAction类,建一个分类包test01.konrad.action,存放HelloAction类,里面写它的保存方法。
如:
private User2 user2;
public User2 getUser2() {
return user2;
}
public void setUser2(User2 user2) {
this.user2 = user2;
}
public String execute (){
userServiceIn serviceIn=new UserService2();
serviceIn.save(user2);
return "success";
}
     当客户端访问地址为hello时,struts2会根据配置文件去找相应的方法,如根据配置文件的配置,找到struts2配置文件中的name为hello的action,根据action配置找到test01.konrad.action包下的HelloAction类的execute()方法,会根据execute()方法返回值去判断result标签的name属性,如果哪个匹配就跳转至什么页面,这里是hello.jsp页面。
下面是原理图+ 6大核心组件,可参考上面来看。

FC:前端控制器,负责统一的分发请求
  Action:业务控制器,负责处理某一类业务
  ValueStack:Action与JSP数据交互的媒介
  Interceptor:拦截器,负责扩展Action,处理Action的共通事务
  Result:负责输出的组件
  Tags:标签,负责显示数据、生成框体


参数传递
1. Action从页面取值  
a) 基本属性注入(页面,Action)

b)域模型注入(页面,Action)

2.页面从Action取值
a)使用EL表达式

b) OGNL

OGNL
1.概念:Object Graph Navigation Language,是一门功能强大的表达式语言,类似于EL。Strut2默认采用OGNL表达式访问Action的数据,实际上是通过ValueStack对象来访问Action。
  2.用法:在Struts2中,OGNL表达式要结合Struts2标签来访问数据
    EL:${user.userName} <==> OGNL:<s:property value="user.userName">
    *a)访问基本属性  <s:property value="属性名"/>
    *b)访问实体对象  <s:property value="对象名.属性名"/>
    c)访问数组/集合  <s:property value="someArray[1]"/> | <s:property value="someList[1]"/>
    d)访问Map  <s:property value="someMap.key" />
    e)运算  <s:property value="'My name is' + name" />
    f)调用方法  <s:property value="name.toUpperCase()" />
    g)创建集合  <s:property value="{'a','b','c'}" /> ArrayList
    h)创建Map  <s:property value="#{'mm':'MM','nn':'NN'}" /> LinkedHashMap
 
ValueStack
 1.概念:是Struts2中,Action向页面传递数据的媒介,封装了Action的数据,并允许JSP通过OGNL来对其访问
  2.原理
3.访问ValueStack
    a)通过<s:debug>观察其结构
    b)输出栈顶:<s:property />
    c)访问Context对象:
      - OGNL表达式以"#"开头
      -key来访问context对象的值,即"#key"得到context中某属性值
    d)迭代集合

e)按数字迭代

4.ValueStack栈顶的变化
    - 默认情况下栈顶为Action
    - 循环过程中,栈顶为循环变量(集合迭代时,循环变量是集合中的对象,即栈顶为实体对象,可以以实体对象为root来写OGNL表达式;数字迭代时,循环变量是数字,不能以数字为实体对象,需要通过var声明变量名,以"#变量名"来引用,此情况下,是从context对象中取出值)
    - 循环结束后,栈顶变回Action
 
  5.EL表达式访问ValueStack
    a)EL也是从ValueStack中取的值
    b)EL默认的取值范围是page,request,session,application
    c)Struts2重写的request的getAttribute方法,先试图从原始request中取值,如果没取到再从ValueStack中取值
 
Result原理
1.介绍:用于做输出的组件,用于向页面输出一些内容,转发、重定向可以理解为特殊方式的输出。每一个Result实际上是一个类,这些类都实现了共同的接口ResultStruts2预置了10种类型的Result,定义在strtus-default.xml
  2.Result类型
    adispatcher:用于转发的result,可以将请求转发给JSP,这种类型的Result对应的类为ServletDispacherResult,通过default="true"指定该ResultStruts2默认的Result类型。
    bstream:用于向页面输出二进制数据,此种类型的Result可以将二进制数据输出到请求发起端,对应类为StreamResult
<result name="success" type="stream">
        <!--codeStream为定义在Action的输入流InputStream -->
    <param name="inputName">codeStream</param>
</result>
 
    credirectAction:用于将请求重定向给另外一个Action,对应类为ServletActionRedirectResult
<result name="login" type="redirectAction">
    <!--若重定向的Action与当前Action在同一个namespace下,可以省略namespace-->
    <param name="namespace">
            /命名空间
    </param>
    <param name="actionName">
            action
    </param>
</result>
    djson:用于向页面输出json格式的数据,可以将json字符串输出到请求发起端。对应类为JSONResult
<result name="success" type="json">
    <!--输出一个Action属性
   指定属性为基本类型,则直接返回该属性值
   如果指定属性为实体对象,则返回格式{"code":"as1","name":"hk"}
    -->
    <param name="root">属性名</param>
    <!--输出多个Action属性-->
    <param name="includeProperties">属性名1,属性名2...</param>
    <!--输出所有属性,不需要param标签-->
</result>
json需要导包,修改package继承关系为json-default
 
关于struts2框架中,最重要的就属拦截器。
拦截器的应用,在AOPAspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
谈到拦截器,还有一个词大家应该知道——拦截器链(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
1.拦截器的实现原理:
大部分时候,拦截器方法都是通过代理的方式来调用的。Struts 2的拦截器实现相对简单。当请求到达Struts 2ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。
2.用途:拦截器适合封装一些通用处理,便于重复利用。例如请求参数传递给Action属性,日志的记录,权限检查,事务处理等。拦截器是通过配置方式调用,因此使用方法比较灵活,便于维护和扩展。
3.使用步骤
1.创建拦截器组件(创建一个类,实现Interceptor接口,并实现intercept方法;也可以继承MethodFilterInterceptor,这种方式可以使action中某个方法不进行拦截)
          public String intercept(ActionInvocation invocation){
                  //拦截器--前部分处理
                    invocation.invoke();
                   //拦截器--后续处理     
          }
2注册拦截器
        <package>
                 <interceptors>
                              <interceptorname="别名" class="实现类"/>
                              <!--其他拦截器-->
                   </interceptors>
          </package>
3. 引用拦截器(哪个Action希望被拦截器扩展,需要在此action配置下,引用拦截器)
          <action>                 <!--手动的使用一次系统默认的拦截器-->                  <interceptor-refname="defaultStack"/>
                   <interceptor-refname="拦截器别名"/>
                    <!--可以写多个-->                  <!--可以使用excludeMethods参数属性,设置不过滤的方法-->
          </action>
4. 拦截器栈
          <interceptor-stackname="myStack">
                   <interceptor-refname="拦截器别名1"/>
                   <interceptor-refname="拦截器别名2"/>
          </interceptor-stack>
5. FileUpload拦截器
    a)原理:首先FileUpload拦截器将表单中提交的文件,以临时文件的形式保存到服务器临时路径下。之后FileUpload拦截器将该临时文件对象注入给ActionAction自主处理该临时文件。最后FileUpload拦截器删除临时文件。
    b)使用步骤
      导包 commons-io.jar
      Action:定义File类型属性(some),接受拦截器注入的临时文件对象。若想要获取原始文件名,要定义String类型属性,属性名为File类型属性+FileName(someFileName)
      表单设置:method="post" enctype="multipart/form-data"
    c)设置限制(Struts2文件上传默认最大值为2097152B,2M
      在struts.xml中重置默认限制值  <constant name="struts.multipart.maxSize" value="5000000" />
原创粉丝点击