Struts2, Spring 和 Hibernate 的理解之我谈

6 篇文章 0 订阅
3 篇文章 0 订阅
某人提出的问题:
大家好,我是应届毕业生,我在找工作时候,面试官问我:用自己的话分别谈谈对 struts2,spring,Hibernate的理解,我应该怎么说啊?求高人指点。(不要那些官方语言)


我的回答:
Struts2 是基于 Filter 进行跳转控制的工具,封装了从不同请求路径到不同程序的分发过程。我个人觉得这种分发应该根据系统的预期复杂程度来决定是否使用。毕竟,基于反射的框架工具,都会带来执行速度的缓慢。这意味着同样规模的用户,服务器需要消耗 避免反射型框架 十倍以上的内存。
  对于页面跳转,我个人认为应该将软件结构设计成网络传输与数据功能分开的模式。这种模式意味着,同一种网络请求,就对应某一个程序程序。由这些和访问直接对应的程序方法来进行各种功能的组合调用。这么做是因为,在实际系统中,这种组合而来的功能流程,对于一个系统来说,是几乎不会临时改变的。就算能够改变,也不方便通过让实施人员调整配置文件来达成这种变化。
  另外,如果网络和客户端(运行 JavaScript 的浏览器本身也可以理解为一种客户端)的数据交互,如果能够提纯,也就能在一定程度上解决对复杂跳转控制的依赖,从而不使用 Struts 及类似产品。具体 单页面应用 的有关内容,有机会再说吧。

Spring 主要的功能是对象依赖关系的注入,以及方法执行前、后的监视(切片)。在实现途径上,通过 Spring 执行的每一个方法,都不是直接执行,而是通过代理程序的方式。这严重损害了服务器性能。
  还是刚才的观点,我认为软件结构的设计,可以避免很多系统曾经出现的问题,比如依赖层次过多造成人工控制困难,等。
  通过 Spring 进行切片是一个具备很高开发效率的方式。不过因为性能严重低下,所以内网系统可以考虑。公网系统,则应该通过可配置的模块化功能执行流程,来避免代码重复编写。

Hibernate 是对象-关系转换工具,并且能够在软件层面实现 分布式事务 。不过就像 Spring 一样,其性能也完全无法得到保证。我之前没有研究过分布式事务如何实现。不过考虑到数据安全问题,现实中数据库一般并不会向外网透露。这造成了分布式事务在绝大多数项目中缺乏实用意义。对象-关系转换,其实也是因为 Java 对于数据处理的僵死,不像现在新语种那样能够轻松往已经存在的对象中添加属性。
  可以考虑自定义基于 Map 的数据结构,以简便地和关系型数据库进行对应。这样能够很大程度摆脱对对象-关系转换工具的依赖。


后来此篇日志在 ITeye 论坛引起了一些关注和讨论,我把主要内容补充部分有代表性的在下边。  2012-11-5 Monday
---------- ---------- ---------- ----------
ansjsun 说:楼主对反射有偏见呵呵..其实问这个问题的人就有点脑残..不过你能说出自己的理解就很好了..我以前也常问..一般面试的人都给我背了一遍...我感觉你挺有想法的...不过性能问题..得做测试在说话....哪个反射性能低下..实际上..在多次预热的时候..性能不一定会差...从你的回答..能看出你理论上比较强..换句话说就是..过度自信...这不是什么好事....除非测试过..否则别把话说死了...其他的没了.....
我曾经是多么坚定的反射拥护者啊,也会因为每一大版 JavaDevelopmentKit 发布,其中提到反射执行速度又提高了 50% 而兴奋。问题是经过实际测试,这速度真是差别太大了……
  我刚才翻了一下自己的帖子。最近百度正在转型,我以前的日志数据丢失了。所以拿不到截图和准确数字。但实际的执行速率是这样的:
