New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架? #8

Open
RubyLouvre opened this Issue Apr 30, 2015 · 18 comments

Comments

Projects
None yet
@RubyLouvre
Owner

RubyLouvre commented Apr 30, 2015

今年我一直在思考web开发里的前后端分离的问题,到了现在也颇有点心得了,随着这个问题的深入,再加以现在公司很多web项目的控制层的技术框架由struts2迁移到springMVC,我突然有了一个新的疑问无法得到正确的解释,为什么我们现在做java的web开发,会选择struts2或者springMVC这样的框架,而不是使用servlet加jsp这样的技术呢?特别是现在我们web的前端页面都是使用velocity这样的模板语言进行开发,抛弃了jsp,这样的选择又会给我们java的web开发带来什么样的好处,延着这个问题的思路,我又发现新的疑问,为什么现在很多java企业级开发都会去选择spring框架,spring框架给我们开发的应用带来了什么?这么一想还真是问倒我了,我似乎很难找到一串能让人完全信服的答案,最终我发现,这些我认为我很熟悉很常用的技术,其实还有很多让我陌生不解的地方,这些陌生和不解的地方也正是我是否能更高层次使用它们的关键,今天这篇文章我就来讲讲这些问题,不过struts2,spring这样的技术经过这么多年的积累已经是相当庞大和复杂,它们的面很广,本人虽然已经用了它们多年,还是有很多技术不熟悉和不清楚,所以本文不是全面对我题目做出解答的文章,而是根据我现有知识结构来理解这个问题。

软件里有很多优秀的框架,有一种类型的框架,它的特点是建立在一个现有技术的基础上,提供和现有技术一样业务功能的技术框架,这个新的技术框架比原技术更加易用,更加健壮同时功能更加强大,例如:jQuery,以及本文所要谈到的struts2和springMVC,深究这些框架都是相当之复杂,但是它们的优点其实只有一个:就是让使用者只关心核心业务的开发,框架帮你屏蔽原有技术跟业务开发无关的各类技术问题。像jQuery,struts2或springMVC这类框架之所以优秀,就是它们在这点上做的太好了,以至于很多使用它的程序员都已经不清楚原有技术的真实面目,因此我们要将struts2理解的更好,使用的更加熟练和深入,这里我们就要跳出struts2的技术,到struts2技术的源头servlet,仔细研究下servlet的特点,只有这样我们才能把struts2框架学的更好。

Servlet的作用是接收浏览器传给服务端的请求(request),并将服务端处理完的响应(response)返回给用户的浏览器,浏览器和服务端之间通过http协议进行沟通,其过程是浏览器根据用户的选择将相关信息按http协议报文的规范组装请求的http报文,报文通过网络传输到指定的服务器,服务器通过特定的web容器接收这个报文信息,例如:tomcat,jetty,jboss这样的web容器,web容器会将http报文解析出来,如果是用户请求,最终解析出来的报文信息会用一个request对象存储起来,服务端使用这个request做完相应的处理后,服务端程序将结果信息封装到response对象里,然后将response对象交给web容器,web容器则把这个response对象转变为http协议的报文,并将报文回传给浏览器,浏览器最后解析这个响应报文,将最终结果展示给用户。

Web容器创造了servlet接口,servlet接口就是开发人员自己实现业务逻辑的地方,程序员开发servlet就好比做填空题,而填空题的语境或者说上下文提示就是由request和response对象,但是javaEE规范里的servlet接口很简单,就三个方法init,service和destory,但是这个接口太笼统,所以规范里还提供了一个HttpServlet类,这个类根据http请求类型提供了doGet,doPost等方法,servlet接口最大的特点就是根据http协议的特点进行定义,因此做servlet开发时候如果使用者对http协议特点不是特别熟悉,都会碰到或多或少令人迷惑的问题,特别是碰到一些复杂特殊的请求时候:例如文件上传,返回特殊的文件格式到浏览器,这时候使用servlet开发就不是很方便了,servlet开发还有个问题可能大家常常被忽视,就是请求的数据的类型转化,http协议传输都是文本形式,到了web容器解析后也是文本类型,如果碰到货币,数字,日期这样的类型需要我们根据实际情况进行转化,如果页面传送的信息非常多,我们就不得不做大量类型转化,这种工作没有什么技术含量,是个体力活而且很容易导致程序错误。同时java的企业开发都是围绕javabean进行,类型转化好的数据还要封装到对应的javabean里,这种转来转去的事情对于项目开发绝对不是什么好事情,所以古老的struts1为这种问题找到了一种解决方案,就是定义了一个DTO对象(数据传输对象),专门负责做这样的事情,不过到了struts2,整个替代servlet的action本身就是一个javabean。

Java的企业开发一个技术特点就是使用javabean进行的,struts2的特点之一就是它替代servlet的操作类就是一个典型的javabean,首先struts2框架将页面传输的数据进行类型转化和封装后将请求信息封装到了这个javabean的属性里,这样我们开发web程序时候就省去了烦心的类型转化和封装的问题,前面我讲到传统的servlet是根据http协议进行定义的,它会按你请求方式(post还是get方式)来处理用户的请求,但是对于一名程序开发人员而言,一个请求,具体到一个url,其实对于服务端而言就是服务端对外提供的一个功能,或者说是服务端对外的一个动作,如果我们使用servlet开发程序我们就得把http的动作转化为具体的业务动作,这就让程序开发变得繁琐,增强了开发的难度,所以struts2替代servlet的javabean就屏蔽了servlet里http的请求方式和具体业务动作转化的问题,javabean里的每一个方法都可以和每一个url请求一一对应,这必然减轻了开发的难度问题。

