论坛首页 Java企业应用论坛

对struts的一点理解

浏览 6076 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-05-12  
对struts的一点理解.
  因为1.0比较简单,先从1.0的源码开始看起的,看过之后,虽然有些地方不是很清楚,但大体的框架能够理解了,
其实struts1.0之中使用的技术也不过那些,servlet,jsp,tag,java的内省机制,xml,以及实现国际化的东西。看过
一些介绍struts的东西,国内的大多都是垃圾,英文的还看不懂,开始很郁闷,所以我说英语是多么的重要!用我的理解
方式来说struts是这养的:1客户端发出请求,表现成带有参数的一个串像 abc.do?aa=aa&bb=bb 这里是开始 2struts中只有
一个servlet,请求会被传到这里,他的作用主要有两个,a:改变 session级,servletcontext级,request级 的数据,也就是说
他把从业务逻辑中得到的数据放到这三个地方,想想,就只有这三个地方了吧,然后他会是用servletcontext.getRequestdispather(通过forwardd得到的路径),
跳到一个jsp,这个jsp就是传说中的view,因为数据都是已经是现成的了,被actionservlet放到了三个级别中,所以他的工作就是使用tag显示
这些数据,当然里面需要一些技巧,(写到这里就知道自己的文学水平差啊,我看我写的东西也就自己能看懂,没关系,我不介意^_^)。
  我再次说一下一个问题,struts很花稍,但实时上可以抽象成两个servlet(1 actionServlet 2,显示的jsp) 他们之间是通过RequestDispatcher来联系的
第一个是处理数据,将数据放到3个级别的地方,第二个就是用这些数据显示页面,当然之间会有很多枝杈,但大体就是可以这么理解,所以我说struts
不过如此,至少1.0是这样。但是因为我刚入挨踢,做起项目还是很费劲,自己给自己打气吧吧!
  说这些都是没用的,你要真正立即struts还要看他的源码,不然本来很垃圾的东西,你会觉得他很神,这些感觉更多是宣传出来的。1.0比较