1、直接访问属性。假设某个属性访问速度是 1 毫秒,那么通过反射(Java6.0)访问速度就是 200+ 毫秒,应该是能稳定在 260-290 之间,通过 Spring 来 get 在 1000 毫秒以上,2000 毫秒以下。
2、方法执行。如果不涉及 final 参数,则有参数方法直接执行速度为 1 毫秒,通过反射访问速度就是 600-800 毫秒,通过 Spring 来获取方法值在 1000 毫秒以上 2000 毫秒以下。
那个时候具体的测试方法,是在同等条件下,长时间多次执行某一个方法的调用。时间长度大概在 0.5-20 秒(基数)左右。然后切换成反射调用,测时间;再切换成 Spring 获取值,求时间。
  数据收集,是通过浏览器启动某方法,然后后台 System.out.println 输出的 Calendar.getInstance 时间。
我明白,不应该说空话的。在这之前,大概是 2、3 年前,我刚设计过一个用 Spring3 的产品,那个时候大家主要还在用 Spring2 ,现学的标注声明,觉得这个理念很先进。可在知道这种性能问题之后,我就觉得基于运行时反射的执行框架,只应该应用于内网应用,或者服务器硬件充足型应用。
  以上我的回答,是指我觉得 Struts 再使用标注,也是基于反射的,就避免不开性能上边的问题。当然了,如果今后ta做了大规模的缓存,将反射结果全都缓存了,那么执行速度就能大幅度提升;但相应的就是内存消耗问题。
  我现在用自己改的一版 Tomcat(基于7.0.22),弱联网游戏一台服务器可以带 10000+ 的同时在线用户。而我们这边有一个最近才投资的小游戏公司,做网络游戏,用 Java Play ,开发速度是非常快,但是一台服务器只能容 1000 同时在线用户。服务器成本对于内网应用来说是小头,但是对于公网应用来说,是一个很不得了的支出,必须得考虑节省啊……用框架和用这种速成中间件,有一些类似的。
  性能,这东西真不是扯淡。部分内容请参看上边的回复。因为做互联网应用,服务器成本是很大的开销,所以真是不能不考虑。这和内网应用/服务器密集的应用不一样。我以前给城市政府做项目,那当然是 Oracle ,架构也好分,数据的处理逻辑全放存储过程;服务端也可以用 Spring3 。但是做一个网络游戏服务器产品,那真不敢这么弄。这么弄的后果就是小规模的 CP(内容提供商),完全无法基于这样的产品做他们的网游。因为小规模几台服务器,受不了经过推广一瞬间暴增的那种低质量用户。
---------- ---------- ---------- ----------
Matol 说:有自己的想法和理解很好,但是,对于有些东西的看法太过于偏激了。
这么说来,好像是,我是有些偏激了。一方面是因为第四页我的诸多回复中提到的互联网应用对服务器成本的控制。另一方面我仔细想了想,可能也是因为这么些年我的算法技能一直没有机会使用,所以总会不自觉地就希望能给自己营造出一个算法有用,算法能够带来时效的氛围。
  在这种不自觉的自我影响中,我就越来越觉得性能问题很严重。那些动辄几百倍执行速度的都是真实数据。但我现在想,如果足够理智的话,应该仔细核算使用低效框架的服务器成本增值,和不使用框架的开发成本增值,谁更大。我以前考虑到这个问题的时候,就自己给自己应付过去了,一直没有仔细想过。
  唉,我的理想啊……
  我才做完了一个公式解析的开源小项目,本来正准备做一个内存数据中心(高可用)的开源项目,来解决我这边网络游戏排名能够实现即时排名而不像绝大多数网友得定期刷新的问题。现在看来要仔细核算一下用 MemoryCache 还是自己开发了……
  虽然很沮丧,不过,还是谢谢您……
---------- ---------- ---------- ----------
84707227 说:面试官只是问你对SSH的理解,不是总结SSH的不足。试问一下,SSH有那么多缺点,很多公司(至少中国的很多公司)都在用,怎么解释?
  SSH 缺点并不一样,我只提到了一个共同的缺点,就是执行速度低。
  那么,这个问题什么时候才严重呢?就是执行速度对整个系统比较重要的时候。
  对于服务器运算资源冗余的应用场景,框架还是低速,但不会影响到系统执行结果。那就无所谓。如果服务器运算资源紧张,集群规模比较小但用户数量很大,那就是不该使用。
  当然,很多公司即便是运算资源紧张,依然使用大量的框架,这有几个原因。
