springmvc.doc_第1页
springmvc.doc_第2页
springmvc.doc_第3页
springmvc.doc_第4页
springmvc.doc_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

总结一下springMVC几个关键的步骤,总共可以分为六个步骤,分别为:(1) 客户端向spring容器发起一个http请求(2) 发起的请求被前端控制起所拦截(DispatcherServlet),前端控制器会去找恰当的映射处理器来处理这次请求。(3) 根据处理器映射(Handler Mapping)来选择并决定将请求发送给那一个控制器。(4) 在控制器中处理所发送的请求,并以modeandView(属性值和返回的页面)的形式返回给向前端控制器。(5) 前端控制器通过查询viewResolver对象来试着解决从控制返回的视图。(6) 如果前端控制找到对应的视图,则将视图返回给客户端,否则抛异常。spring3.1 mvc 框架的特点如果仅仅关注于web方面的支持,Spring有下面一些特点: 清晰的角色划分:控制器,验证器,命令对象,表单对象和模型对象;分发器,处理器映射和视图解析器;等等。 直接将框架类和应用类都作为JavaBean配置,包括通过应用上下文配置中间层引用,例如,从web控制器到业务对象和验证器的引用。 可适应性,但不具有强制性:根据不同的情况,使用任何你需要的控制器子类(普通控制器,命令,表单,向导,多个行为,或者自定义的),而不是要求任何东西都要从Action/ActionForm继承。 可重用的业务代码,而不需要代码重复:你可以使用现有的业务对象作为命令对象或表单对象,而不需要在ActionForm的子类中重复它们的定义。 可定制的绑定和验证:将类型不匹配作为应用级的验证错误,这可以保存错误的值,以及本地化的日期和数字绑定等,而不是只能使用字符串表单对象,手动解析它并转换到业务对象。 可定制的处理器映射,可定制的视图解析:灵活的模型可以根据名字/值映射,处理器映射和视图解析使应用策略从简单过渡到复杂,而不是只有一种单一的方法。 可定制的本地化和主题解析,支持JSP,无论有没有使用Spring标签库,支持JSTL,支持不需要额外过渡的Velocity,等等。 简单而强大的标签库,它尽可能地避免在HTML生成时的开销,提供在标记方面的最大灵活性。Spring MVC开发实现步骤:1 新建web project2 添加spring支持3 修改web.xml,配置DispatcherServlet4 实现Model层实体类5实现Controller6实现View7.修改applicationContext.xml1、org.springframework.web.context.ContextLoaderListener ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。至于ApplicationContext.xml这个配置文件部署在哪,如何配置多个xml文件,书上都没怎么详细说明。现在的方法就是查看它的API文档。在ContextLoaderListener中关联了ContextLoader这个类,所以整个加载配置过程由ContextLoader来完成。看看它的API说明 第一段说明ContextLoader可以由 ContextLoaderListener和ContextLoaderServlet生成。如果查看ContextLoaderServlet的API,可以看到它也关联了ContextLoader这个类而且它实现了HttpServlet。这个接口第二段,ContextLoader创建的是 XmlWebApplicationContext这样一个类,它实现的接口是WebApplicationContext-ConfigurableWebApplicationContext-ApplicationContext-BeanFactory这样一来spring中的所有bean都由这个类来创建第三段,讲如何部署applicationContext的xml文件,如果在web.xml中不写任何参数配置信息,默认的路径是”/WEB-INF/applicationContext.xml,在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml。如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数:1. 2. contextConfigLocation3. 4. /WEB-INF/classes/applicationContext-*.xml5. 6. 在 里指定相应的xml文件名,如果有多个xml文件,可以写在一起并一“,”号分隔。上面的applicationContext-*.xml采用通配符,比如这那个目录下有applicationContext-ibatis-base.xml,applicationContext-action.xml,applicationContext-ibatis-dao.xml等文件,都会一同被载入。由此可见applicationContext.xml的文件位置就可以有两种默认实现:第一种:直接将之放到/WEB-INF下,之在web.xml中声明一个listener、第二种:将之放到classpath下,但是此时要在web.xml中加入,用它来指明你的applicationContext.xml的位置以供web容器来加载。按照 Struts2 整合spring的官方给出的档案,写成:1. 2. 3. contextConfigLocation4. /WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml5. 2、spring中dispatcherservlet的运行机制 dispatcherservlet是spring的web框架(以下简称springweb)中的核心servlet.spring的web框架象其它web框架一样是一个请求驱动的web框架,其设计围绕一个能将请求分发到控制器的servlet,它也提供其它功能帮助web应用开发。-spring framework 开发参考手册(中文版)而在springweb框架中这个servlet就是org.springframework.web.servlet.dispatcherservlet。这个servlet的继承关系如下图所示:springweb首先将传统的httpservlet抽象类包装成了bean;frameworkservlet抽象出了web框架中的servlets的一些基本行为,比如对application context的访问;dispatcherservlet的主要工作就是将一个request分发到一个合适的处理器上,并将处理返回的modelandview绘制出来返回给客户端。dispatcherservlet作为一个servlet那他一定有两个主要的方法:init()和doservice()。一 init()初始化。dispatcherservlet继承体系中init()方法的实现位于httpservletbean中,httpservletbean首先调用initbeanwrapper(),初始化beanwrapper,然后调用抽象方法initservletbean(),这个方法的实现位于他的子类frameworkservlet中;framewordservlet中的initservletbean()方法将调用initwebapplicationcontext(),初始化webapplicationcontext,然后同样调用他的抽象方法initframeworkservlet(),而这个抽象方法的实现位于最终的dispatcherservlet中;dispatcherservlet中的initframeworkservet()将依次初始化multipar(用作文件上传)解析器、本地化信息解析器、主题解析器处理器映射等等内容。所以dispatcherservlet的初始化顺序为init();initbeanwrapper();initservletbeaninitwebapplicationcontext()initframework();initmultipartresolver();initlocaleresolver();initthemeresolver();inithandlermappings();inithandleradapters();inithandlerexceptionresolvers();initviewresolvers();二 doservice()处理请求。dispatcherservlet中无论是通过post方式还是get方式提交的request,最终都会交由doservice()处理。doservice()中的处理逻辑大致分以下六个步骤:1.if(request是multipart,即文件上传) 则将request解析并包装成multiparthttpservletrequest2.mappedhandler = gethandler(request)根据request得到相应的处理器3.调用注册的所有拦截器的prehandle方法4.调用处理器 handleradapter ha = new gethandleradapter(mappedhandler.gethandler(); modelandview mv = ha.handle(req, res, mappedhandler.gethandler()/这里使用了adapter模式5.调用注册的所有拦截器的posthandle方法6.绘制mv3、Spring Autowire自动装配 在应用中,我们常常使用标签为JavaBean注入它依赖的对象。但是对于一个大型的系统,这个操作将会耗费我们大量的资源,我们不得不花费大量的时间和精力用于创建和维护系统中的标签。实际上,这种方式也会在另一种形式上增加了应用程序的复杂性,那么如何解决这个问题呢?Spring为我们提供了一个自动装配的机制,尽管这种机制不是很完善,但是在应用中结合标签还是可以大大的减少我们的劳动强度。前面提到过,在定义Bean时,标签有一个autowire属性,我们可以通过指定它来让容器为受管JavaBean自动注入依赖对象。的autowire属性有如下六个取值,他们的说明如下:1、No:即不启用自动装配。Autowire默认的值。2、byName:通过属性的名字的方式查找JavaBean依赖的对象并为其注入。比如说类Computer有个属性printer,指定其autowire属性为byName后,Spring IoC容器会在配置文件中查找id/name属性为printer的bean,然后使用Seter方法为其注入。3、byType:通过属性的类型查找JavaBean依赖的对象并为其注入。比如类Computer有个属性printer,类型为Printer,那么,指定其autowire属性为byType后,Spring IoC容器会查找Class属性为Printer的bean,使用Seter方法为其注入。4、constructor:通byType一样,也是通过类型查找依赖对象。与byType的区别在于它不是使用Seter方法注入,而是使用构造子注入。5、autodetect:在byType和constructor之间自动的选择注入方式。6、default:由上级标签的default-autowire属性确定。注意:在配置bean时,标签中Autowire属性的优先级比其上级标签高,即是说,如果在上级标签中定义default-autowire属性为byName,而在中定义为byType时,Spring IoC容器会优先使用标签的配置。下面通过一个例子来说明如何在应用中使用自动装配(工程代码见例程3.2)。新建一个java工程,为其添加上Spring开发能力后,创建一个ioc.test包,再分别创建电脑类(Computer)、主机类(Host)和显示器类(Dispaly),为电脑类添加Host类型的属性host和Display类型的属性display,再添加一个run方法,让电脑可以“运行”一起来。属性代码如下:电脑类:1packageioc.test;23/*/*4*authorzhangyong5*/6publicclassComputer78privateHosthost;9privateDisplaydisplay;10/电脑运行方法11publicvoidrun()12System.out.println(你好,我是电脑,正在运行!);13System.out.print(+host.run()+,);14System.out.println(display.run();1516/Geter和Seter方法,省略1718 再给主机类添加一run方法,让主机也可以“运行”,代码如下:1packageioc.test;23publicclassHost4publicStringrun()5return我是主机,正在运行!;678 同上也给Display类添加run方法,如下:1packageioc.test;23publicclassDisplay4publicStringrun()5return我是显示器,正在运行!;678下面便是修改Spring的配置文件,让IoC容器为我们的“电脑”自动装配“主机”和“显示器了”。分别配置两个bean,host和display。再配置一个名computer1的bean,autowire属性设为byName,同理配置computer1和computer3,autowire属性分别设为byType和default,最后设置标签的default-autowire属性为autodetect。至此,配置工作已经完成,可以看到,我们并没有显式的给computer bean它注入依赖对象host和display。配置代码如下:12345678910现在可以建立一个测试类来测试一下Spring时候真的为我们自动装配好了我们需要的bean。代码如下:1packageioc.test;23/import省略4publicclassTestMain56publicstaticvoidmain(Stringargs)7ApplicationContextac=newClassPathXmlApplicationContext(8applicationContext.xml);9/byName10Computercomputer1=(Computer)ac.getBean(computer1);11System.out.println(autowire=byName:);12computer1.run();1314/byType15Computercomputer2=(Computer)ac.getBean(computer2);16System.out.println(autowire=byType:);17computer2.run();1819/default20Computercomputer3=(Computer)ac.getBean(computer3);21System.out.println(autowire=default:);22computer3.run();232425运行该类,输出结果如下:从运行结果可以看出,Spring IoC容器已经为我们自动的装配好的“电脑”,从而配置文件简洁了许多。但是,自动装配并不是十全十美的,我们不论是使用byName还是byType的方法,Spring不一定就能很准确的为我们找到JavaBean依赖的对象。另外,如果使用自动装配,Spring配置文件的可读性也大大降低,我们不能很容易的看出个bean之间的依赖关系,这也在一定程度上降低了程序可维护性。因此在使用自动装配时,应当权衡利弊,合理的与ref的方法相结合,尽量在降低工作量的同时,保证应用的可维护度。4、spring组件扫描使用详解 关于spring自动检测组件的使用方式网上太多了,而且也不是我记录的重点,我想说下一点可能你还不知道的经验我们知道如果不想在xml文件中配置bean,我们可以给我们的类加上spring组件注解,只需再配置下spring的扫描器就可以实现bean的自动载入。先写一个小例子,剩下的在下面解释下面是引用spring framework开发手册中的一段话“Spring 2.5引入了更多典型化注解(stereotype annotations): Component、Service和 Controller。 Component是所有受Spring管理组件的通用形式;而Repository、Service和 Controller则是Component的细化,用来表示更具体的用例(例如,分别对应了持久化层、服务层和表现层)。也就是说,你能用Component来注解你的组件类,但如果用Repository、Service 或Controller来注解它们,你的类也许能更好地被工具处理,或与切面进行关联。例如,这些典型化注解可以成为理想的切入点目标。当然,在Spring Framework以后的版本中, Repository、Service和 Controller也许还能携带更多语义。如此一来,如果你正在考虑服务层中是该用 Component还是Service,那Service显然是更好的选择。同样的,就像前面说的那样, Repository已经能在持久化层中进行异常转换时被作为标记使用了。”下面是网上目前关于组件扫描最详细的介绍Spring applicationContext.xml的标签用途比我想像的還要實用。而且後來才知道,有了,另一個標籤根本可以移除掉,因為被包含進去了。原本我survery Spring3通常只配置成,意即在base-package下尋找有Component和Configuration的target Class。而現在如下的飯粒:提供兩個子標籤:和各代表引入和排除的過濾。而上例把use-default-filters屬性設為false,意即在base-package所有被宣告為Component和Configuration等target Class不予註冊為bean,由filter子標籤代勞。filter標籤在Spring3有五個type,如下:Filter TypeExamples ExpressionDescriptionannotationorg.example.SomeAnnotation符合SomeAnnoation的target classassignableorg.example.SomeClass指定class或interface的全名aspectjorg.example.*Service+AspectJ語法regexorg.example.Default.*Regelar Expressioncustomorg.example.MyTypeFilterSpring3新增自訂Type,實作org.springframework.core.type.TypeFilter所以上例用的regex就有個語病,com.foo.config.* 可以找到com.foo.config.WebLogger,但也可以找到com1fool2config3abcde,因為小數點在Regex是任意字元,是故要用.把小數點跳脫為佳。(2010/3/15補充:但要使用.方式,其use-default-filters不能為false,否則抓不到,感覺是Bug)Spring3提供豐富的Filter支援,有益配置策略,不需面臨Configuration Hell,比如Regex的com.foo.*.action.*Config,這樣就可以找到com.foo package下所有action子package的*Config的target class。我按他的例子,配置了我自己的如下:但是死活扫描不到,网上又没有更好的讲解,没办法只好自己试,改成 这样连没有加注解的类也扫描并实例化,结果报错,因为有的类根本就没有默认的构造函数不能实例化,能不报错吗改成问题依旧 嘿,这次可以了,写全限定名就可以,表达式却不行,但是如果我有成千上百个还得一个一个这样配置啊?不行,继续研究,我想有个base-package的配置,从表面意思来看这是个“基本包”,是否表示下面的过滤路径是基于这个包的呢?于是试着改成 嘿,行了。5、详解contextConfigLocation spring的应用初始化流程一直没有搞明白,刚刚又碰到了相关的问题。决定得好好看看这个流程。我们在开发spring的项目当中基本上都会在web.xml通过:1. 2. contextConfigLocation3. 4. /WEB-INF/conf/application-*.xml5. 6. contextConfigLocation /WEB-INF/conf/application-*.xml 来初始化各个spring的配置文件,但是我们只是知道这段代码的功能, 并不是很清楚我们配置了这段代码之后为什么就能去初始化配置文件。当然我们还会加上: 1. 2. org.springframework.web.context.ContextLoaderListener3. org.springframework.web.context.ContextLoaderListener 这一个listener,我首先就会想contextConfigLocation这个一定能在ContextLoaderListener这个类当中找到,打开了源码,这个listener是实现了ServletContextListener这个接口的,这个接口只有两个方法: 1. publicinterfaceServletContextListener2. extendsEventListener3. 4. 5. publicabstractvoidcontextInitialized(ServletContextEventservletcontextevent);6. 7. publicabstractvoidcontextDestroyed(ServletContextEventservletcontextevent);8. public interface ServletContextListener extends EventListener public abstract void contextInitialized(ServletContextEvent servletcontextevent); public abstract void contextDestroyed(ServletContextEvent servletcontextevent);而且它是继承了EventListener这个接口的,打开这个接口的代码让我大吃一惊,里面没有方法啥都没有: 1. packagejava.util;2. 3. 4. publicinterfaceEventListener5. 6. package java.util;public interface EventListener而且还是java.util包下的,并不是spring之中的东西。 这样找了之后没有找到,往回退到ContextLoaderListener这个类的方法上,contextInitialized方法是用来初始化上下文的:1. publicvoidcontextInitialized(ServletContextEventevent)2. 3. contextLoader=createContextLoader();4. contextLoader.initWebApplicationContext(event.getServletContext();5. public void contextInitialized(ServletContextEvent event) contextLoader = createContextLoader(); contextLoader.initWebApplicationContext(event.getServletContext(); 方法中有个createContextLoader方法: 1. protectedContextLoadercreateContextLoader()2. 3. returnnewContextLoader();4. protected ContextLoader createContextLoader() return new ContextLoader(); 这个方法返回了一个ContextLoader实例,进入到ContextLoader类中,按ctrl+f来寻找contextConfigLocation,这时没有出现电脑的咚的声音,找到了它: 1. protectedWebApplicationContextcreateWebApplicationContext(ServletContextservletContext,ApplicationContextparent)2. throwsBeansException3. 4. ClasscontextClass=determineContextClass(servletContext);5. if(!(org.springframework.web.context.ConfigurableWebApplicationContext.class).isAssignableFrom(contextClass)6. 7. thrownewApplicationContextException(Customcontextclass+contextClass.getName()+isnotoftype+(org.springframework.web.context.ConfigurableWebApplicationContext.class).getName()+);8. else9. 10. ConfigurableWebApplicationContextwac=(ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);11. wac.setParent(parent);12. wac.setServletContext(servletContext);13. wac.setConfigLocation(servletContext.getInitParameter(contextConfigLocation);14. customizeContext(servletContext,wac);15. wac.refresh();16. returnwac;17. 18. protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent) throws BeansException Class contextClass = determineContextClass(servletContext); if(!(org.springframework.web.context.ConfigurableWebApplicationContext.class).isAssignableFrom(contextClass) throw new ApplicationContextException(Custom context class + contextClass.getName() + is not of type + (org.springframework.web.context.ConfigurableWebApplicationContext.class).getName() + ); else ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass); wac.setParent(parent); wac.setServletContext(servletContext); wac.setConfigLocation(servletContext.getInitParameter(contextConfigLocation); customizeContext(servletContext, wac); wac.refresh(); return wac; 通过代码,ConfigurableWebApplicationContext设置了从servletContext获取到的参数的值,再进入ConfigurableWebApplicationContext的代码中,它只是一个接口,进入StaticWebApplicationContext的setConfigLocation方法: 1. publicvoidsetConfigLocation(StringconfigLocation)2. 3. if(configLocation!=null)4. thrownewUnsupportedOperationException(StaticWebApplicationContextdoesnotsupportconfiglocations);5. else6. return;7. public void setConfigLocation(String configLocation) if(configLocation != null) throw new UnsupportedOperationException(StaticWebApplicationContext does not support config locations); else return; 这个方法中很奇怪,当参数不为空就抛出异常,查看spring的文档:TheStaticWebApplicationContextclass does not support this method.说是此类不支持这个方法,这下子又卡住了。又要退回去,看这句: 1. ConfigurableWebApplicationContextwac=(ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);ConfigurableWebApplica

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论