博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA(四)
阅读量:4164 次
发布时间:2019-05-26

本文共 9794 字,大约阅读时间需要 32 分钟。

Java杂谈(九)--Struts 

                J2ee的开源框架很多,笔者只能介绍自己熟悉的几个,其他的目前在中国IT行业应用得不是很多。希望大家对新出的框架不要盲目的推崇,首先一定要熟悉它比旧的到底好在哪里,新的理念和特性是什么?然后再决定是否要使用它。   
               
                这期的主题是Struts,直译过来是支架。Struts的第一个版本是在2001年5月发布的,它提供了一个Web应用的解决方案,如何让Jsp和 servlet共存去提供清晰的分离视图和业务应用逻辑的架构。在Struts之前,通常的做法是在Jsp中加入业务逻辑,或者在Servlet中生成视图转发到前台去。Struts带着MVC的新理念当时退出几乎成为业界公认的Web应用标准,于是当代IT市场上也出现了众多熟悉Struts的程序员。即使有新的框架再出来不用,而继续用Struts的理由也加上了一条低风险,因为中途如果开发人员变动,很容易的招进新的会Struts的IT民工啊, ^_^!   
           
                笔者之前说的都是Struts-1,因为新出了Struts-2,使得每次谈到Struts都必须注明它是Struts-1还是2。笔者先谈比较熟悉的 Struts-1,下次再介绍一下与Struts-2的区别:   
               
                1.   Struts框架整体结构   
                Struts-1的核心功能是前端控制器,程序员需要关注的是后端控制器。前端控制器是是一个Servlet,在Web.xml中间配置所有 Request都必须经过前端控制器,它的名字是ActionServlet,由框架来实现和管理。所有的视图和业务逻辑隔离都是应为这个 ActionServlet,       它就像一个交通警察,所有过往的车辆必须经过它的法眼,然后被送往特定的通道。所有,对它的理解就是分发器,我们也可以叫做Dispatcher,其实了解Servlet编程的人自己也可以写一个分发器,加上拦截request的Filter,其实自己实现一个struts框架并不是很困难。主要目的就是让编写视图的和后台逻辑的可以脱离紧耦合,各自同步的完成自己的工作。   
                那么有了ActionServlet在中间负责转发,前端的视图比如说是Jsp,只需要把所有的数据Submit,这些数据就会到达适合处理它的后端控制器Action,然后在里面进行处理,处理完毕之后转发到前台的同一个或者不同的视图Jsp中间,返回前台利用的也是Servlet里面的forward 和redirect两种方式。所以到目前为止,一切都只是借用了Servlet的API搭建起了一个方便的框架而已。这也是Struts最显著的特性?? 控制器。   
                那么另外一个特性,可以说也是Struts-1带来的一个比较成功的理念,就是以xml配置代替硬编码配置信息。以往决定Jsp往哪个servlet提交,是要写进Jsp代码中的,也就是说一旦这个提交路径要改,我们必须改写代码再重新编译。而Struts提出来的思路是,编码的只是一个逻辑名字,它对应哪个class文件写进了xml配置文件中,这个配置文件记录着所有的映射关系,一旦需要改变路径,改变xml文件比改变代码要容易得多。这个理念可以说相当成功,以致于后来的框架都延续着这个思路,xml所起的作用也越来越大。   
       
                大致上来说Struts当初给我们带来的新鲜感就这么多了,其他的所有特性都是基于方便的控制转发和可扩展的xml配置的基础之上来完成它们的功能的。   