1、爪哇(Java)开发人员过分熟悉使用框架,以至于很多人,嗯,绝大多数爪哇(Java)从业者没有能力脱离框架编写大规模应用。
2、研发耗时。互联网应用国内的行情(我怀疑国际上也是),目前都注重快出产品。这目的是利用创意抢用户。所以研发耗时低,就算可能得不偿失,可能服务器硬件成本会变得极高,只要用户体验别太差,最终就会用这种速成方案。当然,这也就造就了技术积累缓慢。
3、理念都是在不断更新的。比如早年认为用文本文件配置就是灵活的,后来认为用标注标明就已经灵活了,到现在认为“约定优于明示”才是更有效的。说实话,SSH 作为成熟框架,都已经有些显露出落后的疲态了。关于这个,可以关注一下 Python 这门语言。然而,程序员们,技术更新是能够很快,但理念更新并不是那么容易的,得多否定自己。这个,大家都做不够好。
4、公司的项目是长久以来继承下来的,谁也承担不起重构的风险。也不觉得重构是一个意义很大的事情。当然了,其实很可能会回归第 1 点,也就是就算重构还是会选用框架,顶多就是找找谁相对更好用。这是爪哇(Java)程序员的开发模式。
---------- ---------- ---------- ----------
cbbaaa1989 说:汇编的性能比java 好太多了,你为什么不用汇编
  说实话,我是考虑过汇编的。但不用汇编的理由有二个
1、我不会。这是实情。而且掌趣科技这边一个会的也没有……   T T    我以前约了一个测试的朋友一起学,但是因为各自工作繁忙,以及异地,都没有学成。吐槽一下我的毅力……太差了。
2、服务器硬件 CPU 的问题。因为现在硬件不归我自己的部门负责,受到一些因素影响,造成拿到的服务器完全无法统一规格,也无法保证支持的指令集一致。无法用汇编写通用的本地方法。
  在之前,我会用 C 语言做一些最核心的方法,生成 .dll ,映射成 native 方法来使用。
但是在掌趣科技这边,我在推广全部服务器 虚拟化 ,而且不准备使用 Windows 服务器,全部用了当时新版的 CentOS 6.1 。而我又不知道 Linux C 怎么和 Java 绑定。所以这边的事情也放下来了。
  其实 Java 的执行效率是非常高的。如果你愿意来我的日志看看,前几篇有一个是我为字符串处理写了几个比系统类库快很多倍的方法。但是这种个位数倍数的速度差,都是小事情。本帖第四页回复,我写了之前对反射的性能测试数据。动辄几百倍啊……如果需要服务器性能,这还是应该避免一些的。
  不使用传统三大框架,这不是想当然,虽然可能有我想做算法的因素含在里边。但至少并不是一个太不理智的选择。
   1. struts是一个按MVC模式设计的Web层框架,其实它就是一个大大的servlet,这个Servlet名为ActionServlet,或是ActionServlet的子类。我们可以在web.xml文件中将符合某种特征的所有请求交给这个Servlet处理,这个Servlet再参照一个配置文件(通常为/WEB-INF/struts-config.xml)将各个请求分别分配给不同的action去处理。    一个扩展知识点:struts的配置文件可以有多个,可以按模块配置各自的配置文件,这样可以防止配置文件的过度膨胀;    2. ActionServlet把请求交给action去处理之前,会将请求参数封装成一个formbean对象(就是一个java类,这个类中的每个属性对应一个请求参数),封装成一个什么样的formbean对象呢?看配置文件。    3.要说明的是, ActionServlet把formbean对象传递给action的execute方法之前,可能会调用formbean的validate方法进行校验,只有校验通过后才将这个formbean对象传递给action的execute方法,否则,它将返回一个错误页面,这个错误页面由input属性指定,(看配置文件)作者为什么将这里命名为input属性,而不是error属性,我们后面结合实际的运行效果进行分析。    4.action执行完后要返回显示的结果视图,这个结果视图是用一个ActionForward对象来表示的,actionforward对象通过struts-config.xml配置文件中的配置关联到某个jsp页面,因为程序中使用的是在struts-config.xml配置文件为jsp页面设置的逻辑名,这样可以实现action程序代码与返回的jsp页面名称的解耦。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值