java编程思想总结(三)
java编程思想总结是一个持续更新的系列,是本人对自己多年工作中使用到java的一个经验性总结,也是温故而知新吧,因为很多基础的东西过了这么多年,平时工作中用不到也会遗忘掉,所以看看书,上上网,查查资料,也算是记录下自己的笔记吧,过一段时间之后再来看看也是蛮不错的,也希望能帮助到正在学习的人们,本系列将要总结一下几点:
- 面向对象的编程思想
- java的基本语法
- 一些有趣的框架解析
- 实战项目的整体思路
- 代码的优化以及性能调优的几种方案
- 整体项目的规划和视角
- 其它遗漏的东西以及补充
一些有趣的框架解析
框架部分主要描述一些我在工作中遇到的常用框架,主要针对WEB开发,最常接触到就是大家都熟悉的Hibernate,Struts,Spring以及SpringMVC,后来玩分布式又熟悉了Hessian等服务框架,当然还有一些例如Quartz,IBATIS,MyBatis,Jackson,Freemarker等有意思的框架,客户的需求总是千奇百怪,幸亏有这么多有趣的框架存在,节约了我们很多时间,去研究研究它们,总能给自己带来一些新的想法和思路,开阔眼界,当然今天主要是总结性的概述这些框架的作用(优缺点),以及它们有趣的地方,我自己也算是复习吧,毕竟时间总是能带走很多东西!
Hibernate
创始人:Gavin King
背景故事:
时间2001年,地点是澳大利亚悉尼的Clarence Street有一家叫做Cirrus Technologies的公司,这是一家做J2EE企业级应用开发和咨询的公司,Gavin King在工作的时候发现CMP(实体bean技术)效率太烂(来自百度百科),并决定设计一种更好的方案,因此与当时的老板产生了争执,为了赢得争执,Gavin King耗时2年开发了Hibernate,这就是Gavin King,一个充满激情、脾气很倔、永不言败的人。
工作原理:
Hibernate技术本质是一个ORM(对象关系映射)框架,提供数据库服务的中间件。它是利用数据库以及其他一些配置文件(Hibernate.properties,XML Mapping等)为应用程序提供数据持久化服务。
1. hibernate如何连接数据库?
配置文件Hibernate.cfg.xml文件中定义了和数据库进行连接的信息,包括数据库方言.jdbc驱动.用户名.密码和URL等。
Configuration 类借助dom4j的xml解析器进行xml的解析设置环境,然后使用这些环境属性来生成sessionfactory。
这样sessionfactory生成的session 就能够成功获得数据库的连接。
2. hibernate如何进行数据库写操作?
当保存一个pojo持久化对象时,触发Hibernate保存事件监听器进行处理。
Hibernate通过映射文件获得对象对应的数据库表名以及属性对应的数据库列名,然后通过反射机制获得持久化对象的各个属性,最终组织向数据库插入新对象的SQL的insert语句。
调用session.save()保存数据后这个对象会被标识为持久化状态放在session,当事物进行提交时才真正执行 insert语句。
3. hibernate如何从数据中载入对象?
当需要读取读取文件时,Hibernate先尝试从session缓存中读取,如果session缓存数据不存在或是脏数据并且配置了二级缓存,Hibernate尝试从二级缓存中检索数据;否则Hibernate会根据对象类型·主键等信息组织select语句到数据库中读取,再把select结果组织成对象返回。
4. hibernate如何进行数据库查询操作?
Hibernate提供SQL HQL Criteria查询方式。HQL是其中运用最广泛的查询方式。
用户使用session.createQuery()函数以一条HQL语句为参数创建Query查询对象后,Hibernate会使用Anltr库把HQL语句解析成jdbc可以识别的sql语句。如果设置了 查询缓存,那么执行Query.list()时,Hibernate会先对查询缓存进行查询,如果查询缓存不存在,在使用select语句查询数据库。
优点:
- 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
- Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
- hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
- hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
缺点:
- 由于对持久层封装过于完整,导致开发人员无法对SQL进行优化,无法灵活使用JDBC的原生SQL,Hibernate封装了JDBC,所以没有JDBC直接访问数据库效率高。要使用数据库的特定优化机制的时候,不适合用Hibernate。
- 框架中使用ORM原则,导致配置过于复杂,一旦遇到大型项目,比如300张表以上,配置文件和内容是非常庞大的,另外,DTO满天飞,性能和维护问题随之而来。
- 如果项目中各个表中关系复杂,表之间的关系很多,在很多地方把lazy都设置false,会导致数据查询和加载很慢,尤其是级联查询的时候。
- Hibernate在批量数据处理时有弱势,对于批量的修改,删除,不适合用Hibernate,这也是ORM框架的弱点。
MyBatis(IBatis)
创始人:Clinton Begin,Apache软件基金会
背景故事:
IBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2002年发起的开放源代码项目。于2010年6月16号迁移至谷歌,改名为MyBatis。
工作原理:
MyBatis(ibatis) 是一个基于Java的半自动化的持久框架,半自动化是指ibatis并不会在运行期自动生成sql语句执行,而是具体的sql需要通过配置文件进行编写,并将所需的参数,以及返回的结果字段映射到指定的POJO.
MyBatis(ibatis)通过 SQL Map 将 Java 对象映射成 SQL 语句和将结果集再转化成 Java 对象,与其他 ORM 框架相比,既解决了 Java 对象与输入参数和结果集的映射,又能够让用户方便的手写使用 SQL 语句。
MyBatis(ibatis)要达到目的就是把用户关心的和容易变化的数据放到配置文件中配置,方便用户管理。而把流程性的、固定不变的交给 MyBatis(ibatis)来实现。这样是用户操作数据库简单、方便,这也是 MyBatis(ibatis)的价值所在。
优点:
- iBATIS被广泛认为是最简单的一种持久化框架,sql可以写在xml中,结构清晰,灵活配置。
- 文件归类,select 后的字须定义到标签中,可以实现部分代码复用。
- 执行sql后,返回的结果集自动封装。类似以下代码,均可省略。
- MyBatis真正的力量是在映射语句中。
这里是奇迹发生的地方。对于所有的力量,SQL映射的XML文件是相当的简单。
当然如果你将它们和对等功能的JDBC代码来比较,你会发现映射文件节省了大约95%的代码量。
MyBatis的构建就是聚焦于SQL的,使其远离于普通的方式。
简洁的代码和简单的配置使得使用iBATIS所需的代码量可以减少到了相应JDBC代码的62%
总结一下:可以省代码。
- 动态sql。
- MyBatis改进了应用的设计方式以确保未来的可维护性,后期可维护性增加。
- 基于xml的,所以适合多平台。
缺点:
- 开源的东西,文档资料少,官方说明文档太简单,真正有应用价值的信息不多。
- 实现了结果集自动封装,一把双刃剑,返回的结果集封装结果单一,不能实现灵活封装,同名字段,会覆盖。
- sql写在xml, 没有办法打断点,调试非常不方便。
- 日志输出不完全。
- 错误信息提示异样 ,报错信息比较混乱,有些时间没有参考价值,没有起到提示作用。
- 文档少,现有的文档提供的标签,也不能完全满足我们的需求。
Hibernate与MyBatis(IBatis)的对比
- iBATIS非常简单易学,Hibernate相对较复杂,门槛较高。iBATIS拿来文档看半天到两天就可以掌握了。Hibernate可能需要3倍以上的时间来掌握。
- 二者都是比较优秀的开源产品。但Hibernate现在已经是主流O/R Mapping框架,从文档的丰富性,产品的完善性,版本的开发速度都要强于iBATIS。
- 当系统属于二次开发,无法对数据库结构做到控制和修改,那iBATIS的灵活性将比Hibernate更适合。
- 系统数据处理量巨大,性能要求极为苛刻,这往往意味着我们必须通过经过高度优化的SQL语句(或存储过程)才能达到系统性能设计指标。在这种情况下iBATIS会有更好的可控性和表现。iBatis比Hibernate更容易进行sql的优化。鉴于一般系统性能的瓶颈都在数据库上,所以这一点是iBatis非常重要的一个优势。
- iBatis 可以进行细粒度的优化
- iBatis需要手写sql语句,也可以生成一部分,Hibernate则基本上可以自动生成,偶尔会写一些Hql。同样的需求,iBATIS的工作量比Hibernate要大很多。类似的,如果涉及到数据库字段的修改,Hibernate修改的地方很少,而iBATIS要把那些sql mapping的地方一一修改。
- 维护方面
iBatis更好一些。因为iBatis的sql都保存到单独的文件中。而Hibernate在有些情况下可能会在java代码中保存sql/hql。
- 运行效率
在不考虑cache的情况下,iBatis应该会比hibernate快一些或者很多(根据实际情况会有所不同)。
- 对不同数据库类型的支持。iBatis对不同数据库类型的支持不够好,如果你要开发的系统是要在对中数据间移植,那可能用hibernate比较好。
- 对缺省的cache支持。iBatis对缺省的cache支持不够好,但是hibernate的cache支持其实也不是很好,而且很复杂。尤其是对于大并发量的应用。所以我更倾向于自己管理cache。
- 映射的方式不同,以数据库字段一一对应映射得到的PO(persistant object)和Hibernte这种对象化映射得到的PO是截然不同的,本质区别在于这种PO是扁平化的,不像Hibernate映射的PO是可以表达立体的对象继承,聚合等等关系的,这将会直接影响到你的整个软件系统的设计思路。
Struts
创始人:Craig Mcclanahan
背景故事:
Struts最早是作为ApacheJakarta项目的组成部分,项目的创立者希望通过对该项目的研究,改进和提高JavaServer Pages 、Servlet、标签库以及面向对象的技术水准。
Struts这个名字来源于在建筑和旧式飞机中使用的支持金属架。这个框架之所以叫”Struts”,是为了提醒我们记住那些支撑我们房屋,建筑,桥梁,甚至我们踩高跷时候的基础支撑。这也是一个解释Struts在开发Web应用程序中所扮演的角色的精彩描述。当建立一个物理建筑时,建筑工程师使用支柱为建筑的每一层提供支持。同样,软件工程师使用Struts为业务应用的每一层提供支持。它的目的是为了帮助我们减少在运用MVC设计模型来开发Web应用的时间。
工作原理:
- Struts1
Struts1通过内部对象及配置文件的协同工作,以ActionServlet作为核心控制器,负责拦截用户的所有请求,完成了对页面和Action灵活控制。从而实现Model和View的分离,降低他们之间的耦合程度。
Struts 1框架有3个重要组成部分:
ActionForm必须实现ActionForm的基类(设计上并不是真正的POJO),其工作流程如下:
- 初始化:struts框架的总控制器ActionServlet是一个Servlet,它在web.xml中配置成自动启动的
Servlet,在启动时总控制器会读取配置文件(struts-config.xml)的配置信息,为struts
中不同的模块初始化相应的对象。(面向对象思想)
- 发送请求:用户提交表单或通过URL向WEB服务器提交请求,请求的数据用HTTP协议传给web服务器。
- form填充:struts的总控制器ActionServlet在用户提交请求时将数据放到对应的form对象中的成员
变量中。
- 派发请求:控制器根据配置信息对象ActionConfig将请求派发到具体的Action,对应的formBean一并
传给这个Action中的excute()方法。
- 处理业务:Action一般只包含一个excute()方法,它负责执行相应的业务逻辑(调用其它的业务模块)
完毕后返回一个ActionForward对象。服务器通过ActionForward对象进行转发工作。
- 返回响应:Action将业务处理的不同结果返回一个目标响应对象给总控制器。
- 查找响应:总控制器根据Action处理业务返回的目标响应对象,找到对应的资源对象,一般情况下
为jsp页面。
- 响应用户:目标响应对象将结果传递给资源对象,将结果展现给用户。
- Struts2
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。
一个请求在Struts2框架中的处理大概分为以下几个步骤:
1. 客户端初始化一个指向Servlet容器(例如Tomcat)的请求。
2. 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 。
v3. 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action ,FilterDispatcher是控制器的核心,就是mvc中c控制层的核心。
4. 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy 。
5. ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类 。
6. ActionProxy创建一个ActionInvocation的实例。
7. ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8. 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。
返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper 。
struts1与struts2区别:
- struts1要求Action类继承一个抽象基类,而不是接口。
struts2的action类可以实现一个action接口,也可以实现其他接口。
- struts1 的action是单例模式,线程是不安全的。
struts2 的 action线程是安全的,action为每一个请求都生成了一个实例。
- sturts1过去依赖serlet API,不容易测试。
struts2不依赖于容器,允许Action脱离容器单独被测试。
- struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。
struts2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。
- struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).
- struts1使用标准JSP机制把对象绑定到页面中来访问。
struts2 使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。
- struts1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。
struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。
- struts1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。
struts2支持通过validate方法和XWork校验框架来进行校验。
- struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。http://www.linuxso.com/architecture/7694.html
- 执行流程
struts1
jsp发起httprequest请求->servlet捕获->struts.xml->namespace+ActionName-> Action->填充表单setXxx()->action.execute()->”success”->Result->设置request属性->跳转目标页
struts2
Action(jsp发起httprequest请求,被过滤器捕获)->FilterDispatcher->struts.xml->namespace+ActionName->new Action->填充表单setXxx()->action.execute()->”success”->Result->设置request属性->跳转目标页
优点:
- 实现了MVC模式,层次结构清晰,使程序员只需关注业务逻辑的实现。
- 丰富的标签库,大大提高了开发的效率。
- Struts2提供丰富的拦截器实现。
- 通过配置文件,就可以掌握整个系统各个部分之间的关系。
- 异常处理机制,只需在配置文件中配置异常的映射,即可对异常做相应的处理。
- Struts2的可扩展性高。
Struts2的核心jar包中由一个struts-default.xml文件,在该文件中设置了一些默认的bean,resultType类型,默认拦截器栈等,所有这些默认设置,用户都可以利用配置文件更改,可以更改为自己开发的bean,resulttype等。
因此用户开发了插件的话只要很简单的配置就可以很容易的和Struts2框架融合,这实现了框架对插件的可插拔的特性。
- 面向切面编程的思想在Strut2中也有了很好的体现。
最重要的体现就是拦截器的使用,拦截器就是一个一个的小功能单位,用户可以将这些拦截器合并成一个大的拦截器,这个合成的拦截器就像单独的拦截器一样,只要将它配置到一个Action中就可以。
缺点:
- 对Action执行的控制困难。
- 对Servlet的依赖性过强。
- 测试不方便. Struts的每个 Action都同Web层耦合在一起,这样它的测试依赖于Web容器,单元
测试也很难 实现。
- 对事件支持不够
- 前端表达式语言方面.Struts集成了JSTL,所以它主要使用JSTL的表达式语言来获取数据。可是
JSTL的表达 式语言在Collection和索引属性方面处理显得很弱
- 安全性有待提高,struts2中设计存在一系列安全隐患。
SpringMVC
创始人:Rod Johnson
背景故事:
Rod Johnson在Spring中创造SpringMVC的原因是因为当时流行的MVC框架都有各种各样的缺陷.
他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。
Rod Johnson大叔告诉我们,Spring就是在“不重复发明轮子”的理念及指导原则上做起来。于是一夜之间,随着Spring在全世界的风风火火,特别是吹到我们祖国的时候,也许是爱屋及乌(或鸟)的原因吧,“轮子理论”也被众多的Spring粉丝当成做人做事做程序的信条及原则。
“轮子理论”,也即“不要重复发明轮子”,这是西方国家的一句谚语,原话是:Don’t Reinvent the Wheel。
工作原理
SpringMVC基于servlet原理实现,Spring提供了DispatcherServlet,这个类不仅负责实现请求转发,还负责启动一个WebApplicationContext容器。 按照Spring一贯的IoC哲学,所有的Controller都是JavaBean,并由IoC容器统一管理。对于View,则采取了更灵活的处理方 式,Spring MVC允许使用不同的View实现,除了JSP外,还可以使用Velocity、Freemaker、XSLT等多种View技术。
1. 客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.
2. DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。
3. DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。
4. Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。
5. Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。
6. Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端。
优点:
- SpringMVC属于spring系列产品,基于spring能与许多框架进行无缝结合。
- 轻量级MVC框架,灵活,方便,配置简单。
- 支持注解,可实现真正的0配置。
- 入门容易
缺点:
- springMVC的控制器对象的处理请求方法需要带有HttpServletRequest和HttpServletResponse参数,这样不便于调试;
- springMVC无法脱离spring框架。
Struts与SpringMVC的对比
- Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,因为Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
- 由上边原因,SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文。
- 由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
- 拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。
- SpringMVC的入口是servlet,而Struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。
- SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
- SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱。
- spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
- 设计思想上,Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。
- SpringMVC开发效率和性能高于Struts2。
- SpringMVC可以认为已经100%零配置。
Spring
创始人:Rod Johnson
背景故事:
Rod Johnson在2002年编著的《Expert one on one J2EE design and development》一书中,对Java EE 系统框架臃肿、低效、脱离现实的种种现状提出了质疑,并积极寻求探索革新之道。以此书为指导思想,他编写了interface21框架,这是一个力图冲破Java EE传统开发的困境,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和部署的轻量级开发框架。
Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。同年他又推出了一部堪称经典的力作《Expert one-on-one J2EE Development without EJB》,该书在Java世界掀起了轩然大波,不断改变着Java开发者程序设计和开发的思考方式。在该书中,作者根据自己多年丰富的实践经验,对EJB的各种笨重臃肿的结构进行了逐一的分析和否定,并分别以简洁实用的方式替换之。至此一战功成,Rod Johnson成为一个改变Java世界的大师级人物。
工作原理:
Spring即一个AOP框架,也是一IOC容器。 内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的 。
Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是 在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过 配置类达到的。
优点:
- Spring能有效地组织你的中间层对象,不管你是否选择使用了EJB。如果你仅仅使用了Struts或其他为J2EE的 API特制的framework,Spring致力于解决剩下的问题。
- Spring能消除在许多工程中常见的对Singleton的过多使用。根据我的经验,这是一个很大的问题,它降低了系统的可测试性和面向对象的程度。
- 通过一种在不同应用程序和项目间一致的方法来处理配置文件,Spring能消除各种各样自定义格式的属性文件的需要。曾经对某个类要寻找的是哪个魔法般的属性项或系统属性感到不解,为此不得不去读Javadoc甚至源编码?有了Spring,你仅仅需要看看类的JavaBean属性。Inversion of Control的使用(在下面讨论)帮助完成了这种简化。
- 通过把对接口编程而不是对类编程的代价几乎减少到没有,Spring能够促进养成好的编程习惯。
- Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
- 使用Spring构建的应用程序易于单元测试。
- Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码。
- Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适用于许多web应用。例如,Spring能使用AOP提供声明性事务管理而不通过EJB容器,如果你仅仅需要与单个数据库打交道,甚至不需要一个JTA实现。
- Spring为数据存取提供了一个一致的框架,不论是使用的是JDBC还是O/R mapping产品(如Hibernate)。
Spring确实使你能通过最简单可行的解决办法来解决你的问题。而这是有有很大价值的。
缺点:
- jsp中要写很多代码、控制器过于灵活,缺少一个公用控制器
以上主流框架看完,我们来看一些有趣的插件,不止是有趣,对我们的工作帮助非常大。
Quartz
创始人:OpenSymphony开源组织
背景故事:
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。(来自百度百科)
工作原理
Quartz中有两个基本概念:作业(Job)和触发器(Trigger)。
作业是能够调度的可执行任务,触发器提供了对作业的调度。
1. JobDetail表示一个具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略。
2. Scheduler是一个计划调度器容器(总部),容器里面可以盛放众多的JobDetail和trigger,当容器启动后,里面的每个JobDetail都会根据trigger按部就班自动去执行。
3. JobDetail是一个可执行的工作,它本身可能是有状态的。
4. Trigger代表一个调度参数的配置,什么时候去调。
5. 当JobDetail和Trigger在scheduler容器上注册后,形成了装配好的作业(JobDetail和Trigger所组成的一对儿),就可以伴随容器启动而调度执行了。
6. scheduler是个容器,容器中有一个线程池,用来并行调度执行每个作业,这样可以提高容器效率。
优点:
- 支持Cron表达式定义时间点也支持SimpleTrigger对应时间点,可以很精确的定义时间点
- 支持集群,可以在多个服务器(连同一个数据库)自动分配到不同的服务器上执行。
- 支持多种错误处理形式(如错误后下次不执行、马上重新执行、下次继续执行等)。
- 支持多种漏触发处理(如关机漏触发情况)。
- 支持动态设置触发事件。
- 方便与spring等开源框架的集成整合。
缺点:
动态化起来比较复杂。
Jackson
创始人:Tatu Saloranta
背景故事:
暂无
工作原理:
利用java反射机制,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象,转换的关键就是ObjectMapper 。
在使用ObjectMapper对象readValue或者writeValue的时候,JSON可以以字符串的形式传入,也可以以文件的形式传入,官方的例子是让将JSON保存在文件中。
明显JSON字串中的key与Java类中的field名字应该要相同,而且类如果有自定义构造函数的时候,进行JSON->对象转换会出错,Date域是以long类型输出的,有必要的话,需要进行格式转换。
优点:
- 多处理模式,且可很好协作。
- 不仅是注解,可以混合式注解!
- 完全支持泛型类型。
- 可使用任何构造及工厂方法(不只是默的零参方法)。
- 多态类型
- 支持父/子引用(一对多,ORM)。
缺点:
暂无
Freemarker
创始人:Benjamin Geer(版权归属)和Mike Bayer
背景故事:
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件,FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,没有被绑定到Servlet或HTML或任意Web相关的东西上,它也可以用于非Web应用环境中。
1999年末,FreeMarker的第一个版本出现在SourceForge网站上,它最初是由Benjamin Geer和Mike Bayer编写,他们定义了FreeMarker最基本的语法。FreeMarker 1获得了LGPL(宽通用公共许可证)的许可,其版权归属于Benjamin Geer。此外,Nicholas Cull、Holger Arendt等人对该项目也做出了主要贡献。
工作原理:
假设在一个应用系统中需要一个HTML页面如下:
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome Big Joe!</h1>
<p>Our latest product:
<a href="products/greenmouse.html">green mouse</a>!
</body>
</html>
页面中的用户名(即上面的“Big Joe”)是登录这个网页的访问者的名字, 并且最新产品的数据应该来自于数据库才能随时更新。所以,不能直接在HTML页面中输入“Big Joe”、“greenmouse”及链接, 不能使用静态HTML代码。可以使用要求输出的模板来解决,模板和静态页面是相同的,只是它会包含一些FreeMarker将它们变成动态内容的指令:
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
模板文件存放在Web服务器上,当有人来访问这个页面,FreeMarker就会介入执行,然后动态转换模板,用最新的数据内容替换模板中${…}的部分,之后将结果发送到访问者的Web浏览器中。访问者的Web浏览器就会接收到例如第一个HTML示例那样的内容(也就是没有FreeMarker指令的HTML代码),访问者也不会察觉到服务器端使用的FreeMarker。(存储在Web服务器端的模板文件是不会被修改的;替换也仅仅出现在Web服务器的响应中。)
为模板准备的数据整体被称作为数据模型。数据模型是树形结构(就像硬盘上的文件夹和文件),在视觉效果上, 数据模型可以是(这只是一个形象化显示,数据模型不是文本格式,它来自于Java对象):
(root)
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"
早期版本中,可以从数据模型中选取这些值,使用user和latestProduct.name表达式即可。类比于硬盘的树形结构,数据模型就像一个文件系统,“(root)”和latestProduct就对应着目录(文件夹),而user、url和name就是这些目录中的文件。
总体上,模板和数据模型是FreeMarker来生成输出所必须的组成部分:模板 + 数据模型 = 输出[11] 。
优点
- 可以彻底的分离表现层和业务逻辑。
曾经海浪在使用JSP 开发过程中发现在页面中大量的存在业务逻辑的代码,使得页面内容凌乱,在后期大量的修改维护过程中就变得非常困难。
FreeMarker根本不支持Java脚本代码。
FreeMarker的原理就是:模板+数据模型=输出,模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的。用户最终看到的输出是模板和数据模型合并后创建的。
- 可以提高开发效率。
根据海浪以往的开发经验,使用的都是JSP 页面来展示数据的,即所谓的表现层。大家都知道,JSP在第一次执行的时候需要转换成Servlet类,开发阶段进行功能调适时,需要频繁的修改JSP,每次修改都要编译和转换,那么试想一天中我们浪费在程序编译的时间有多少。相对于JSP来说,FreeMarker模板技术不存在编译和转换的问题,所以就不会存在上述问题。而且开发过程中,大家在不必在等待界面设计开发人员完成页面原形后,大家再来开发程序。
- 使得开发过程中的人员分工更加明确。
以往用JSP展现数据时,作为程序员的我们,并不熟悉界面设计技术,反之界面开发人员,也并不熟悉程序语言。对两者而言,交替性的工作本身就有难度。有时候稍有不慎,可能会将某个页面元素删除或去掉了某个程序符号,使得页面走样或程序错误,这样就需要双方相互沟通协作,解决出现的问题。有时候因为项目中的时间,任务量等因素的存在,可能这个工作就由一个人来完成,这样就可能加大某一方开发人员的工作量。使用FreeMarker后,作为界面开发人员,只专心创建HTML文件、图像以及Web页面的其他可视化方面,不用理会数据;而程序开发人员则专注于系统实现,负责为页面准备要显示的数据。
缺点
- 应用FreeMarker模板技术,在修改模板后,可能会看到已经过期的数据。如:生成静态的HTML页面后,如果一旦模板改变,而没有及时更新模板生成的HTML页面的话,用户看到的就是过期的数据。
- FreeMarker模板技术在应用过程中,FreeMarker中的变量必须要赋值,如果不赋值,那么就会抛出异常。想避免错误就要应用if/elseif/else 指令进行判段,如果对每一个变量都判断的话,那么则反而增加了编程的麻烦。
- FreeMarker的map限定key必须是string,其他数据类型无法操作。
- FreeMarker不支持集群应用。为了编成的方便性,把序列化的东西都放到了Session中,如Session,request等,在开发的过程中确实方便,但如果将应用放到集群中,就会出现错误。
Hessian
创始人:caucho 公司
背景故事:
Hessian 是由 caucho 提供的一个基于 binary-RPC 实现的远程通讯 library ,它是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。
工作原理:
Hessian 是基于 Binary-RPC 协议实现,通过 Hessian 本身提供的 API 来发起请求,通过Http协议进行传输,响应端根据 Hessian 提供的 API 来接收请求,Hessian 根据其私有的串行化机制来将请求信息进行反序列化,传递给使用者时已是相应的请求信息对象了。Hessian通常使用二进制传输数据,通过Web应用来提供服务,通过接口暴露。Servlet和Spring的DispatcherServlet都可以把请求转发给Hessian服务。
优点:
- 简单易用,面向接口,通过接口暴露服务,jar包只有200、300k,不需要配置防火墙。
- 效率高,复杂对象序列化速度仅次于RMI,简单对象序列化优于RMI,二进制传输。
- 多语言支持:wiki、Java、Flash/Flex、Python、C++、.NET C#、PHP、Ruby、Objective-C
可与spring集成,配置简单,HessianServiceExporte。
缺点:
- 缺乏安全机制,传输没有加密处理。
- 异常机制不完善,总是报一些错误,错误原因也是千奇百怪,提示信息不足。
- 事务处理欠缺。
- 版本问题,spring 2.5.6对照3.1.3版,spring 3对照4.0及以上版本,需要使用spring MVC 部分内容。