下面将分别介绍Action和FormBean,       这两个是Struts中最核心的两个组件。   
                    2.   后端控制器Action   
                Action就是我们说的后端控制器,它必须继承自一个Action父类,Struts设计了很多种Action,例如DispatchAction、 DynaValidationAction。它们都有一个处理业务逻辑的方法execute(),传入的request,       response,       formBean和actionMapping四个对象,返回actionForward对象。到达Action之前先会经过一个 RequestProcessor来初始化配置文件的映射关系,这里需要大家注意几点:   
                    1)   为了确保线程安全,在一个应用的生命周期中,Struts框架只会为每个Action类创建一个Action实例,所有的客户请求共享同一个Action 实例,并且所有线程可以同时执行它的execute()方法。所以当你继承父类Action,并添加了private成员变量的时候,请记住这个变量可以被多个线程访问,它的同步必须由程序员负责。(所有我们不推荐这样做)。在使用Action的时候,保证线程安全的重要原则是在Action类中仅仅使用局部变量,谨慎的使用实例变量。局部变量是对每个线程来说私有的,execute方法结束就被销毁,而实例变量相当于被所有线程共享。   
   
                    2)   当ActionServlet实例接收到Http请求后,在doGet()或者doPost()方法中都会调用process()方法来处理请求。 RequestProcessor类包含一个HashMap,作为存放所有Action实例的缓存,每个Action实例在缓存中存放的属性key为 Action类名。在RequestProcessor类的processActionCreate()方法中,首先检查在HashMap中是否存在 Action实例。创建Action实例的代码位于同步代码块中,以保证只有一个线程创建Action实例。一旦线程创建了Action实例并把它存放到 HashMap中,以后所有的线程会直接使用这个缓存中的实例。   
                    3)   <action>       元素的   <roles>   属性指定访问这个Action用户必须具备的安全角色,多个角色之间逗号隔开。RequestProcessor类在预处理请求时会调用自身的 processRoles()方法,检查配置文件中是否为Action配置了安全角色,如果有,就调用HttpServletRequest的 isUserInRole()方法来判断用户是否具备了必要的安全性角色,如果不具备,就直接向客户端返回错误。(返回的视图通过   <input>   属性来指定)   
                3.   数据传输对象FormBean   
                Struts并没有把模型层的业务对象直接传递到视图层,而是采用DTO(Data       Transfer       Object)来传输数据,这样可以减少传输数据的冗余,提高传输效率;还有助于实现各层之间的独立,使每个层分工明确。Struts的DTO就是 ActionForm,即formBean。由于模型层应该和Web应用层保持独立。由于ActionForm类中使用了Servlet       API,       因此不提倡把ActionForm传递给模型层,       而应该在控制层把ActionForm       Bean的数据重新组装到自定义的DTO中,       再把它传递给模型层。它只有两个scope,分别是session和request。(默认是session)一个ActionForm标准的生命周期是:   
                1)   控制器收到请求       ->       
                2)   从request或session中取出ActionForm实例,如不存在就创建一个       ->   
                3)   调用ActionForm的reset()方法       ->       
                4)   把实例放入session或者request中       ->       
                5)   将用户输入表达数据组装到ActionForm中       ->       
                6)   如眼张方法配置了就调用validate()方法           ->   
                7)   如验证错误就转发给   <input>   属性指定的地方,否则调用execute()方法   
                validate()方法调用必须满足两个条件:   
                1)   ActionForm       配置了Action映射而且name属性匹配   
                2)   <aciton>       元素的validate属性为true   
       
                如果ActionForm在request范围内,那么对于每个新的请求都会创建新的ActionForm实例,属性被初始化为默认值,那么reset ()方法就显得没有必要;但如果ActionForm在session范围内,同一个ActionForm实例会被多个请求共享,reset()方法在这种情况下极为有用。   
                4.   验证框架和国际化   
                Struts有许多自己的特性,但是基本上大家还是不太常用,说白了它们也是基于JDK中间的很多Java基础包来完成工作。例如国际化、验证框架、插件自扩展功能、与其他框架的集成、因为各大框架基本都有提供这样的特性,Struts也并不是做得最好的一个,这里也不想多说。Struts的验证框架,是通过一个validator.xml的配置文件读入验证规则,然后在validation-rules.xml里面找到验证实现通过自动为Jsp插入 Javascript来实现,可以说做得相当简陋。弹出来的JavaScript框不但难看还很多冗余信息,笔者宁愿用formBean验证或者 Action的saveErrors(),验证逻辑虽然要自己写,但页面隐藏/浮现的警告提示更加人性化和美观一些。   
                至于Struts的国际化,其实无论哪个框架的国际化,java.util.Locale类是最重要的Java       I18N类。在Java语言中,几乎所有的对国际化和本地化的支持都依赖于这个类。如果Java类库中的某个类在运行的时候需要根据Locale对象来调整其功能,那么就称这个类是本地敏感的(Locale-Sensitive),       例如java.text.DateFormat类就是,依赖于特定Locale。   
                创建Locale对象的时候,需要明确的指定其语言和国家的代码,语言代码遵从的是ISO-639规范,国家代码遵从ISO-3166规范,可以从   
                   
                   
                Struts的国际化是基于properties的message/key对应来实现的,笔者曾写过一个程序,所有Jsp页面上没有任何Text文本串,全部都用的是   <bean:message>   去Properties文件里面读,这个时候其实只要指定不同的语言区域读不同的Properties文件就实现了国际化。需要注意的是不同语言的字符写进Properties文件的时候需要转化成Unicode码,JDK已经带有转换的功能。JDK的bin目录中有native2ascii这个命令,可以完成对*.txt和*.properties的Unicode码转换。   
                OK,今天就说到这里,本文中的很多内容也不是笔者的手笔,是笔者一路学习过来自己抄下来的笔记,希望对大家有帮助!Java杂谈一路走来,感谢大家持续的关注,大概再有个2到3篇续篇就改完结了!笔者尽快整理完成后续的写作吧……^_^ 
