3.Struts1.x工作原理

Struts1.x是MVC的最基础实现,那么在整个Struts1.x的开发过程之中,请求的处理流程是最需要关注的,
同时也是我们可以发现程序问题的所在。


整个Struts之中时将一个Servlet的控制变为了两个部分:ActionForm,Action.
它这样拆分的目的是为了让验证与具体的控制相分离。
分离的目的是为了让验证与核心操作分开,但是同时也产生一个新的问题,如果在项目之中,
每一个Action都要进行一个业务处理的话,那么这每一个Action都需要使用一个ActionForm进行匹配,
结果就是ActionForm会无限多;Struts1.x最大的缺点在于ActionForm过多。Struts2.x以及新的
各种开发框架之中最大的优点时利用了拦截器的方式来解决ActionForm的问题;
整个程序流程:图2


1.只要是MVC的操作,那么其基本的核心流程:JSP提交给Servlet,而后由Servlet再跳转到指定的
JSP页面;
2.再使用Struts框架的时候由于Struts框架里面支持有各种标签操作,所以再定义JSP的时候可以使用HTML标签生成
HTML元素,那么这种标签的好处是可以帮助用户隐藏一些代码的细节,例如:<html:text property="mid">,那么
这样的操作本身会生成HTML元素,但是同时它也可以自动的与ActionForm中的属性相关联(如果不使用这个标签,
参数名称必须再ActionForm中定义好);
同时在使用<html:form>标签的时候由于其会设置一个Action的处理路径(action="mylogin.do"),所以在生成HTML
代码之前都会默认先调用一次ActionForm的reset()方法表示进行内容的初始化;
3.随后表单要进行提交的时候输入的是”struts-config.xml“文件里面的配置的action的路径,同时后面要加上*.do ,
因为在Struts里面所有的处理都是提交给一个ActionServelt的,那么这个的配置在web.xml文件里面定义了;

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

之所以项目中的struts-config.xml文件有效,那么是因为在ActionServlet之中要读取此路径中的内容,读取后
一定要进行SAX解析进行文件的解析;这个ActionServlet是在项目加载的时候默认先执行的,
也就是说在项目容器一旦运行后会立刻加载struts的配置文件,而这个ActionServlet也可以作为请求的处理,处理的时候
只需要后缀为.do就可以找到这个Servlet。
4.当ActionServlet接收用户的请求之后,会自动的将其请求处理的路径与指定的ActionForm关联,而后利用反射动态设置ActionForm
类对象中的属性,调用setter方法,提交的路径是在Action上配置的,而Action与ActionForm的关联是在struts-config.xml文件定义的;

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config> 
<form-beans > 在此配置所有的ActionForm类
<form-bean 表示一个ActionForm的配置
name="myloginForm" 此ActionForm的名字,此名称在本文件有效
type="cn.struts.form.MyloginForm" /> ActionForm的对应的程序类名称

</form-beans>

<global-exceptions /> 定义全局异常
<global-forwards /> 定义全局条件,例如:errors.jsp,forward.jsp
<action-mappings > 定义所有的Action,ActionForm与Action的关联就在于此
<action 配置一个Action
attribute="myloginForm" 本Action要使用的ActionForm
input="/login.jsp" 默认的错误处理页,一旦出现了验证错误则跳转到此路径
name="myloginForm" 本Action要使用的ActionForm
path="/mylogin" 此Action的操作路径,与*do结合使用
scope="request" 可选的范围有两种:request,session
type="cn.struts.action.MyloginAction" 对应的Action类名称
cancellable="true">
<forward 局部跳转,只为一个Action服务
name="success" 跳转的名称(key),程序读取key取得跳转的路径
path="/login.jsp"/>跳转的路径
<forward name="failure" path="/login.jsp"/>
</action>
</action-mappings>

<message-resources 配置的式全局资源,可以实现国际化操作
parameter="cn.struts.ApplicationResources" /> 定义资源文件的路径
</struts-config>

5.当ActionForm里面有内容之后(都是利用反射设置的),那么会自动调用validate()方法进行数据的验证,如果出现了
错误,则向ActionErrors里面进行错误信息的保存,每一个错误信息都是由ActionMessage保存,
在ActionMessage的构造方法里面需要设置错误信息对应的资源文件中定义的key的信息。

mid.input.null=xxx
password.input.null=xxx

errors.add("参数名称",new ActionMessage("mid.input.null"));
如果此时validate()方法返回的内容式是null(不验证)或者说返回的ActionErrors(相当于一个集合)中的错误的数据个数为0,
表示为验证通过,则继续将处理交给Action完成,但是如果出现了错误(验证没有通过),则会使用input属性定义的跳转路径,将
请求跳转回指定的页面并且使用<html:errors>标签进行显示。
6.当验证通过之后会将请求交给Action进行处理,而在Acrtion里面(必须继承一个指定的父类),
会默认执行execute()方法进行控制器的执行,在控制器里面正常应该调用业务层中的方法,而后根据结果跳转到指定的路径;
所有的跳转路径都在struts-config.xml文件里面进行了定义;

<action
attribute="myloginForm"
input="/login.jsp"
name="myloginForm"
path="/mylogin"
scope="request"
type="cn.struts.action.MyloginAction"
cancellable="true">
<forward 
name="success" 
path="/login.jsp"/>
<forward name="failure" path="/login.jsp"/>
</action>

通过ActionMapping类可以读取struts-config.xml文件中的配置,并且利用这个类对象的findForward()方法可以设置要读取
数据key的信息,而后要跳转的路径会使用ActionForward类对象进行包装。而在ActionServlet类里面根据接收到的ActionForward里面
保存的路径key(name="success")取出对应的value(path="/login.jsp"),而后利用RequestDispatcher接口实现跳转操作。
总结:Struts1.x的缺点?
随着项目开发的进行,在Struts开发里面一定会存在有多个Action,但是每一个Action都必须有一个与之对应的ActionForm绑定,
那么开发的代码量实在是太大了,而且有些操作是不需要验证的,但是考虑到结构的完整性依然需要编写ActionForm,太重复了;
ActionForm是需要编写验证操作,但是如果真的分开来写,那么会出现一个问题,几乎90%的验证代码都是重复的;
所有的要使用的Action,ActionForm都要求在struts-config.xml文件里面进行定义,但如果开发量大,那么这个文件的庞大程序几乎
就不可想象,而且文件一大,在进行有些代码修改的时候,可能就会出现错乱;
综合来讲,整个Struts的开发的确满足了标准的MVC处理结构,但是最终发现,这种实现的方式也存在有用一定的历史局限性(在2005年之前所有的
开发都是基于配置文件编写的),以及初期的设计失误(ActionForm的操作上很失败)。
优点:
开发结构严谨,所有的开发者必须按照指定的结构继承类并且覆写指定的方法;
提供了大量的标签:
html标签:在于可以进行自动的数据填充以及数据回显上;
logic标签:实现页面的逻辑处理(循环、判断),有了JSTL之中,这个也没特点了;
bean标签:在没有EL之前,可以使用bean标签输出对象的属性内容,有了EL之后,这个操作不用了;
可以直接进行VO对象的转换以及分发操作。
一定要记住:Struts是在工作在显示层与控制层上的框架,它不涉及业务层与数据层;

posted on 2018-10-21 20:36 剑主_ch 阅读( ...) 评论( ...) 编辑 收藏