Servlet另一个作用就是构造response对象,让页面获得正确的响应,其实现代的浏览器是一个多媒体工具,文字,图片,视屏等等东西都可以在浏览器里显示,资源的不同就会导致http响应报文的差别,如果我们使用servlet开发就要根据资源的不同在java程序里用硬编码的形式处理,这样的程序很难复用,而且如果程序员对某种资源的处理理解不到位,就会导致问题的出现,struts2通过配置文件的形式将这样的逻辑从java程序里剥离出来,使用配置的方式进行统一管理,这个做法和spring的AOP方式类似,这样就让结果处理方式更加统一,更加利于管理,同时也提升了程序的健壮性以及降低了开发的难度。

Servlet在MVC开发模式里就是其中C层即控制层,控制层就像俄罗斯的双头鹰(一个头向东看一个头向西看)一样,一个头向M层模型层看,一个头向V层视图层看,模型层也是用java编写的,控制层也属于服务端语言开发,所以M层和C层的沟通没有天然的障碍,但是和V层视图层就不一样了,这是一个跨语言的沟通,对于浏览器,它只懂得html,javascript和css,浏览器是理解不了java这种语言的东西,但是要让服务端的东西能被浏览器理解接受,我们就必须得把服务端的响应信息放到页面里,因此就需要一个技术把java的信息转化到html页面里,这就是javaEE规范里提供了jsp技术,jsp其实是一种服务端技术而非客户端技术,不过它看起来似乎更像html技术,最早的jsp开发里都是直接将java代码写到页面里,这种坏处谁都知道,之后javaEE规范提供了自定义标签技术,使用一种类似html标签的方式来解析java代码,struts2框架提供了一整套完整的自定义标签技术,这似乎听起来不算啥,但是它的作用非凡,因为自定义标签之所以叫自定义就是每个人都可以自己来定义,如果没有一个规范必然产生混乱,而且一套完善的自定义标签是个系统工程,一套完整的自定义标签相当于我们在自己定义一套新的开发语言,做程序的人听到这个一定就会明白开发一套完整的自定义标签的工作量和开发难度都是难以想象的,而且自定义标签都是和控制层紧密相连,其难度又会增加一个维度,所以struts2提供的自定义标签对于业务开发带来的将是质的飞越。

Servlet里还有两个重要的技术:监听器和过滤器,对于监听器在web开发里使用的场景比较少,都是一些十分特别的情况才会使用,大部分web开发里可以忽略它的使用,我们用的最多的监听器可能就是对ServletContext创建和销毁的监听器,ServletContext是整个web应用的全局对象,它和Web应用的生命周期绑定在一起,因此使用这个监听器对Web应用的全局信息进行初始化和销毁操作,例如spring容器的初始化操作。比较有意思的是过滤器,在struts2里有个拦截器,它们的作用相同都是用来拦截请求的,因为拦截器是struts2的特有功能,在struts2里使用拦截器自然比使用过滤器更顺手,其实拦截器所用的技术比过滤器更加先进,因为拦截器使用了反射技术,因此拦截器拦截的面更大,控制请求的能力更强,它能完成的任务也会更加的丰富多彩。

在我第一次接触struts2时候,有人告诉我struts设计的一个目的就是想屏蔽在控制层里操作request和response对象,因为这两个http协议的儿子会造成web开发里思路的混乱,但是我在实际开发里却经常不自觉的使用这两个对象。而且本人做前端开发非常喜欢使用ajax,使用ajax技术时候我就很讨厌struts2的自定义标签,我更加喜欢在页面里用javascript技术处理各种信息,最终struts2在我眼里就是一个servlet的变体,因此曾经有段时间我常常在想是不是可以抛弃struts2,直接用servlet,因为struts2里用到了太多反射机制,特别是使用注解做配置(注解是用反射实现的),在java里反射的执行效率是非常低的,直接使用servlet一定能提升web应用的执行效率。其实这个倒很难做到,因为当时我没法在servlet里灵活的运用spring技术。

下面我要谈谈spring了。

spring技术可以说是java企业开发里最重要的技术,不过真的理解spring的作用和意义还真是一件麻烦的事情,很多人对spring理解其实都是停留在使用阶段(例如:声明式事务很好用等等),当今的spring技术生态环境里可谓是蔚为壮观,spring已经包罗万象,它的内容之多完全不亚于它的本源java语言了,而spring这么大的框都是建立在ioc和aop技术之上,只有深入理解了这两个技术我们才能明白为什么spring这个框能装的下那么多东西了。

首先是ioc,ioc技术第一个解释叫做控制反转,它还有个解释就是依赖注入,这两个名字很难从字面理解,但是当你理解它的原理后就会发现它们的描述是何等准确。Ioc技术的本质就是构建对象的技术换句话说就是将一个类实例化成对象的技术,在java里实例化类通过new关键字进行的,每次new一个类都会产生一个新的实例对象,这么做视乎很浪费,有时这种浪费还挺危险,因为在程序开发时候我们常常只需要某个类永远只能产生一个的实例对象这个时候就得使用单例模式,此外在设计模式里还可以通过工厂方式产生对象,使用过spring的人看到上面的文字就知道了,spring里bean的定义就和上面的内容一一对应,scope属性single产生单例对象,prototype产生新对象,bean还可以通过工厂方式产生对象,可以说spring的bean就是制造对象的工具。面向对象编程里对象相当于显示生活中的一个实体,例如我们有个对象作用是完成打猎的操作,那么打猎这个对象内部包含两个辅助对象:人和枪,只有人和枪赋予了打猎这个对象,那么打猎对象才能完成打猎的操作,但是构建一个人和枪的对象并不是看起来那么简单,这里以枪为例,要创造一把枪我们需要金属,需要机床,需要子弹,而机床和子弹又是两个新对象,这些对象一个个相互嵌套相互关联,大伙试想下如果我们在java代码里构建一个枪的对象那是何其的复杂,假如我们要构造的不是简单的枪对象而是更加复杂的航空母舰,那么构造这个对象的成本之高是让人难以想象的,怎么来消除这种对象相互嵌套相互依赖的关系了?spring提供了一种方式,这种方式就是spring提供一个容器,我们在xml文件里定义各个对象的依赖关系,由容器完成对象的构建,当我们java代码里需要使用某个实例的时候就可以从容器里获取,那么对象的构建操作就被spring容器接管,所以它被称为控制反转,控制反转的意思就是本来属于java程序里构建对象的功能交由容器接管,依赖注入就是当程序要使用某个对象时候,容器会把它注入到程序里,这就叫做依赖注入。在java开发里我们想使用某个类提供的功能,有两种方式,一种就是构造一个新的类,新的类继承该类,另一种方式则是将某个类定义在新类里,那么两个类之间就建立一种关联关系,spring的ioc容器就是实现了这种关联关系(记住不是继承关系哦),那么某个类要被赋予到新类有哪些办法了?一般只有两种:一种就是通过构造函数,一种就是通过setXXX方式,这也是spring容器使用到了两种标准的注入方式。

不管是上面说的继承方式,还是关联方式其实都是增强目标对象能力的开发手段,在设计模式里有一种代理模式,代理模式将继承模式和关联模式结合在一起使用,代理模式就是继承模式和关联模式的综合体,不过这个综合体的作用倒不是解决对象注入的问题,而是为具体操作对象找到一个保姆或者是秘书,这就和小说里的二号首长一样,这个二号首长对外代表了具体的实例对象,实例对象的入口和出口都是通过这个二号首长,因为具体的实例对象是一号首长,一号首长是要干大事的,所以一些事务性,重复性的工作例如泡茶,安排车子,这样的工作是不用劳烦一号首长的大驾,而是二号首长帮忙解决的,这就是aop的思想,aop解决程序开发里事务性,和核心业务无关的问题,但这些问题对于业务场景的实现是很有必要的,在实际开发里aop也是节省代码的一种方式。

Spring的核心技术的作用本质就是一个 沟通机制,spring总是尽全力的让沟通的双方信息畅通,同时降低双方的沟通成本,在现实机构里一个善于沟通的人肯定是该公司的领导,很会沟通的领导能调动起各种资源的积极性,善于沟通的领导就会做到海纳百川,让各种不同人追随他,所以当今的spring就是一个大框,什么都可以往里装。

Spring很像银行,它不能直接创造物质财富,但是一切资源都要通过它进行流通,它能控制经济发展的走向,回到程序的世界,spring的作用是被标榜为程序之间的解耦,spring能降低不同模块之间的耦合度,原因就是在程序开发里不同模块之间信息的沟通是通过对象传递完成的,而对象能否顺利传递就是要合理的构建好对象,而管理好对象的构建方式就能管理好对象传递,这就是spring给系统架构设计带来的好处。

@Lihuanghe

This comment has been minimized.

Show comment
Hide comment
@Lihuanghe

Lihuanghe May 4, 2015

前端大牛能对后端理解如此,实在是太牛啦。
ioc和aop是编程思想,放到前端,后端都是一样的。随着前端承担越来越多的业务,必然对ioc和aop有需要,但是究竟这个需要会到哪种程度这很难说。也许会有前端的ioc,Aop框架发展起来。
我补充一些:

tomcat容器帮我们解决了从http字符流到HttpServletRequest对象的创建,随后交给servlet处理。随着servlet承载越来越多,越来越复杂的业务,一个doGet,doPost方法,两个request,response对象已远远不能满足需求了。

struts2,springMVC这些框架为此提供了解决方案:把HttpServletRequest 与JavaBean的一个method建立关系。根据HttpServletRequest 创建对应的JavaBean,生成方法参数对象,同时调用对应的method方法,接收method返回值,最后根据返回值创建HttpServletresponse对象交给容器。

框架做了这么多,只有一个目的:程序员只需要关心method方法怎么写(后端的mvc还要处理业务逻辑,数据持久化这些问题)。

以上这些是OOP,IOC,AOP协作一致来降低业务复杂度(解耦)。

话说回来。如果没有这么高的复杂度,如果不是servlet要承担越来越多的业务,鬼才会搞一个这么复杂的框架呢。

我觉得这是值得前端借鉴的,如果不是ajax流行,不是js性能的大幅提升,不是前端业务越来越复杂。我想也用不到backbone, avalon这些框架,简单的jsp页面或者velocity模版就能搞定了。
avalon可能也要融入一些aop的思想。

前端大牛能对后端理解如此,实在是太牛啦。
ioc和aop是编程思想,放到前端,后端都是一样的。随着前端承担越来越多的业务,必然对ioc和aop有需要,但是究竟这个需要会到哪种程度这很难说。也许会有前端的ioc,Aop框架发展起来。
我补充一些:

