|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
归根到底,net网页编程跨平台可以,但是要重新编写代码,否则还分什么J2EE/J2SE/J2ME呢!比来在写一个营业上用到的框架,回忆起打仗过的一些MVC框架,特别是次要奉献在后端体现层上的那些,它们之间有太多的类似,在不休解耦的过程当中,层数和模块数也愈来愈多,必要不休引进层与层之间的映照逻辑将分歧条理之间联系关系起来,我们无妨来检察一下这个历程,可否寻觅一些MVC框架的个性和启发。
MVC1到MVC2模子的退化
这个话题有点老。MVC1在桌面程序中使用较多,营业逻辑固然放在Model内里,Controller卖力将用户的哀求数据传送到Model往,以后就撒手不论了,让View经由过程察看者形式不休获知Model的最新变更(能够是Model变更后关照View,也能够是View本人来猎取)。这个形式看起来很复杂,不外很简单发明一个严峻的成绩,View必需对Model洞若观火,要否则怎样察看它呢。这其实是一件不甚公道的事变。
MVC2则解开了Model和View的耦合,Controller酿成了中介者一样的脚色,View吸收了用户输出,Controller把处置哀求分拨给Model,处置完后,又把了局交回View来展示。不外,如许的价值是Controller酿成了一个百事通,假如它要体贴Model和View的详细完成,耦合的成绩只是换了一件外套罢了。以是,必要对Controller进一步解耦。上面的话题,也是借由这一点睁开的。
从这个改动就能够看出在解耦方面的退化,可是仍然没有做足,厥后ASP.NET又出了MVC3、MVC4,我没有往懂得个中的变动。这只是关于解耦的一个前传,上面让我们回到正题,看看那些跟着解耦的进一步举行,新发生的映照逻辑和设置。
URLMapping
大概最早会有人如许写代码:
12345if("/ServletTest/eg1".equals(request.getURI()))xxx;elseif("/ServletTest/eg2".equals(request.getURI()))xxx;......可是如今应当已不会有人如许写了,印象中即使是最早只是用JSP+Servlet写程序的那一批程序员写网站使用的时分,URL和把持器出口的映照逻辑也已被自力出来了,比方Tomcat的web.xml:
12345678<servlet><servlet-name>Example</servlet-name><servlet-class>com.xxx.xxx.Example</servlet-class></servlet><servlet-mapping><servlet-name>Example</servlet-name><url-pattern>/example</url-pattern></servlet-mapping>可是如许的设置婚配的表达式不敷天真(比方没法自界说婚配逻辑),并且设置过于冗杂(一般来讲,我是一个xml设置文件的仇恨者),因而当今的MVC框架都供应了一套本人的映照婚配逻辑,比方Struts2:
1234<actionname="example"class="com.xxx.xxx.ExampleAction"><resultname="success"type="dispatcher">/success.jsp</result><resultname="input".../></action>还能够设置全局的跳转逻辑,传送参数等等,总之设置是天真多了,但是每写一段把持器的逻辑,仍是必要设置一段到XML文件中。如许的成绩也是能够办理的,将变更点自力到Action里,设置文件中只写这个变更的参数,如许只必要一个设置就能够完成年夜部分跳转了。
关于分歧参数称号和参数个数变更的情形,下面的举措撑持得又欠好了,幸亏很多框架都供应了注解设置的举措,把URL映照的逻辑酿成短短的注解:
1@Results({@Result(name="success",location="/success.jsp"),@Result(name="error",location="/error.jsp")})但是这帮难奉养的程序员啊,仍是嫌贫苦,这就必要使用CoC准绳(规约优于设置,ConventionoverConfiguration)。在SpringMVC中,声了然ControllerClassNameHandlerMapping今后,关于如许没有设置任何映照信息的办法:
123456@ControllerpublicclassExampleControllerextendsMultiActionController{@RequestMappingpublicvoide1(...);}类名叫做ExampleController,办法名叫做e1,因而在利用以下URI举行会见的时分,就主动mapping到这个example办法上:
1/example/e1好了,这总满意怠惰的程序员你了吧。
DataBinding
这里DataBinding(数据绑定)指的是将用户哀求提交下去的数据和范畴模子绑定起来,即天生多少个照顾数据的模子对象。
自不用说,最原始的体例应当是相似如许的办理办法:
1234Useruser=newUser();user.setName=(String)request.getParameter("name");user.setAge=(Integer)request.getParameter("age");......这固然不会进程序员的高眼了,因而框架替你把参数绑定到一个数据汇合的对象上,你猎取起来就简单多了,好比在Grails框架中,能够如许写:
12345defexample={defname=params.name;defage=params.age;......}大概爽性换成参数映照的设置文件,但是仍是好拢谑“规约优于设置”又来了,以Struts2为例:
1234classUserAction{privateUseruser;//get/set办法}这类情形下,只需提交如许的哀求:
1/example/userAction?user.name=Jim&user.age=18这个name为Jim、age为18的User对象就主动被塞进这个Action往了。SpringMVC的情形相似,只不外粒度更小,参数注进的不是类Action实例的属性,而是Controller办法的参数——固然,头脑是一样的。
视图指向
你大概猜到我要说的内容了。程序员最原始的做法应当是相似这个模样的:
1request.getRequestDispatcher("/common/success.jsp").forward(request,response);以后退化成为设置文件设置的情势、注解设置的情势,有了前文的先容,这其实是没甚么出格的。值得一提的是,我用过一个框架,它关于URLMapping(front-controller做的事变)和ViewRouting(backend-controller做的事变)经由过程如许一种风趣的机制来完成:
- 依据URL路径和Controller前往的了局字符串往寻觅响应目次下对应称号的handler;
- 假如找不到就找defaultHandler;
- 假如仍是找不到就往上一级目次往找,依此类推。
举例来讲,Controller前往View的路径为“user/admin/do”,就到…/user/admin目次下寻觅一个do.handler的文件,找不到就寻觅同目次下的default.handler,再找不到就往父目次往递回寻觅。这类机制就使得URLMapping和ViewRouting的历程变得具有自然的承继性(好比公用的success.handler能够放在顶级目次中)。
这类体例实在也是设置,可是既不是设置文件,也不是注解,更不是代码,而是一个文件和文件夹的构造布局。
最初,你一定晓得我仍是要回到“规约优于设置”下面来。效果就是,比方会见user/do默许完成后就往寻觅…/user/success.jsp,非常后经由过程非常拦阻器起首寻觅…/user/failed.jsp。
页面聚合
关于服务端页面模板的构造在我看来一向是网站使用编程中对照亏弱的一块(客户端页面聚合即前端页面聚合我在此先不会商),直到如今,页面模板的代码仍是极简单堕入过于庞大和不容易了解的地步。最入手下手追溯到JSP出生之前的时期,页面是能够由Servlet一行一行输入的:
123PrintWriterpw=response.getWriter();pw.write("xxx");......谁人时分还没有页面模板的观点。因而JSP呈现,能够把页面HTML和页面上用于展现的Java代码糅合在一同。至于JSP最后就简单被误用做了更多的展现之外的事变,那实在并非工具自己的错。直到如今,另有很多人关于Servlet和JSP有相称的成见,在程序员谈天的时分,你如果说你的网站是用Servlet+JSP做的,对方常常会间接小看你,用那末老土的手艺。实在手艺自己并没有任何错,Servlet+JSP仍然能够十分大度地办理良多实践成绩。
关于页面模板,不管你是利用JSP,仍是FreeMarker、Velocity,你城市面临一个成绩,一个和Java代码、C++代码一样必要依附和构造的成绩。因而程序员就将页面分为几个子页面,经由过程如许的体例引进:
1<%@pageimport="xxx.jsp"%>不外,关于一些大众的页面而言,大概要被很多页面援用,几近一切的了局页面都要引进header.jsp、menu.jsp、footer.jsp……并传送一些相似的参数。这让碌某绦蛟庇志醯貌豢牧耍矣Ω冒盐矣邢薜木ψㄗ⒌揭滴裉赜械穆呒鸵趁嫔先ィ庑┩ㄓ玫牟糠挚蚣苣懿荒芴嫖揖酆希揖筒恍枰匦牧耍
这和非常处置很像,良多项目都喜好界说本人的总非常,承继自RuntimeException,不必要声明,并且在通用非常拦阻器内一致处置这些未被捕捉的非常,完成通用的逻辑处置和页面转向;而毛病信息就经由过程非常照顾出来了,程序员就不必要把精神分离到大批的非常信息传送下面——好比经由过程前往码这类必要独自处置的情势,记得在老项目(出格是存储历程)的营业逻辑中还常常看到毛病信息的前往码,如今真是愈来愈少见了。
因而Tiles给了如许的页面聚合举措,设置文件:
12345<definitionname="user"extends"main"><putname="title"value="XXXSite-User"/><putname="body"value="user.jsp"/>......</definition>而且能够天真地利用承继和参数传送,但是仍旧不爽,每个页面跳转都要设置如许一块豆腐干,其实是很隆SiteMesh供应了一种更加简便的设置体例:
123456<decoratorname="main"page="main.jsp"><pattern>/*</pattern></decorator><excludes><pattern>/admin/*</pattern></excludes>如许一来,一切的哀求(除婚配“/admin/*”如许的)全体都走到基于main.jsp聚合的逻辑中往了,通用的部分全体在main.jsp中完成,变更的页面仍然依据原本的ViewRouting的映照来寻觅页面,聚合这件事变,就真正对后续开辟的程序员通明了。
关于框架来讲,另有进一步解耦的需求吗?有。好比可设置的拦阻器,关于分歧的哀求可以利用设置为分歧数目和分歧个数拦阻器的“拦阻器栈”来呼应,既大概有前置处置,也大概有后置处置。拦阻器把底本在很多营业里都要反复做的事变(好比权限校验)经由过程AOP这类情势横向切一刀给做了。再好比序列化,假如要前往页面,情势多是text/html的,而要传送对象,情势大概就是application/json如许的,将页面大概对象转换成html大概JSON呼应的活儿,程序员固然也不想干……
纵不雅下面先容的这些MVC框架在解耦和映照方面做的奉献,我们很简单看到,在不休地解耦过程当中,层数、模块数不休在增添,庞大性应当说也在增添,设置固然更庞大,但是爱偷懒的程序总有举措让庞大变得复杂。这个因解耦引发层与层之间映照的设置即是云云:
- 程序员本人完成;
- 框架完成,可是必要手动设置;
- 规约优于设置。
恰是程序员关于怠惰的寻求,作育了一个又一个好用的MVC框架,如今开辟一个网站关于十多年前来讲,其实是烦琐太多太多了,在明天议论的角度上,将来MVC框架还会有如何的开展趋向呢?另有哪一些通用的部分会被解耦出来,你又怎样看?
在VC.net的版本上,为了让C++运行在.NETFramework中,微软为C++引进了托管,就是托管C++(ManagedC++),这个根本就没有流行起来,自托管C++产生以后就没有收到过好评。 |
|