############################################################################################################## 
Java杂谈(九)--Struts2 
        最近业余时间笔者一直Java       Virtual       Machine的研究,由于实习分配到项目组里面,不想从前那么闲了,好不容易才抽出时间来继续这个话题的帖子。我打算把J2ee的部分结束之后,再谈谈 JVM和JavaScript,只要笔者有最新的学习笔记总结出来,一定会拿来及时和大家分享的。衷心希望与热爱Java的关大同仁共同进步……   
        这次准备继续上次的话题先讲讲Struts-2,手下简短回顾一段历史:随着时间的推移,Web应用框架经常变化的需求,产生了几个下一代       Struts的解决方案。其中的Struts       Ti       继续坚持       MVC模式的基础上改进,继续Struts的成功经验。       WebWork项目是在2002年3月发布的,它对Struts式框架进行了革命性改进,引进了不少新的思想,概念和功能,但和原Struts代码并不兼       容。WebWork是一个成熟的框架,经过了好几次重大的改进与发布。在2005年12月,WebWork与Struts       Ti决定合拼,       再此同时,       Struts       Ti       改名为       Struts       Action       Framework       2.0,成为Struts真正的下一代。   
                看看Struts-2的处理流程:   
                1)   Browser产生一个请求并提交框架来处理:根据配置决定使用哪些拦截器、action类和结果等。   
                2)   请求经过一系列拦截器:根据请求的级别不同拦截器做不同的处理。这和Struts-1的RequestProcessor类很相似。   
                3)   调用Action:       产生一个新的action实例,调用业务逻辑方法。   
                4)   调用产生结果:匹配result       class并调用产生实例。   
                5)   请求再次经过一系列拦截器返回:过程也可配置减少拦截器数量   
                6)   请求返回用户:从control返回servlet,生成Html。   
                这里很明显的一点是不存在FormBean的作用域封装,直接可以从Action中取得数据。       这里有一个Strut-2配置的web.xml文件:   
                <filter>       
                        <filter-name>   controller   </filter-name>       
                        <filter-class>   org.apache.struts.action2.dispatcher.FilterDispatcher   </filter-class>   
                </filter>   
                <filter-mapping>       
                        <filter-name>   cotroller   </filter-name>       
                        <url-pattern>   /*   </url-pattern>   
                </filter-mapping>   
        注意到以往的servlet变成了filter,ActionServlet变成了FilterDispatcher,*.do变成了/*。filter 配置定义了名称(供关联)和filter的类。filter       mapping让URI匹配成功的的请求调用该filter。默认情况下,扩展名为   ".action   "。这个是在default.properties文件里的   "struts.action.extension   "属性定义的。   
        default.properties是属性定义文件,通过在项目classpath路径中包含一个名为“struts.properties”的文件来设置不同的属性值。而Struts-2的默认配置文件名为struts.xml。由于1和2的action扩展名分别为.do和.action,所以很方便能共存。我们再来看一个Struts-2的action代码:   
        public   class   MyAction   {   
              public   String   execute()   throws   Exception   {       
                      //do   the   work       
                      return   "success   ";   
              }   
        }   
        很明显的区别是不用再继承任何类和接口,返回的只是一个String,无参数。实际上在Struts-2中任何返回String的无参数方法都可以通过配置来调用action。所有的参数从哪里来获得呢?答案就是Inversion       of       Control技术(控制反转)。笔者尽量以最通俗的方式来解释,我们先试图让这个Action获得reuqest对象,这样可以提取页面提交的任何参数。那么我们把request设为一个成员变量,然后需要一个对它的set方法。由于大部分的action都需要这么做,我们把这个set方法作为接口来实现。   
        public   interface   ServletRequestAware   {   
                public   void   setServletRequest(HttpServletRequest   request);   
        }   
        public   class   MyAction   implements   ServletRequestAware   {       
                private   HttpServletRequest   request;       
                public   void   setServletRequest(HttpServletRequest   request)   {       
                        this.request   =   request;       
                }   
                               
                public   String   execute()   throws   Exception       {   
                          //     do   the   work   directly   using   the   request       
                          return       Action.SUCCESS;       
                }       
        }   
        那么谁来调用这个set方法呢?也就是说谁来控制这个action的行为,以往我们都是自己在适当的地方写上一句 action.setServletRequest(…),也就是控制权在程序员这边。然而控制反转的思想是在哪里调用交给正在运行的容器来决定,只要利用Java反射机制来获得Method对象然后调用它的invoke方法传入参数就能做到,这样控制权就从程序员这边转移到了容器那边。程序员可以减轻很多繁琐的工作更多的关注业务逻辑。Request可以这样注入到action中,其他任何对象也都可以。为了保证action的成员变量线程安全, Struts-2的action不是单例的,每一个新的请求都会产生一个新的action实例。   
        那么有人会问,到底谁来做这个对象的注入工作呢?答案就是拦截器。拦截器又是什么东西?笔者再来尽量通俗的解释拦截器的概念。大家要理解拦截器的话,首先一定要理解GOF23种设计模式中的Proxy模式。   
        A对象要调用f(),它希望代理给B来做,那么B就要获得A对象的引用,然后在B的f()中通过A对象引用调用A对象的f()方法,最终达到A的f()被调用的目的。有没有人会觉得这样很麻烦,为什么明明只要A.f()就可以完成的一定要封装到B的f()方法中去?有哪些好处呢?   
        1)   这里我们只有一个A,当我们有很多个A的时候,只需要监视B一个对象的f()方法就可以从全局上控制所有被调用的f()方法。   
        2)   另外,既然代理人B能获得A对象的引用,那么B可以决定在真正调A对象的f()方法之前可以做哪些前置工作,调完返回前可有做哪些后置工作。   
        讲到这里,大家看出来一点拦截器的概念了么?它拦截下一调f()方法的请求,然后统一的做处理(处理每个的方式还可以不同,解析A对象就可以辨别),处理完毕再放行。这样像不像对流动的河水横切了一刀,对所有想通过的水分子进行搜身,然后再放行?这也就是AOP(Aspect       of       Programming面向切面编程)的思想。   
        Anyway,Struts-2只是利用了AOP和IoC技术来减轻action和框架的耦合关系,力图到最大程度重用action的目的。在这样的技术促动下,Struts-2的action成了一个简单被框架使用的POJO(Plain       Old       Java       Object)罢了。实事上AOP和IoC的思想已经遍布新出来的每一个框架上,他们并不是多么新的技术,利用的也都是JDK早已可以最到的事情,它们代表的是更加面向接口编程,提高重用,增加扩展性的一种思想。Struts-2只是部分的使用这两种思想来设计完成的,另外一个最近很火的框架 Spring,更大程度上代表了这两种设计思想,笔者将于下一篇来进一步探讨Spring的结构。   
        PS:       关于Struts-2笔者也没真正怎么用过,这里是看了网上一些前辈的帖子之后写下自己的学习体验,不足之处请见谅! 
################################################################################################################## 
Java杂谈(十)--Spring 
                笔者最近比较忙,一边在实习一边在寻找明年毕业更好的工作,不过论坛里的朋友非常支持小弟继续写,今天是周末,泡上一杯咖啡,继续与大家分享J2ee部分的学习经验。今天的主题是目前很流行也很好的一个开源框架-Spring。   
                引用《Spring2.0技术手册》上的一段话:   
                Spring的核心是个轻量级容器,它是实现IoC容器和非侵入性的框架,并提供AOP概念的实现方式;提供对持久层、事务的支持;提供MVC       Web框架的实现,并对于一些常用的企业服务API提供一致的模型封装,是一个全方位的应用程序框架,除此之外,对于现存的各种框架,Spring也提供了与它们相整合的方案。   
接下来笔者先谈谈自己的一些理解吧,Spring框架的发起者之前一本很著名的书名字大概是《J2ee       Development       without       EJB》,他提倡用轻量级的组件代替重量级的EJB。笔者还没有看完那本著作,只阅读了部分章节。其中有一点分析觉得是很有道理的:   
                EJB里在服务器端有Web       Container和EJB       Container,从前的观点是各层之间应该在物理上隔离,Web       Container处理视图功能、在EJB       Container中处理业务逻辑功能、然后也是EBJ       Container控制数据库持久化。这样的层次是很清晰,但是一个很严重的问题是Web       Container和EJB       Container毕竟是两个不同的容器,它们之间要通信就得用的是RMI机制和JNDI服务,同样都在服务端,却物理上隔离,而且每次业务请求都要远程调用,有没有必要呢?看来并非隔离都是好的。   
                再看看轻量级和重量级的区别,笔者看过很多种说法,觉得最有道理的是轻量级代表是POJO       +       IoC,重量级的代表是Container       +       Factory。(EJB2.0是典型的重量级组件的技术)我们尽量使用轻量级的Pojo很好理解,意义就在于兼容性和可适应性,移植不需要改变原来的代码。而Ioc与Factory比起来,Ioc的优点是更大的灵活性,通过配置可以控制很多注入的细节,而Factory模式,行为是相对比较封闭固定的,生产一个对象就必须接受它全部的特点,不管是否需要。其实轻量级和重量级都是相对的概念,使用资源更少、运行负载更小的自然就算轻量。   
                话题扯远了,因为Spring框架带来了太多可以探讨的地方。比如它的非侵入性:指的是它提供的框架实现可以让程序员编程却感觉不到框架的存在,这样所写的代码并没有和框架绑定在一起,可以随时抽离出来,这也是Spring设计的目标。Spring是唯一可以做到真正的针对接口编程,处处都是接口,不依赖绑定任何实现类。同时,Spring还设计了自己的事务管理、对象管理和Model2       的MVC框架,还封装了其他J2ee的服务在里面,在实现上基本都在使用依赖注入和AOP的思想。由此我们大概可以看到Spring是一个什么概念上的框架,代表了很多优秀思想,值得深入学习。笔者强调,学习并不是框架,而是框架代表的思想,就像我们当初学Struts一样……   
                1.Spring       MVC   
                关于IoC和AOP笔者在上篇已经稍微解释过了,这里先通过Spring的MVC框架来给大家探讨一下Spring的特点吧。(毕竟大部分人已经很熟悉Struts了,对比一下吧)   
众所周知MVC的核心是控制器。类似Struts中的ActionServlet,Spring里面前端控制器叫做DispatcherServlet。里面充当Action的组件叫做Controller,返回的视图层对象叫做ModelAndView,提交和返回都可能要经过过滤的组件叫做 Interceptor。   
                让我们看看一个从请求到返回的流程吧:   
                (1)   前台Jsp或Html通过点击submit,将数据装入了request域   
                (2)   请求被Interceptor拦截下来,执行preHandler()方法出前置判断   
                (3)   请求到达DispathcerServlet   
                (4)   DispathcerServlet通过Handler       Mapping来决定每个reuqest应该转发给哪个后端控制器Controlle

转载地址:http://qgvxi.baihongyu.com/

你可能感兴趣的文章
BOOST_TYPEOF和BOOST_AUTO 作用
查看>>
随机森林概述
查看>>
2011十大战略技术
查看>>
大学应该学的软件知识
查看>>
腾讯看了会沉默,360看了会流泪
查看>>
李开复:移动互联网机会最大 微博会现最大赢家
查看>>
2006年的IT十大战略技术
查看>>
操作系统介绍
查看>>
Desktop Linux: The Dream Is Dead
查看>>
我的9年IT路
查看>>
任正非:让用户像用电一样享受云计算
查看>>
学习技术的几个境界
查看>>
计算机世界:免费的代价
查看>>
方兴东:中国网站十年
查看>>
2010年微软和谷歌十大战场:从桌面到浏览器
查看>>
服务器虚拟化的未来之路
查看>>
写给我们这些浮躁的系统工程师
查看>>
和平分手?你根本不知道吴恩达在百度经历了什么
查看>>
业余研究:关于腾讯与他的QQ帝国
查看>>
马云校长湖畔大学第三期讲义完整版
查看>>