tomcat容器帮我们解决了从http字符流到HttpServletRequest对象的创建,随后交给servlet处理。随着servlet承载越来越多,越来越复杂的业务,一个doGet,doPost方法,两个request,response对象已远远不能满足需求了。

struts2,springMVC这些框架为此提供了解决方案:把HttpServletRequest 与JavaBean的一个method建立关系。根据HttpServletRequest 创建对应的JavaBean,生成方法参数对象,同时调用对应的method方法,接收method返回值,最后根据返回值创建HttpServletresponse对象交给容器。

框架做了这么多,只有一个目的:程序员只需要关心method方法怎么写(后端的mvc还要处理业务逻辑,数据持久化这些问题)。

以上这些是OOP,IOC,AOP协作一致来降低业务复杂度(解耦)。

话说回来。如果没有这么高的复杂度,如果不是servlet要承担越来越多的业务,鬼才会搞一个这么复杂的框架呢。

我觉得这是值得前端借鉴的,如果不是ajax流行,不是js性能的大幅提升,不是前端业务越来越复杂。我想也用不到backbone, avalon这些框架,简单的jsp页面或者velocity模版就能搞定了。
avalon可能也要融入一些aop的思想。

@Lihuanghe

This comment has been minimized.

Show comment
Hide comment
@Lihuanghe

Lihuanghe May 4, 2015

我觉得前后端分离最大的问题在于,前后开端开发人员的知识结构差异大,思维方式也有很大差别。
体现在代码上,前后端的接口就是前端设计的api后端不好实现,后端给的api前端不好用。另外就是前后端的数据结构差异。“定接口”,“改接口”是前后分离后最常遇见的问题。 现在node大行其道,淘宝不是用node搞一个前后分离的框架,让前端人员来编写部分后端代码来解决 “接口”的问题。以前是后端人员兼写前端代码,淘宝这个框架是让前端人中兼写后端代码。是否存在一个中间状态呢?
如何让前后端的开发人中用同一种思维来设计api,如何解决前后端数据结构对应是值得讨论的。

我觉得前后端分离最大的问题在于,前后开端开发人员的知识结构差异大,思维方式也有很大差别。
体现在代码上,前后端的接口就是前端设计的api后端不好实现,后端给的api前端不好用。另外就是前后端的数据结构差异。“定接口”,“改接口”是前后分离后最常遇见的问题。 现在node大行其道,淘宝不是用node搞一个前后分离的框架,让前端人员来编写部分后端代码来解决 “接口”的问题。以前是后端人员兼写前端代码,淘宝这个框架是让前端人中兼写后端代码。是否存在一个中间状态呢?
如何让前后端的开发人中用同一种思维来设计api,如何解决前后端数据结构对应是值得讨论的。

@RubyLouvre

This comment has been minimized.

Show comment
Hide comment
@RubyLouvre

RubyLouvre May 7, 2015

Owner

如何挑选适合的前端框架

最近几年,前端技术迅猛发展,差不多每年都会冒出一款主流的框架。 每次新开业务线或启动新项目时,是第一件事就是纠结:使用什么框架,重造什么轮子?我很高兴应CSDN的邀请谈我的看法。

在五六年,移动端还没有兴起,我们没有什么选择,就是jQuery。有人会说,jQuery只是类库,不是框架;但那时前端业务还没有像今天这么繁重,原本是后端干的事,全部挪到前端来,因为光是jQuery就可以包打天下。jQuery不够用,还有成千上万的jQuery的插件呢。于是问题就是这样一一衍生出来了,一个页面太多jQuery插件了,请求数太多了,于是我们得打包。打包需要我们对插件有规划。于是这需求在社区上逐渐形成了某些规则,其中最出名的是AMD规范,体现上requirejs这个加载库上。

requirejs是前端技术发展上的一个分水岭。javascript在es6之前一直没有自己的加载机制,requirejs的出现意味着前端可以向更大规模发展。以后我说的技术选型,一个非常重要的甄选点, 就是 是否存在加载器机制或符合某个模块规范。

qq 20150508110531

回到原来的话题,选择框架要从两面看,一是看该框架的本领,二是看你们团队的能耐。

从框架的角度来看, 它的功能丰富不丰富,社区活跃度如何,国内社区活跃度如何(有的在国外流行,但国内只有初创公司或一些大公司的边缘项目在试水),文档齐全吗,及时更新吗,测试覆盖率如何,上手难度如何,都是我们考量点。不过能进我们视野内的外国框架,基本是身经百战,在造轮子兴盛的世界闯出来的领头羊。jQuery, angular, knockout, emberjs, polymer, react, backbone, zepto,我们基本是围绕在这几个上面转了。当然还有更大型的东西, EXT, YUI, dojo, easyui, bootstrap, 这是UI库层面的。

下面是2012年外国对当时流行12个javascript MVC框架的纯技术评估:
20120523084951_253

显然,我们第一步就是圈定时下最流行的框架与库,作为评估对象,然后再根据自家公司的情况进行筛选。贵公司是建站公司,还是有自己产品的公司呢?如果是建站公司,页面不会复杂到哪里去,基本上jQuery+bootstrap 搞定,不要想得太多,就是它们。如果有自己产品, 要维护一大堆客户数据要与客户打交道,不难想象是存在非常复杂的CRM系统,按照中国人的特性,这东西只会越来越复杂,这就要慎重考虑了。这往往是持续十年的维护升级,我们需要看一下这框架是否有你们的产品那么长寿,这框架的升级更新是否频繁平缓。