简单,1.1就相对复杂了,但我想有些思想是相同的,所以我看1.0目的是为了学习1.1,学习1.1是为了做东西,唉,还真麻烦,好了,我就大致
说说struts的流程,再罗索一下,我用的是jb9来看源码的,因为我喜欢点右键有个findDefinition 这样跳转起来很方便。
struts1.0中最重要的应该是ActionServlet,它在org.apache.struts.action下,哦,也不短了,
  
                         public class ActionServlet
                           extends HttpServlet {
看看这里就知道他是一个servlet,所以应该从public void init() throws ServletException { 这个init方法开始,我简单的介绍一下
initActions(),记住点右键找findDefinition啊,他会初始一个actions ,这个action 是一个protected FastHashMap  看这里:
protected FastHashMap actions = new FastHashMap(); 他是在servlet生成的时候就生成的了,我要说一下fasthasmap, 想这种fast**
的东西,你都可以立即成去掉fast后的形式,他只不过是struts自定义的一个集合,有两种形态fast:ture 和fast:false false用在初始化
的时候,这是候使用的是会 synchronized (this)来处理多线程的冲突,这样会比较慢,而ture会使用 synchronized (map)用clone的方法处理,
这个不重要,理解是个hashmap就行了, 接着是initInternal(),他是这样的:internal = MessageResources.getMessageResources(internalName)
internal 是 MessageResources 对象,他是实现国际化的那类东西,具体的很麻烦,理解到这就行了,他主要用于servlet内部写日志用的,
initDebug(); 调试级别,是从web.xml中读出来的,getServletConfig().getInitParameter("debug");具体的级别我不太清楚,反正不是很重要的东西
然后是 initApplication() 这个方法跟initInternal()只不过他初始化的 MessageResources 是给用户用的,并且放到ServletContext级 看这里:
getServletContext().setAttribute(Action.MESSAGES_KEY, application); 这个就是在jsp中用<bean:message>使用到的东西,
接下来是一个非常重要的初始化方法 initMapping()他会从web.xml中读取一些信息比如validating,formBean,forward,但这并不是主要的,主要的是这里
if (validate)
    digester = initDigester(detail);
else
    digester = initDigesterOld(detail);
这个是让我迷惑过的东西,我们主要看initDigester,另一个差不多,digester是一个解析struts-config.xml内容的东西,当然什么xml都可以,
我们找一段看看就行了:
          digester.addObjectCreate("struts-config/action-mappings/action",
                                 mappingClass, "className");
        digester.addSetProperties("struts-config/action-mappings/action");
        digester.addSetNext("struts-config/action-mappings/action",
                            "addMapping",
                            "org.apache.struts.action.ActionMapping");

        digester.addSetProperty
            ("struts-config/action-mappings/action/set-property",
             "property", "value");
这个是解析actionMapping的代码,都是先这样,最有调用digester.parse(input),input是xml的流
这些add方法都是在添加rule用来在digester.parse(input)用,然后会通过内省调用servlet中的addDataSource addDataSource addForward
addMapping 这就实现了从mxl到类的转换。接着是initUpload()这个是初始化上传文件的东西,接着是initDataSources(),1.1中可能不这样用了
他将dataSources中的GenericDataSource 按照key放到servletcontext级中,接着是initOther 主要是做
   getServletContext().setAttribute(Action.FORM_BEANS_KEY, formBeans);
getServletContext().setAttribute(Action.FORWARDS_KEY, forwards);
getServletContext().setAttribute(Action.MAPPINGS_KEY, mappings);
接着是 initServlet,完成将urlpatten(abc.do)放到ServletContext, getServletContext().setAttribute(Action.SERVLET_KEY,
                                             servletMapping);
这样init方法玩了,他如要是实现根据struts-config.xml生成formBeans forwards mappings 然后放入servletcontext中,

  下面应该是调用servlet的doget和,dopost方法了,但是他们都没有直接实现而是调用了protected void process(HttpServletRequest request, HttpServletResponse response) 这个方法,这个就是ActionServlet的核心方法,在1.1中又被分离了一部分,找到他看看,
  这个process中也是在调用很多的process**; 第一个就是processPath(); processLocale(request);....这些都很简单,直到这里processMapping()
                     protected ActionMapping processMapping(String path,
                                           HttpServletRequest request) {

        ActionMapping mapping = findMapping(path);
        if (mapping == null)
            mapping = mappings.getUnknown(request);
        if (mapping != null)
            request.setAttribute(Action.MAPPING_KEY, mapping);
        return (mapping);

    }
先根据path(就是xml action中的path)在mappings中找到特定的ActiongMapping 放到request中,并返回他,这是真正跟你的程序有关的开始,
然后是processActionForm(), processPopulate(formInstance, mapping, request);这个方法就是使用内省将请求的参数放到actionform中去,注意 ActionFormBean,和ActiongForm的区别,ActionFormBean中装的是Actiongform的信息,包括名字,和类的类型,这些都是通过digester从xml中获得的,ActionFormBean是用来创建一个新的actionform的东西,也会使用到内省。然后processValidate() 主要是调用actiongform中的validate,和处理errors
request.setAttribute(Action.ERROR_KEY, errors);errors就放在request中,供jsp用,errors是一个HashMap的数据结构的类,key和一个ArrayList,
然后是processForward,processInclude这些是xml中设施相关项,引发的效果一般不用吧,我是很少是forward,和include 然后是processActionCreate(),如果action存在,就从actions通过action的类名查到相应的实例,没有,创建。
action只不过是servlet中的类而已,只不过传了几个重要的参数,就显得很牛×, 然后是:
  ActionForward forward =
            processActionPerform(actionInstance, mapping, formInstance,
                                 request, response);
这个方法很熟悉了完成处理数据,和返回ActionForward,(人家都说起到控制调度模块,和跳转页面,我太俗了)ActionForward其实就是个路径!去看看他的定义,很简单。最后就是processActionForward()有两种跳转方式
           response.sendRedirect(response.encodeRedirectURL(path));//request中的东西没有了
           rd.forward(request, response);//request中的东西保存
就这样条转到了一个相应的jsp去了
    再然后,就应该是servlet的生命周期方法destroy()了
               public void destroy() {

if (debug >= 1)
    log(internal.getMessage("finalizing"));

        destroyActions();
destroyApplication();
        destroyDataSources();
destroyInternal();

    }
  这里的东西都很简单。

  总结一下,struts是这样的,一开始,通过xml初始化,生成formBeans forwards mappings 等,放到相应的位置,然后再process中,得到ActionMapping,
通过ActiongMapping调用processActionForm(mapping, request);得到ActionForm,然后组装参数,然后是 processActionCreate()获得action,然后调用
processActionPerform得到Actionforward(找到path,用于作为Dispatcher的参数) 最后是processActionForward()跳转走,就这样完了,

  再说说用到的类,ActionServlet就是一个普通的servlet,action是servlet中的类,目的是调用模块,以及得到返回页,actiongMapping是个内容很多的东西,
1.0中放在actionMappings中,(actionMappings是个集合),actionforward主要是存放路径信息,actionform可以理解成一个bean,struts页面显示的数据来源,
都喜欢用bean的形式。


  希望一边看源码一遍看我的垃圾,如果我们心灵相同,我想你会找到点东西的,没有看到有人贴过介绍源码的贴,我希望研究struts的前辈能够写点心得,或者帮忙,
修改,看再多的文档也不如show me the code!!!  我很弱,但是我很喜欢看真实的东西,这样才能变强,java是很不好入手,尤其是像我这样英文很烂的人,真是
太痛苦了,我说的东西很肤浅,但是思路还是很清晰,起码我看的懂,现在想想为什么还单身啊,表达能力太弱了,
  虽然我的贴是垃圾,但是我很喜欢,就当作,一个总结吧,我会接着看1.1,如果水平有提高,会接着贴新的,
  我们poper的信念就是不怕BT,越B越勇;
  在这里宣传一下POP:http://pop.pcpop.com 欢迎加入神族
                                                                                by:show me the code
                                                                                2004-5-12 11:31:33
   发表时间:2004-05-12  
http://www.cn-java.com/target/news.php?news_id=2684

我去年写的一篇,可能也是你眼中的垃圾。呵呵
0 请登录后投票
   发表时间:2004-05-12  
孤魂的文章是去年才写的吗?
我记得很早以前就读过了。:)
受益匪浅。

今天看完lq8202的帖子,就看到你的跟贴,
就又读了一遍,感觉还是受益匪浅。

lq8202的文章写的也不错,
特别是不用担心别人看不懂,我看了,很明白。
不过我推荐你也读读孤魂的那篇文章。
在很多Struts源码的工作机理上阐述的相当清楚。
也感激把自己的理解和经验拿出来和别人分享。
可以给人一个基本的概貌。
不过很多问题上,还要知其然也知其所以然。
记得我读孤魂的那篇文章的时候,
正在做一个和Sturts类似的框架,
从Struts里吸取了Processer的设计和异常处理机制
一种技术所以流行,不是全靠宣传,
只了解Struts是怎么流程的是不够的,
而要了解它技术上比别人优势的地方。
比如现在大家都觉得webwork比struts要好,
你会发现它们的原理和流程几乎是一样的,
那么,好在哪里了呢?

呵呵!读孤魂的文章时候,我对Struts知之甚少,
所以有很多东西读不懂,而读你的文章的时候,
已对其有相当的了解,所以收获自然不如当年大,
但这并不说明你的文章不好,就如同不能因为我
读不懂就说他的表达能力比你差一样。:)

另外问一句题外话:孤魂是在加拿大吗?
0 请登录后投票
   发表时间:2004-05-12  
我也忘记了是什么时候写的,写了很久才在chinajavaworld.net放了上去。应该在2002年底写的吧。
BTW:我在广州。
0 请登录后投票
   发表时间:2004-05-19  
最近一直比较懒没有上网,没想到能看到楼上的两位大哥的回复^_^
  小弟是今年6月毕业,刚接触java很短,所以脸皮才这么厚,发了这个烂贴,楼上的东西一定好好拜读,这么好的东西怎么都没有好好宣传,上面的大哥说的对,只知道流程是不够的,但知道流程应该是第一步,对不?
  这个论坛的人都很强,佩服,以后要多给宣传。
0 请登录后投票
   发表时间:2004-05-19  
有问题还要向各位请教
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics