|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
在ruby里才是一切皆对象。当然我不并不是很了解ruby,但是ruby确实是将语法简化得很好。项目 我看到良多项目中,开辟者完成了本人的MVC框架,并非由于他们想做同Struts基本分歧的工具,而是由于他们并没无意识到怎样扩大Struts。开辟本人的MVC框架能够取得全体的把持权,可是这也意味着必要良多资本来完成它(人力物力),在严重的日程布置下,偶然候这是不成能的。 Struts不单单是一个壮大的框架,同时它也是可扩大的。你能够以三种体例来扩大Struts。 1、PlugIn:假如你想在applicationstartup或shutdown的时分做一些营业逻辑的话,那就创立你本人的PlugIn类。 2、RequestProcessor:假如你想在哀求被处置的过程当中某个时候做一些营业逻辑的话,那末创立你本人的RequestProcessor类。好比说,在每次哀求实行之前,你能够扩大RequestProcessor来反省用户是不是上岸了和他是不是有权限往实行某个特定的action。 3、ActionServlet:假如你想在applicationstartup和shutdown的时分和哀求被处置的时分做某些营业逻辑,你也能够扩大ActionServlet类。不外你应该在PlugIn和RequestProcessor都不克不及办理你的需求的时分来利用ActionServlet。 在这篇文章中,我们将利用一个Struts使用的示例来树模怎样利用这三种体例来扩大Struts。示例程序的代码能够从http://www.onjava.com/onjava/2004/11/10/examples/sample1.zip下载。两个扩大Struts乐成的典范是Struts本身的Validation和Tiles框架。 我们假定你已对照熟习Struts框架而且晓得怎样利用它创立一个复杂的使用。假如你想晓得更多关于Struts的内容,请参考官方主页。 PlugIn PlugIn是一个接口,你能够创立一个完成该接口的类,当applicationstartup或shutdown的时分做些事变。 例如说,我创立了一个利用Hibernate作为耐久层的web使用,我想当使用启动的时分就初始化Hibernate,如许子当我的web使用遭到第一个哀求的时分,Hibernate就已是设置好的而且可用的。同时我们想当application封闭的时分封闭Hibernate。我们能够用一个HibernatePlugIn来完成这个需求,经由过程以下的两步: 1、创立一个类完成了PlugIn接口: publicclassHibernatePlugInimplementsPlugIn{ privateStringconfigFile; //Thismethodwillbecalledatapplicationshutdowntime publicvoiddestroy(){ System.out.println("EnteringHibernatePlugIn.destroy()"); //Puthibernatecleanupcodehere System.out.println("ExitingHibernatePlugIn.destroy()"); } //Thismethodwillbecalledatapplicationstartuptime publicvoidinit(ActionServletactionServlet,ModuleConfigconfig) throwsServletException{ System.out.println("EnteringHibernatePlugIn.init()"); System.out.println("valueofinitparameter"+ getConfigFile()); System.out.println("ExitingHibernatePlugIn.init()"); } publicStringgetConfigFile(){ returnname; } publicvoidsetConfigFile(Stringstring){ configFile=string; } } 完成PlugIn接口的类必需完成两个办法:init()和destroy()。当applicationstartup的时分init()办法被挪用,当shutdown的时分destroy()办法被挪用。Struts还同意给你的PlugIn类传送初始化参数。为了传送参数,你必需在PlugIn类中为每个参数创立JavaBean式的setter办法。在我们的HibernatePlugIn类中,我会把configFile的name作为参数传出来,而不是硬编码到程序中。 2、在struts-config.xml中增加以下的代码来公告Struts有新的PlugIn: <struts-config> ... <!--MessageResources--> <message-resourcesparameter="sample1.resources.ApplicationResources"/> <!--Declareyourplugins--> <plug-inclassName="com.sample.util.HibernatePlugIn"> <set-propertyproperty="configFile"value="/hibernate.cfg.xml"/> </plug-in> </struts-config> 属性className是完成了PlugIn接口的类的全限制名。关于每个初始化参数,可使用<set-property>元素传送参数。在我们的例子中,我要把config文件的名字传出来,以是利用了一个带有设置文件路径的<set-property>。 Struts的Tiles和Validator框架都利用PlugIn来读取设置文件举行初始化。别的两件PlugIn能够帮你做到的事变是: ·假如你的application依附于某些设置文件,那末你能够在PlugIn类中反省它们是不是可用,假如不成用的话抛出一个ServletException,如许就能够使ActionServlet变成不成用。 ·PlugIn接口的init()办法是你能够改动ModuleConfig的最初时机,ModuleConfig是一组静态设置信息的汇合,用来形貌基于Struts模块。Struts将会在一切PlugIn处置完后开释ModuleConfig。 Request是怎样被处置的 ActionServlet是Struts框架中独一的Servlet,它卖力处置一切request。不管什么时候吸收到一个request,它城市先实验为以后的request寻觅一个sub-application。一旦一个sub-application被找到,ActionServlet就会为谁人sub-application创立一个RequestProcessor对象,挪用这个对象的process()办法并把HttpServletRequest和HttpServletResponse对象传进。 RequestProcessor.process()就是年夜部分request被处置的中央。process()办法利用了TemplateMethod形式完成,个中有良多自力的办法来实行哀求处置的每步骤,这些办法将会在process办法中顺次被挪用。好比,将会有一个自力的办法用来寻觅以后request对应的ActionForm类,一个办法来反省以后用户是不是有实行actionmapping所必需的权限。这些授与我们极年夜的天真性。在公布的Struts包中有一个RequestProcessor类供应了哀求处置每步骤的默许完成。这就意味着你能够仅仅重写你感乐趣的办法,别的的利用默许的完成。举例来讲,默许地Struts挪用request.isUserInRole()来反省用户是不是有权限实行以后的ActionMapping;这时候假如你想经由过程查询数据库来完成,你所要做的就是重写processRoles()办法,经由过程查询出的用户是不是具有必需的权限来前往true或false。 起首我们将会看到缺省情形下,process()办法是怎样完成的,然后我将会具体注释默许的RequestProcessor类中的每个办法,如许你就能够决意哪一部分是你想要改动的。 publicvoidprocess(HttpServletRequestrequest,HttpServletResponseresponse) throwsIOException,ServletException{ //Wrapmultipartrequestswithaspecialwrapper request=processMultipart(request); //Identifythepathcomponentwewill //usetoselectamapping Stringpath=processPath(request,response); if(path==null){ return; } if(log.isDebugEnabled()){ log.debug("Processinga"+request.getMethod()+"forpath"+path+""); } //SelectaLocaleforthecurrentuserifrequested processLocale(request,response); //Setthecontenttypeandno-cachingheaders //ifrequested processContent(request,response); processNoCache(request,response); //Generalpurposepreprocessinghook if(!processPreprocess(request,response)){ return; } //Identifythemappingforthisrequest ActionMappingmapping= processMapping(request,response,path); if(mapping==null){ return; } //Checkforanyrolerequiredtoperformthisaction if(!processRoles(request,response,mapping)){ return; } //ProcessanyActionFormbeanrelatedtothisrequest ActionFormform=processActionForm(request,response,mapping); processPopulate(request,response,form,mapping); if(!processValidate(request,response,form,mapping)){ return; } //Processaforwardorincludespecifiedbythismapping if(!processForward(request,response,mapping)){ return; } if(!processInclude(request,response,mapping)){ return; } //CreateoracquiretheActioninstanceto //processthisrequest Actionaction= processActionCreate(request,response,mapping); if(action==null){ return; } //CalltheActioninstanceitself ActionForwardforward=processActionPerform(request,response,action,form,mapping); //ProcessthereturnedActionForwardinstance processForwardConfig(request,response,forward); } 1、processMutipart():在这个办法中,Struts将会读取request来反省request的contentType是不是是multipart/form-data。假如是的话,将会剖析request而且将之包装到HttpServletRequest中。当你创立了一个HTMLFORM用来提交数据,那末request的contentType默许就是application/x-www-form-urlencoded。可是假如你的form利用了file范例的input控件同意用户上传文件的话,你就必需将contentType改成multipart/form-data。假如是如许的情形,你就不克不及再经由过程getParameter()来猎取用户提交的数据;你必需将request作为一个InputStream来读取,而且本人剖析它来取得参数值。 2、processPath():在这个办法中,Struts将会读取request的URI,来断定路径元素,这个元素是用来猎取ActionMappint元素。 3、processLocale():在这个办法中,Struts将会为以后request获得Locale,假如设置过的话,还能够将这个对象作为HttpSession中org.apache.struts.action.LOCALE属性的值而保留。作为这个办法的反作用,HttpSession将会被创立,假如你不想创立的话,你能够在ControllerConfig中将locale属性设为false,在struts-config.xml中象以下如许: <controller> <set-propertyproperty="locale"value="false"/> </controller> 4、processContent():经由过程挪用response.setContentType()来为response设置contentType。这个办法起首会实验从struts-config.xml设置中失掉contentType。缺省情形下利用text/html。假如想掩盖它,能够象以下如许: <controller> <set-propertyproperty="contentType"value="text/plain"/> </controller> 5、processNoCache():假如设置是no-cache,Struts将会为每一个response设置上面三个headers: requestedinstrutsconfig.xml response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires",1); 假如你想设置no-cacheheader,在struts-config.xml中到场上面信息: <controller> <set-propertyproperty="noCache"value="true"/> </controller> 6、processPreprocess():这个办法为预处置供应一个hook,能够在子类中掩盖它。它的缺省完成没有作任何事变,老是前往true。前往false的话将会停止以后哀求的处置。 7、processMapping():这个办法将会用路径信息失掉一个ActionMapping对象。也就是struts-config.xml文件中的<action>元素: <actionpath="/newcontact"type="com.sample.NewContactAction"name="newContactForm"scope="request"> <forwardname="sucess"path="/sucessPage.do"/> <forwardname="failure"path="/failurePage.do"/> </action> ActionMapping元素包括了Action类的称号和处置哀求利用的ActionForm等等信息。它还包括以后ActionMapping设置的ActionForwards信息。 8、processRoles():Strutsweb使用供应了一个受权计划。也就是说,一旦一个用户登进了容器,struts的processRoles()办法将会经由过程挪用request.isUserInRole(),来反省他是不是有必需的脚色来运转一个给定的ActionMapping。 <actionpath="/addUser"roles="administrator"/> 假定你有一个AddUserAction而且你只想让administrator可以增添新的user。你所要做的就是给你的AddUserAction元素增添一个role属性,这个属性的值为administrator。如许,在运转AddUserAction之前,这个办法会确保用户具有administraotr的脚色。 9、processActionForm():每个ActionMapping都一个响应的ActionForm类。当Struts处置一个ActionMapping的时分,它将会从<action>元素的name属性中找出对应的ActionForm类的称号。 <form-beanname="newContactForm"type="org.apache.struts.action.DynaActionForm"> <form-propertyname="firstName"type="java.lang.String"/> <form-propertyname="lastName"type="java.lang.String"/> </form-bean> 在我们的例子中,它会先在requestscope中反省是不是有一个org.apache.struts.action.DynaActionForm类的对象存在。假如有它将会利用这个对象,假如没有它将会创立一个新的对象并把它设置在requestscope。 10、processPopulate():在这个办法中,Struts将会用相婚配的request参数拆卸ActionForm的实例变量。 11、processValidate():Struts将会挪用你的ActionForm类的validate办法。假如你从validate()前往ActionErrors,它将会将user重定向到<action>元素的input属性指定的页面。 12、processForward()和processInclude():在这些办法中,Struts将会反省<action>元素的forward或include属性,假如找到了,将会把forward或include哀求安排到设置的页面中。 <actionforward="/Login.jsp"path="/loginInput"/> <actioninclude="/Login.jsp"path="/loginInput"/> 你能够从这些办法的名字上推测它们的分歧:processForward()终极挪用RequestDispatcher.forward(),而processInclude()挪用RequestDispatcher.include()。假如你同时设置了forward和include属性,它将会老是挪用forward,由于forward先被处置。 13、processActionCreate():这个办法从<action>元素的type属性中猎取取得Action类的名字而且创立前往它的实例。在我们的例子中,它将会创立一个com.sample.NewContactAction类的实例。 14、processActionPerform():这个办法挪用你的Action类的excute()办法,你的营业逻辑也就是在excute办法中。 15、processForwardConfig():你的Action类的excute()办法将会前往一个ActionForward对象,这个对象将指出哪一个页面是显现给用户的页面。因而,Struts将会为谁人页面创立一个RequestDispatcher,而且挪用RequestDispatcher.forward()。 下面的列表申明了默许的RequestProcessor完成在处置哀求时每步作的事情,和实行的按次。正如你所看到的,RequestProcessor长短常天真的,同意你经由过程设置<controller>元素的属性来设置它。举例来讲,假如你的使用筹办天生XML内容来取代HTML,你就能够经由过程设置controller元素的属性来关照Struts这些情形。 创立你本人的RequestProcessor 经由过程下面,我们懂得到了RequestProcessor的默许完成是怎样事情的。如今我们要演示一个例子来讲明怎样定制你本人的RequestProcessor。为了展现创立用户定制的RequestProcessor,我们将会让我们的示例完成上面两个营业需求: ·我们想创立一个ContactImageAction类,它将天生图片而不是寻常的HTML页面。 ·在每一个哀求处置之前,我们都想经由过程反省session中的userName属性来断定用户是不是已上岸。假如谁人属性没有找到,我们会把用户重定向到上岸页面。 我们将分两步完成这些营业需求。 1、创立你的CustomRequestProcessor类,它将承继自RequestProcessor类,以下: publicclassCustomRequestProcessor extendsRequestProcessor{ protectedbooleanprocessPreprocess( HttpServletRequestrequest,HttpServletResponseresponse){ HttpSessionsession=request.getSession(false); //Ifuseristryingtoaccessloginpage //thendontcheck if(request.getServletPath().equals("/loginInput.do") ||request.getServletPath().equals("/login.do")) returntrue; //CheckifuserNameattributeisthereissession. //Ifso,itmeansuserhasallreadyloggedin if(session!=null&&session.getAttribute("userName")!=null) returntrue; else{ try{ //IfnoredirectusertologinPage request.getRequestDispatcher("/Login.jsp").forward(request,response); }catch(Exceptionex){ } } returnfalse; } protectedvoidprocessContent(HttpServletRequestrequest, HttpServletResponseresponse){ //CheckifuserisrequestingContactImageAction //ifyesthensetimage/gifascontenttype if(request.getServletPath().equals("/contactimage.do")){ response.setContentType("image/gif"); return; } super.processContent(request,response); } } 在CustomRequestProcessor类的processPreprocess办法中,我们反省session的userName属性,假如没有找到,就将用户重定向到上岸页面。 关于天生图片作为输入的需求,我们必需掩盖processContent办法,起首反省哀求是不是是/contactimage路径。假如是的话,我们就会将contentType设置为image/gif;不然设置为text/html。 2、在你的struts-config.xml文件的<action-mappint>元素以后到场上面的笔墨,告知StrutsCustomRequestProcessor应该被用作RequestProcessor类: <controller> <set-propertyproperty="processorClass"value="com.sample.util.CustomRequestProcessor"/> </controller> 请注重,当你只要很少的action类必要天生非text/html范例的输入时,你覆写processContent()办法是OK的。假如不是如许子的话,你应当创立一个Struts的子使用来处置哀求天生图片的Action,并为它们将contentType设置为image/gif。 Struts的Tiles框架就是利用它本人的RequestProcessor来粉饰Struts的输入。 ActionServlet 假如你检察你的Strutsweb使用的web.xml,你会看到如许的笔墨: <web-app> <servlet> <servlet-name>action=</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <!--Allyourinit-paramsgohere--> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app> 这意味着ActionServlet卖力处置你一切Struts的哀求。你能够创立一个ActionServlet的子类,当使用启动,封闭,每一个哀求的时分做一些特定的事变。可是在承继ActionServlet类之前,你应当只管创立一个PlugIn或RequestProcessor往办理你的成绩。在Servlet1.1之前,Tiles框架是基于ActionServlet来润色天生的呼应。可是从1.1以后,它入手下手利用TilesRequestProcessor类。 总结 决意开辟你本人的MVC框架是一个十分年夜的决意,你必需要思索开辟和保护框架代码所消费的工夫和资本。Struts是一个十分壮大和不乱的框架,你能够修正它来满意你尽年夜多半的营业需求。 但另外一方面,也不要轻率地做出扩大Struts的决意。假如你在RequestProcessor中写了一些功能对照低的代码,它将会在每次哀求时实行,因此下降你全部使用的效力。并且仍是有一些情形,开辟本人的MVC框架要比扩大Struts好。
你说是sun公司对她研究的透还是微软?针对自己工具开发的.net性能上肯定会站上风的。 |
|