如果你的项目是一个跨度三年以上的大工程,用《人月神话》的术语来说,90%就是个焦油坑。我们需要使用更稳键成熟的技术方案,我们需要重点避开谷歌的产品,它的许多产品都是玩票性质, GWT、Closure、Darty就是前车之鉴。polymer是基于许多新技术构建(http://www.csdn.net/article/2013-05-27/2815450-google-polymer),其中Object。observe(), Custom Elements, HTML Imports,Shadow DOM, Model-Driven Views是远远没被标准化, 许多还是独家的, 变数太大,因此才出现如下的悲剧 http://weibo.com/1712131295/CfB7X336J?type=comment#_rnd1430880258836。 angular不是我黑它, 这东西也喜欢断崖式升级, 它在1.08时兼容IE6-8, 1.2时需要打补丁兼容旧式IE, 1.3摒弃对旧式IE的兼容,直接在源码中删除所有兼容代码,因此所有补丁方案都无力回天,并且不支持全局Ctrl函数,许多模块需要独立引用,1.4不向下支持动画模块, 2.0由at改成ts构建,由于使用Object.observe,因此不支持IE6-11,chrome30-……

requirejs

如果你们的产品是后台系统,那么就有两个选择,使用EXT, easyui这些重大的UI库方案,其中EXT具有严重的排它性,它很难与其他前端解决方案并用。什么模块组织,打包,数据可视化,它都已经全部帮你搞定。它文档齐备漂亮, 入门难度中等, 但它要求你的团队非常稳定,现在招一个专职EXT的前端是很难的。easyui是国内比较大牌的UI框架,虽然闭源,不过想扩展它不是难事。此外,国内的淘宝kissy, 网易nej也不错。还有更轻量的方案,MVVM。MVVM最擅长做这些重交互的产品。举例说,为了对应复杂交互的gird,jquery社区开发出各种庞大巨物 datagrid, jqgrid, flexigrid,还不如MVVM几个循环绑定来个干脆利落,扩展性又好。目前,knockout, emberjs, angular与我写的avalon就是这一类框架。angular虽然有点坑,但如果你是从1.3用起,并且不鸟IE,它还是一个不错的选择,其活跃的社区为它带来无限的可能。knockout在。net人群中非常流行,微软出品,前端MVVM框架的鼻祖,不过它需要对后端数据进行过多的加工,因为它本身是不支持对套嵌对象的绑定。emberjs没有一个好干爹,但有一个好亲爹,作者Yehuda Katz是jQuery, rails, Sproutecore, Merb, Handlebars这些著名框架的核心成员, 虎父无犬子,emberjs现在还是国外的第二大MVVM框架。avalon是比较适合国情的MVVM,有它专门兼容IE6的版本,易上手,性能高,视频教程多,出了问题可以抓得着作者,是它的几大卖点。

如果你们的产品是商场这样重演示类的产品,就对SEO有要求,MVVM就不适合了。目前也就angular与avalon在搞后端渲染机制,但还不上了台面。这时jQuery+bootstrap+requirejs就非常好用。requirejs的作用不单单是提供了一个按需加载机制,它还能让我们组织起更为庞大的代码。如果不用requirejs,国内另一个选择是seajs,它的规范是CMD。此外还有commonjs规范, 但这无法直接运行于前端,需要借助fekit, fis, webpack这样的构建工具进行合并了。不管怎么说,你这时选用的框架必须存在AMD,CMD或commonjs任一种加载规范,这方便你以后的横向扩展。至于插件,目前小插件们都趋向用UMD( https://github.com/umdjs/umd ),它可以让AMD,CMD,commonjs任一种加载器加载。

如果你们的产品是移动端,基本上是SPA架构了,因为这会减少等待,整页刷新与请求数。目前该领域非常混乱了,不同于PC端,这要兼容的浏览器是多出N倍,并且为了性能,浏览器商乱砍功能或改变一些浏览器特性的行为,这往往引发一些奇怪的BUG,目前社区正在整理这些坑与解药( https://github.com/jtyjty99999/mobileTech )。但目前没有一个框架能够摆平所有问题,都需要多管齐下。我的见解是

requirejs(按需加载,移动端上可以不打包,善用304缓存,腾讯搞出一个更牛叉的增量更新加载器MT,也可以试试) + backbone(组织代码与路由管理) + zepto(轻量DOM操作) + fastclick.js(点击穿透与延迟处理) + hammer.js(各种触屏事件) + iscroll5.js(滚动条处理) + Animate.css(CSS3动画) + Enquire.js(处理响应式布局)。

可见移动端每个部件都烂到蕊了,每个部件都需要专门的工具进行修复。移动端是非常注重体验的,每一个小角落都存在着各种动画,但浏览器或自带的webview都很差劲,于是native与hybird的话题才一直这么火。有的人说,既然dom是最吃性能,那么就干脆用canvas来代替吧( http://zhuanlan.zhihu.com/FrontendMagazine/19967854http://www.ruanyifeng.com/blog/2015/02/future-of-dom.html )。facebook也推出自己类似的方案, react native,自己实现一套GUI,不过编写语言是javascript。它是使用自己原来的超高性能轮子react实现的。这或者是一条道路。但优缺点也明显,正如angular浓浓的java风,react是在逻辑插入大段标签语言(jsx)。同时react的排它性也非常强,很难与其他库搭配使用。同时,我们可以看到,出自jQuery名门的jQuery mobile并没有入围,那个性能太糟了,连sencha touch。上面说的只是核心库, 还没有搬出UI库呢。号称mobile first的UI库不在少数,由于无视IE,可以大胆使用CSS3。目前比较出彩的有,foundation,semantic,refill, ratchet。如果只是想运行在平板上,性能问题就不会那么拮据了,我们还可以试试inoic, sencha touch, Kendo UI Mobile……

基本上,针对每个平台,我都列出一些主流框架了,但不意味着你们都能驾驭得住。小马过马,老牛没过膝,松鼠淹个半死,就是这么回事。创业公司喜欢新框架,这与他们拿得起高薪招一两个前端牛人而致,基本上所有页面就是他们干的,因此用angular或ember都没区别。小公司则小心,人员流失大,jQuery+requirejs是万金油。大公司则基本上有自己的技术沉淀,换言之,应该有自己的前端框架,除非那东西很陈旧,不建议再造轮子。大公司建议是搞自己的技术委员会,根据自己的人员配置来挑选的框架。有句话说得好,不求最好,但求最合适.有些框架就属于牛逼人手里牛逼闪闪,二逼人手里一团乱麻的。对于某些成长特别快的中等公司来说,这点最需防范 ,牛人是有的,但作战的主体70%都是刚培训出来的实习生,难上手,中文文档不全的框架就必须过滤掉。我也不排除造轮子的可能性,毕竟有些公司就是人才济济,能推出一些靠谱的开源产品来造福社区。

但无论我们选择什么框架或决定自己动手造轮子,都勿忘初心,技术必须让我们工作生活更为轻松愉快——我们只选择我们能驾驭住的框架,我们不能保证它在一年后会过时落后,但至少不会变成绊脚石。套用亚当·斯密的话(税收是一种必要的恶)来说,框架是一种必要的恶,它是强约束的,因此必须慎重选择。

Owner

RubyLouvre commented May 7, 2015

如何挑选适合的前端框架

最近几年,前端技术迅猛发展,差不多每年都会冒出一款主流的框架。 每次新开业务线或启动新项目时,是第一件事就是纠结:使用什么框架,重造什么轮子?我很高兴应CSDN的邀请谈我的看法。

在五六年,移动端还没有兴起,我们没有什么选择,就是jQuery。有人会说,jQuery只是类库,不是框架;但那时前端业务还没有像今天这么繁重,原本是后端干的事,全部挪到前端来,因为光是jQuery就可以包打天下。jQuery不够用,还有成千上万的jQuery的插件呢。于是问题就是这样一一衍生出来了,一个页面太多jQuery插件了,请求数太多了,于是我们得打包。打包需要我们对插件有规划。于是这需求在社区上逐渐形成了某些规则,其中最出名的是AMD规范,体现上requirejs这个加载库上。

requirejs是前端技术发展上的一个分水岭。javascript在es6之前一直没有自己的加载机制,requirejs的出现意味着前端可以向更大规模发展。以后我说的技术选型,一个非常重要的甄选点, 就是 是否存在加载器机制或符合某个模块规范。

qq 20150508110531

回到原来的话题,选择框架要从两面看,一是看该框架的本领,二是看你们团队的能耐。

从框架的角度来看, 它的功能丰富不丰富,社区活跃度如何,国内社区活跃度如何(有的在国外流行,但国内只有初创公司或一些大公司的边缘项目在试水),文档齐全吗,及时更新吗,测试覆盖率如何,上手难度如何,都是我们考量点。不过能进我们视野内的外国框架,基本是身经百战,在造轮子兴盛的世界闯出来的领头羊。jQuery, angular, knockout, emberjs, polymer, react, backbone, zepto,我们基本是围绕在这几个上面转了。当然还有更大型的东西, EXT, YUI, dojo, easyui, bootstrap, 这是UI库层面的。

下面是2012年外国对当时流行12个javascript MVC框架的纯技术评估:
20120523084951_253

显然,我们第一步就是圈定时下最流行的框架与库,作为评估对象,然后再根据自家公司的情况进行筛选。贵公司是建站公司,还是有自己产品的公司呢?如果是建站公司,页面不会复杂到哪里去,基本上jQuery+bootstrap 搞定,不要想得太多,就是它们。如果有自己产品, 要维护一大堆客户数据要与客户打交道,不难想象是存在非常复杂的CRM系统,按照中国人的特性,这东西只会越来越复杂,这就要慎重考虑了。这往往是持续十年的维护升级,我们需要看一下这框架是否有你们的产品那么长寿,这框架的升级更新是否频繁平缓。

如果你的项目是一个跨度三年以上的大工程,用《人月神话》的术语来说,90%就是个焦油坑。我们需要使用更稳键成熟的技术方案,我们需要重点避开谷歌的产品,它的许多产品都是玩票性质, GWT、Closure、Darty就是前车之鉴。polymer是基于许多新技术构建(http://www.csdn.net/article/2013-05-27/2815450-google-polymer),其中Object。observe(), Custom Elements, HTML Imports,Shadow DOM, Model-Driven Views是远远没被标准化, 许多还是独家的, 变数太大,因此才出现如下的悲剧 http://weibo.com/1712131295/CfB7X336J?type=comment#_rnd1430880258836。 angular不是我黑它, 这东西也喜欢断崖式升级, 它在1.08时兼容IE6-8, 1.2时需要打补丁兼容旧式IE, 1.3摒弃对旧式IE的兼容,直接在源码中删除所有兼容代码,因此所有补丁方案都无力回天,并且不支持全局Ctrl函数,许多模块需要独立引用,1.4不向下支持动画模块, 2.0由at改成ts构建,由于使用Object.observe,因此不支持IE6-11,chrome30-……

requirejs

如果你们的产品是后台系统,那么就有两个选择,使用EXT, easyui这些重大的UI库方案,其中EXT具有严重的排它性,它很难与其他前端解决方案并用。什么模块组织,打包,数据可视化,它都已经全部帮你搞定。它文档齐备漂亮, 入门难度中等, 但它要求你的团队非常稳定,现在招一个专职EXT的前端是很难的。easyui是国内比较大牌的UI框架,虽然闭源,不过想扩展它不是难事。此外,国内的淘宝kissy, 网易nej也不错。还有更轻量的方案,MVVM。MVVM最擅长做这些重交互的产品。举例说,为了对应复杂交互的gird,jquery社区开发出各种庞大巨物 datagrid, jqgrid, flexigrid,还不如MVVM几个循环绑定来个干脆利落,扩展性又好。目前,knockout, emberjs, angular与我写的avalon就是这一类框架。angular虽然有点坑,但如果你是从1.3用起,并且不鸟IE,它还是一个不错的选择,其活跃的社区为它带来无限的可能。knockout在。net人群中非常流行,微软出品,前端MVVM框架的鼻祖,不过它需要对后端数据进行过多的加工,因为它本身是不支持对套嵌对象的绑定。emberjs没有一个好干爹,但有一个好亲爹,作者Yehuda Katz是jQuery, rails, Sproutecore, Merb, Handlebars这些著名框架的核心成员, 虎父无犬子,emberjs现在还是国外的第二大MVVM框架。avalon是比较适合国情的MVVM,有它专门兼容IE6的版本,易上手,性能高,视频教程多,出了问题可以抓得着作者,是它的几大卖点。

如果你们的产品是商场这样重演示类的产品,就对SEO有要求,MVVM就不适合了。目前也就angular与avalon在搞后端渲染机制,但还不上了台面。这时jQuery+bootstrap+requirejs就非常好用。requirejs的作用不单单是提供了一个按需加载机制,它还能让我们组织起更为庞大的代码。如果不用requirejs,国内另一个选择是seajs,它的规范是CMD。此外还有commonjs规范, 但这无法直接运行于前端,需要借助fekit, fis, webpack这样的构建工具进行合并了。不管怎么说,你这时选用的框架必须存在AMD,CMD或commonjs任一种加载规范,这方便你以后的横向扩展。至于插件,目前小插件们都趋向用UMD( https://github.com/umdjs/umd ),它可以让AMD,CMD,commonjs任一种加载器加载。

如果你们的产品是移动端,基本上是SPA架构了,因为这会减少等待,整页刷新与请求数。目前该领域非常混乱了,不同于PC端,这要兼容的浏览器是多出N倍,并且为了性能,浏览器商乱砍功能或改变一些浏览器特性的行为,这往往引发一些奇怪的BUG,目前社区正在整理这些坑与解药( https://github.com/jtyjty99999/mobileTech )。但目前没有一个框架能够摆平所有问题,都需要多管齐下。我的见解是

requirejs(按需加载,移动端上可以不打包,善用304缓存,腾讯搞出一个更牛叉的增量更新加载器MT,也可以试试) + backbone(组织代码与路由管理) + zepto(轻量DOM操作) + fastclick.js(点击穿透与延迟处理) + hammer.js(各种触屏事件) + iscroll5.js(滚动条处理) + Animate.css(CSS3动画) + Enquire.js(处理响应式布局)。

可见移动端每个部件都烂到蕊了,每个部件都需要专门的工具进行修复。移动端是非常注重体验的,每一个小角落都存在着各种动画,但浏览器或自带的webview都很差劲,于是native与hybird的话题才一直这么火。有的人说,既然dom是最吃性能,那么就干脆用canvas来代替吧( http://zhuanlan.zhihu.com/FrontendMagazine/19967854http://www.ruanyifeng.com/blog/2015/02/future-of-dom.html )。facebook也推出自己类似的方案, react native,自己实现一套GUI,不过编写语言是javascript。它是使用自己原来的超高性能轮子react实现的。这或者是一条道路。但优缺点也明显,正如angular浓浓的java风,react是在逻辑插入大段标签语言(jsx)。同时react的排它性也非常强,很难与其他库搭配使用。同时,我们可以看到,出自jQuery名门的jQuery mobile并没有入围,那个性能太糟了,连sencha touch。上面说的只是核心库, 还没有搬出UI库呢。号称mobile first的UI库不在少数,由于无视IE,可以大胆使用CSS3。目前比较出彩的有,foundation,semantic,refill, ratchet。如果只是想运行在平板上,性能问题就不会那么拮据了,我们还可以试试inoic, sencha touch, Kendo UI Mobile……

基本上,针对每个平台,我都列出一些主流框架了,但不意味着你们都能驾驭得住。小马过马,老牛没过膝,松鼠淹个半死,就是这么回事。创业公司喜欢新框架,这与他们拿得起高薪招一两个前端牛人而致,基本上所有页面就是他们干的,因此用angular或ember都没区别。小公司则小心,人员流失大,jQuery+requirejs是万金油。大公司则基本上有自己的技术沉淀,换言之,应该有自己的前端框架,除非那东西很陈旧,不建议再造轮子。大公司建议是搞自己的技术委员会,根据自己的人员配置来挑选的框架。有句话说得好,不求最好,但求最合适.有些框架就属于牛逼人手里牛逼闪闪,二逼人手里一团乱麻的。对于某些成长特别快的中等公司来说,这点最需防范 ,牛人是有的,但作战的主体70%都是刚培训出来的实习生,难上手,中文文档不全的框架就必须过滤掉。我也不排除造轮子的可能性,毕竟有些公司就是人才济济,能推出一些靠谱的开源产品来造福社区。

但无论我们选择什么框架或决定自己动手造轮子,都勿忘初心,技术必须让我们工作生活更为轻松愉快——我们只选择我们能驾驭住的框架,我们不能保证它在一年后会过时落后,但至少不会变成绊脚石。套用亚当·斯密的话(税收是一种必要的恶)来说,框架是一种必要的恶,它是强约束的,因此必须慎重选择。

@qinhanlei

This comment has been minimized.

Show comment
Hide comment
@qinhanlei

qinhanlei Jul 10, 2015

最近需要学习JavaEE后端技术,搜索至此,对理解概念和原理真是大有帮助,十分感谢!

最近需要学习JavaEE后端技术,搜索至此,对理解概念和原理真是大有帮助,十分感谢!

@pcwuyu

This comment has been minimized.

Show comment
Hide comment
@pcwuyu

pcwuyu Apr 25, 2016

受益匪浅,甚是感激。

pcwuyu commented Apr 25, 2016

受益匪浅,甚是感激。

@4357

This comment has been minimized.

Show comment
Hide comment
@4357

4357 May 17, 2016

十分感谢!

4357 commented May 17, 2016

十分感谢!

@kayhong

This comment has been minimized.

Show comment
Hide comment
@kayhong

kayhong Jun 9, 2016

不得不说 写得真是66666
一字一句都很清楚, 醍醐灌顶就是这个!
逻辑, 层次, 无可挑剔

感谢!!!

kayhong commented Jun 9, 2016

不得不说 写得真是66666
一字一句都很清楚, 醍醐灌顶就是这个!
逻辑, 层次, 无可挑剔

感谢!!!

@WinjayYu

This comment has been minimized.

Show comment
Hide comment
@WinjayYu

WinjayYu Jul 18, 2016

写的真好,最近正在学习springMVC,受益匪浅

写的真好,最近正在学习springMVC,受益匪浅

@Lnybb

This comment has been minimized.

Show comment
Hide comment
@Lnybb

Lnybb Aug 24, 2016

受益匪浅,学技术应该究其本质

Lnybb commented Aug 24, 2016

受益匪浅,学技术应该究其本质

@RandomCas

This comment has been minimized.

Show comment
Hide comment
@RandomCas

RandomCas Sep 20, 2016

听君一席话,甚读十年书

听君一席话,甚读十年书

@yyy2015

This comment has been minimized.

Show comment
Hide comment
@yyy2015

yyy2015 Feb 17, 2017

正在学习j2ee技术,受益良多

yyy2015 commented Feb 17, 2017

正在学习j2ee技术,受益良多

@firefoxer1992

This comment has been minimized.

Show comment
Hide comment
@firefoxer1992

firefoxer1992 Feb 28, 2017

666。编程思想很重要。。

666。编程思想很重要。。

@mogongzi

This comment has been minimized.

Show comment
Hide comment
@mogongzi

mogongzi Mar 8, 2017

感谢楼主分享

mogongzi commented Mar 8, 2017

感谢楼主分享

@Lhcnicholas

This comment has been minimized.

Show comment
Hide comment
@Lhcnicholas

Lhcnicholas Mar 17, 2017

最近被问到类似的问题。静下心来仔细想想,自己还真的是不知道为什么,平时的开发中,都是拿来就用,而缺少这样的疑问。楼主这篇文章给了我很大帮助!!

最近被问到类似的问题。静下心来仔细想想,自己还真的是不知道为什么,平时的开发中,都是拿来就用,而缺少这样的疑问。楼主这篇文章给了我很大帮助!!

@LuckyLin

This comment has been minimized.

Show comment
Hide comment
@LuckyLin

LuckyLin Mar 20, 2017

解释得通俗易懂!感谢楼主

解释得通俗易懂!感谢楼主

@zhuzhongqiang

This comment has been minimized.

Show comment
Hide comment
@zhuzhongqiang

zhuzhongqiang Jun 7, 2017

叼的一比

叼的一比

@miotyan

This comment has been minimized.

Show comment
Hide comment
@miotyan

miotyan Jun 27, 2017

像我这种除了666也不会说别的了,谢谢博主的文章帮我理清思路

miotyan commented Jun 27, 2017

像我这种除了666也不会说别的了,谢谢博主的文章帮我理清思路

@bryant-shuai

This comment has been minimized.

Show comment
Hide comment
@bryant-shuai

bryant-shuai Aug 4, 2017

博主你好,我一直有个疑问:就是java中为什么不使用Vue,angular等 这些很火的js技术,而使用easyUI呢?

博主你好,我一直有个疑问:就是java中为什么不使用Vue,angular等 这些很火的js技术,而使用easyUI呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment