Struts是Apache 基金会Jakarta 项目组的一个Open Source 项目,它采用MVC模式,能够很好地帮助java 开发者利用J2EE开发Web应用。和其他的java架构一样,Struts 也是面向对象设计,将MVC模式"分离显示逻辑和业务逻辑"的能力发挥得淋漓尽致。Structs 框架的核心是一个弹性的控制层,基于如 Java Servlets,JavaBeans,ResourceBundles与XML等标准技术,以及 Jakarta Commons 的一些类库。Struts有一组相互协作的类(组件)、Servlet以及jsp tag lib组成。基于struts构架的web应用程序基本上符合JSP Model2的设计标准,可以说是一个传统 MVC设计模式的一种变化类型。
目的
Struts的目的是为了减少在运用MVC设计模型来开发Web应用的时间。
Struts的流程
服务器启动后,根据web.xml加载ActionServlet读取struts-config.xml文件内容到内存。
以登陆为例:第一次进login.jsp会先实例化Form、把默认值(String默认为空字符串,整形默认为0)赋给表单元素。 输入用户名密码提交表单、提交到action属性的login.do,通过ActionServlet读struts-config.xml文件找到 action下的path属性找到.do,通过name属性找form-beans中的form-bean的name属性得到ActionForm的包名类名,先实例化form,把表单的值填充给form,调用form的validate方法验证、ActionErrors返回null表示验证通过,否则失败返回input指定的页面.验证通过会实例化Action,执行Action的excute方法。
控制器:ActionServlet的作用
Action,这个类通常由用户提供,该控制器负责接收来自ActionServlet的请求,并根据该请求调用模型的业务逻辑方法处理请求,并将处理结果返回给JSP页面显示。org.apache.struts.action.ActionServlet类实现的,这个类是javax.servlet.http.HttpServlet类的扩展。
Model部分:ActionForm和JavaBean
由ActionForm和JavaBean组成,其中ActionForm用于封装用户的请求参数,封装成ActionForm对象,该对象被ActionServlet转发给Action,Action根据ActionFrom里面的请求参数处理用户的请求。 JavaBean则封装了底层的业务逻辑,包括数据库访问等。
View部分
该部分采用JSP实现。Struts提供了丰富的标签库,通过标签库可以减少脚本的使用,自定义的标签库可以实现与Model的有效交互,并增加了现实功能。
注意:
系统核心控制器,对应上图的ActionServlet。该控制器由Struts框架提供,继承HttpServlet类,因此可以配置成标注的Servlet。该控制器负责拦截所有的HTTP请求,然后根据用户请求决定是否要转给业务逻辑控制器。 业务逻辑控制器,负责处理用户请求,本身不具备处理能力,而是调用Model来完成处理。对应Action部分。
框架中所使用的组件
ActionServlet 控制器
ActionClass 包含事务逻辑
ActionForm 显示模块数据
ActionMapping 帮助控制器将请求映射到操作
ActionForward 用来指示操作转移的对象
ActionError 用来存储和回收错误
Struts标记库 可以减轻开发显示层次的工作
Struts配置文件
这是将struts组件结合在一起的东东:struts-config.xml。默认值
\WEB-INF\struts-config.xml。
配置文件可以定义:
全局转发
ActionMapping类 帮助控制器将请求映射到操作
ActionForm bean 显示模块数据
JDBC数据源
配置全局转发
全局转发用来在JSP页之间创建逻辑名称映射。
转发都可以通过对调用操作映射的实例来获得。
看看具体每个组件的作用
配置全局转发
<global-forwards>
<forward name="bookCreated" path="/BookView.jsp"/>
</global-forwards>
配置ActionMapping
ActionMapping对象帮助进行框架内部的流程控制,它们可将请求URI映射到Action类,并且将Action类与ActionForm bean相关联。ActionServlet在内部使用这些映射,并将控制转移到特定Action类的实例。
如:
<action-mappings>
<action path="/createBook" type="BookAction" name="bookForm" scope="request" input="/CreateBook.jsp">
</action>
<forward name=”failure” path=”/CreateBook.jsp”/>
<forward name=”cancel” path=”/index.jsp”/>
</action-mappings>
配置ActionForm Bean
<form-beans>
<form-bean name="bookForm" type="BookForm"/>
</form-beans>
配置JDBC数据源
ActionServlet类
框架中的控制器组件是有org.apache.struts.action.ActionServlet类实现的,这个类是javax.servlet.http.HttpServlet类的扩展。 Struts controller基本功能是:
1. 截获用户的Http请求
2. 把这个请求映射到相应的Action类,如果这是此类收到的第一个请求,将初始化实例并缓存。
3. 创建或发现一个ActionForm bean实例(看配置文件是否定义),然后将请求过程移植到bean.
4. 调用Action实例的perform()方法并将ActioForm bean,Action Mapping对象,request和response对象传给它。
5.perform返回一个ActionForword对象,此对象连接到相应的jsp页面.
ActionMapping类
将特定请求映射到特定Action的相关信息存储在ActionMapping中,ActionServelt将ActionMapping传送到Action类的perform()方法,Action将使用ActionMapping的findForward()方法,此方法返回一个指定名称的ActionForward,这样Action就完成了本地转发。若没有找到具体的ActionForward,就返回一个null。
public ActionForward findForward(String name)
可在映射中动态添加ActionForward:
public void addForward(ActionForward forward)
可返回与映射关联的表单bean:
public String getName()
可返回映射的属性域(会话或请求)
public String getScope()
Action类
Action类真正实现应用程序的事务逻辑,它们负责处理请求。在收到请求后,ActionServlet会: 为这个请求选择适当的Action 如果需要,创建Action的一个实例 调用Action的perform()方法 如果ActionServlet不能找到有效的映射,它会调用默认的Action类(在配置文件中定义)。如果找到了ActionServlet将适当的ActionMapping类转发给Action,这个Action使用ActionMapping找到本地转发,然后获得并设置ActionMapping属性。根据servlet的环境和被覆盖的perform()方法的签名,ActionServlet也会传送ServletRequest对象或HttpServletRequest对象。 所有Action类都扩展org.apache.struts.action.Action类。
ActionForm类
框架假设用户在应用程序中为每个表单都创建了一个ActionForm bean,对于每个在struts-config.xml文件中定义的bean,框架在调用Action类的perform()方法之前会进行以下操作: 在相关联的关键字下,它检查用于适当类的bean实例的用户会话,如果在会话中没有可用的bean,它就会自动创建一个新的bean并添加到用户的会话中。 对于请求中每个与bean属性名称对应的参数,Action调用相应的设置方法。 当Action perform()被调用时,最新的ActionForm bean传送给它,参数值就可以立即使用了。 ActionForm类扩展org.apache.struts.action.ActionForm类,程序开发人员创建的bean能够包含额外的属性,而且ActionServlet可能使用反射(允许从已加载的对象中回收信息)访问它。
ActionForward类
目的是控制器将Action类的处理结果转发至目的地。 Action类获得ActionForward实例的句柄,然后可用三种方法返回到ActionServlet,所以我们可以这样使用findForward(): ActionServlet根据名称获取一个全局转发 ActionMappin实例被传送到perform()方法,并根据名称找到一个本地转发
错误处理
struts提供了两个类来处理错误:ActionErrors和ActionError,它们都扩展org.apache.struts.action。ActionErrors保存着ActionError对象的集合,其中每一个代表了独立的错误信息。每个ActionError都包含了关键字,能够映射到资源文件中存储的错误信息,而这个资源文件是在ActionServlet初始化参数中指定的。
1.servlet的生命周期
servlet有良好的生存期的定义,包括如何加载、实例化、初始化、处理客户端请求以及如何被移除。
2.与CGI区别
在于servlet处于服务器进程中,
它通过多线程方式运行其service方法,
一个实例可以服务于多个请求,
并且其实例一般不会销毁,
而CGI对每个请求都产生新的进程,
服务完成后就销毁,
所以效率上低于servlet。
Struts优点与缺点
Struts是开源软件,使开发者能更深入的了解其内部实现机制。
Struts 优点:业界"标准"(很多成功案例),学习资源丰富。
Struts的优点主要集中体现在两个方面:Taglib和页面导航。
a、利用Struts提供的taglib可以大大节约开发时间。
b、维护扩展比较方便。通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。
c、表现与逻辑分离
d、表单验证解决了请求数据的验证问题,增强了系统健壮性。
e、便于团队开发
Struts缺点:
a、大量的使用标签,对于初学者难度较大。
b、ActionForms使用不便、无法进行单元测(StrutsTestCase只能用于集成)
Struts提供了几个标签库?都是什么标签库?
Struts提供了五个标签库,即:HTML、Bean、Logic、Template和Nested。
HTML 标签 用来创建能够和Struts 框架和其他相应的HTML 标签交互的HTML 输入表单
Bean 标签 在访问JavaBeans 及其属性,以及定义一个新的bean 时使用
Logic 标签 管理条件产生的输出和对象集产生的循环
Template 标签 随着Tiles框架包的出现,此标记已开始减少使用
Nested 标签 增强对其他的Struts 标签的嵌套使用的能力
Tiles框架是什么?
Tiles框架为创建Web页面提供了一种模板机制,它能将网页的布局和内容分离。
你对MVC的理解,MVC有什么优缺点?结合Struts,说明在一个Web应用如何去使用?
MVC设计模式(应用观察者模式的框架模式)
M: Model(Business process layer),模型,操作数据的业务处理层,并独立于表现层 (Independent of presentation)。
V: View(Presentation layer),视图,通过客户端数据类型显示数据,并回显模型层的执行结果。
C: Controller(Control layer),控制器,也就是视图层和模型层桥梁,控制数据的流向,接受视图层发出的事件,并重绘视图
MVC框架的一种实现模型
模型二(Servlet-centric): JSP+Servlet+JavaBean,以控制为核心,JSP只负责显示和收集数据,Sevlet,连接视图和模型,将视图层数据,发送给模型层,JavaBean,分为业务类和数据实体,业务类处理业务数据,数据实体,承载数据,基本上大多数的项目都是使用这种MVC的实现模式。
Struts MVC框架(Web application frameworks) Struts是使用MVC的实现模式二来实现的,也就是以控制器为核心。
Struts提供了一些组件使用MVC开发应用程序:
Model:Struts 没有提供model 类。这个商业逻辑必须由Web 应用程序的开发者以JavaBean或EJB的形式提供
View:Struts提供了action form创建form bean,用于在controller和view间传输数据。此外,Struts提供了自定义JSP标签库,辅助开发者用JSP创建交互式的以表单为基础的应用程序,应用程序资源文件保留了一些文本常量和错误消息,可转变为其它语言, 可用于JSP中。
Controller:Struts提供了一个核心的控制器ActionServlet,通过这个核心的控制器来调用其他用户注册了的自定义的控制器Action,自定义Action需要符合Struts的自定义Action规范,还需要在struts-config。xml的特定配置文件中进行配置,接收JSP输入字段形成Action form,然后调用一个Action控制器。Action控制器中提供了model的逻辑接口。
叙述Struts ActionForm执行步骤
(1)检查Action的映射,确定Action中已经配置了对ActionForm的映射
(2)根据name属性,查找form bean的配置信息
(3)检查Action的formbean的使用范围,确定在此范围下,是否已经有此form bean的实例。
(4)假如当前范围下,已经存在了此form bean的实例,而是对当前请求来说,是同一种类型的话,那么就重用。
(5)否则,就重新构建一个form bean的实例
(6)form bean的reset()方法备调用
(7)调用对应的setter方法,对状态属性赋值
(8)如果validatede的属性被设置为true,那么就调用form bean的validate()方法。
(9)如果validate()方法没有返回任何错误,控制器将ActionForm作为参数,传给Action实例的execute()方法并执行
简单叙述Struts 里 ActionForm Bean的作用
(1)ActionForm Bean也是一种JavaBean,除了具有一些JavaBean的常规方法,还包含一些特殊的方法,用于验证HTML表单数据以及将其属性重新设置为默认值。
(2)Struts框架利用ActionForm Bean来进行View组件和Controller组件之间表单数据的传递。
(3)Struts框架把View组件接受到的用户输入的表单数据保存在ActionForm Bean中,把它传递给Controller组件,Controller组件可以对ActionForm Bean中的数据进行修改,JSP文件使用Struts标签读取修改后的ActionForm Bean的信息,重新设置HTML表单。
简述Struts Form Bean的表单验证流程
(1)当用户提交了HTML表单,Struts框架自动把表单数据组装到ActionForm Bean中。
(2)接下来Struts框架会调用ActionForm Bean的validate()方法进行表单验证。
(3)如果validate()方法返回的ActionErrors 对象为null,或者不包含任何ActionMessage对象,就表示没有错误,数据验证通过。
(4)如果ActionErrors中包含ActionMessage对象,就表示发生了验证错误,Struts框架会把ActionErrors对象保存到request范围内,然后把请求转发到恰当的视图组件,视图组件通过<html:errors>标签把request范围内的ActionErrors对象中包含的错误消息显示出来,提示用户修改错误
简述Struts框架响应客户请求的工作流程
(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回用户请求路径无效的信息。
(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中。
(3)根据配置信息决定是否需要表单验证。如果需要验证,就调用ActionForm的validate()方法。
(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessge的ActionErrors对象,就表示表单验证成功。
(5)ActionServlet根据AtionMapping实例包含的映射信息决定将请求转发给哪个Action。如果应用的Action实例不存在,就先创建这个实例,然后调用Action的execute()方法。
(6)Action的execute()方法返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指向的JSP组件。
(7)ActionForward对象指向的JSP组件生成动态页面,返回给客户。
对于以上流程的步骤(4),如果ActionForm的validate()方法返回一个包含一个或多个ActionError的ActionErrors对象,就表示表单验证失败,此时ActionServlet将直接把请求转发给包含客户提交表单的JSP组件。在这种情况下,不会再创建Action对象并调用Action的execute方法。
Struts的工作机制,为什么要用?
工作机制:
在web应用启动时就会加载初始化ActionServlet,ActionServlet从struts-config.xml文件中读取配置信息,把它们存放到各种配置对象,当ActionServlet接收到一个客户请求时,将执行如下流程。
(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回请求路径无效信息;
(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm 对象中;
(3)根据配置信息决定是否需要表单验证。如果需要验证,就调用ActionForm的validate()方法;
(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功;
(5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪个Action,如果相应的 Action实例不存在,就先创建这个实例,然后调用Action的execute()方法;
(6)Action的execute()方法返回一个ActionForward对象,ActionServlet在把客户请求转发给 ActionForward对象指向的JSP组件;
(7)ActionForward对象指向JSP组件生成动态网页,返回给客户;
为什么要用:
JSP、Servlet、JavaBean技术的出现给我们构建强大的企业应用系统提供了可能。但用这些技术构建的系统非常的繁乱,所以在此之上,我们需要一个规则、一个把这些技术组织起来的规则,这就是框架,Struts便应运而生。
基于Struts开发的应用由3类组件构成:控制器组件、模型组件、视图组件
具体如图:
说下Struts的设计模式
MVC模式: web应用程序启动时就会加载并初始化ActionServler。用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数据,ActionServler根据Struts-config。xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后调用Action的execute()方法。Execute()从ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生成动态的网页,返回给客户。
单例模式 Factory(工厂模式):
定义一个基类===》实现基类方法(子类通过不同的方法)===》定义一个工厂类(生成子类实例) ===》开发人员调用基类方法
struts中的几个关键对象的作用(说说几个关键对象的作用)
ActionServlet,requestProcess,ActionForm,Action等等
Action是不是线程安全的?如果不是有什么方式可以保证Action的线程安全?如果是,说明原因
不是线程安全的。只要不申明类变量就可以保证线程安全。因为只存在一个Action类实例,所有线程会共享类变量。