浅谈sping和spingmvc

sping与spingmvc的关系:

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。其实Spring可以说是一个管理bean的ioc容器,也可以说是包括很多开源项目的总称,spring mvc是其中一个开源项目,作为Spring的一个子项目,与Spring的IoC容器配合起来更简便。http请求一到,由容器(如:tomact)解析http搞成一个request,通过映射关系(路径,方法,参数啊)被spring mvc一个分发器去找到可以处理这个请求的bean,那tomcat里面就由spring管理bean的一个池子(bean容器)里面找到,处理完了就把响应返回回去。springmvc的controller里面有个注解service,spring的ioc功能就可以把这个sercice插进去(反射)。其实可以把spring看成是一个工具箱,里面有各种工具,springmvc只是其中的一把扳手。


MVC与WEB应用

MVC即Model-View-Control(MVC)框架:

Model:

模型应该包含由视图显示的数据.在J2EE Web应用中,数据通常应该由普通的javabean组成.一旦一个控制器选择了视图,模型就要包含视图相应的数据.模型本身不应该进一步的访问数据,也不应该和业务对象相联系.

模型要解决的问题包括:

l          封装要显示的数据

l          我不认为模型要依赖于特定的框架

l          不一定非得是javabean

View:

视图负责显示出模型包含的信息,视图不必了解控制器或是底层业务对象的具体实现

视图要解决的问题包括:

l          在显示给定数据模型的情况下显示内容

l          不应该包含有业务逻辑

l          可能需要执行显示逻辑,比如颜色交替的显示某个数组的各行

l          视图最好不处理验证的错误,数据的验证应该在由其他组件完成

l          视图不应该处理参数,参数应该交由控制器集中处理

Control:

控制器就好像MVC里的中枢神经,它也许会需要一些助手来帮助它比如解析视图,解析参数等.控制器可以访问到业务对象或者是它的代理是很重要的,比如Struts里的Action.

控制器要解决的问题包括:

l          检查和抽取请求参数

l          调用业务对象,传递从请求中获取的参数

l          创建模型,视图讲显示对应的模型

l          选择一个合适的视图发送给客户端

l          控制器有时不会只有一个

Spring MVC Framework的目标

上面说了一些MVC的原理,以及现在主流框架的一些问题,现在来看Spring是如何处理的. Spring MVC框架根据不同的角色定义了很多接口,但是它最大的问题也是依赖于Servlet API

Spring MVC Framework有这样一些特点:

l          它是基于组件技术的.全部的应用对象,无论控制器和视图,还是业务对象之类的都是java组件.并且和Spring提供的其他基础结构紧密集成.

l          不依赖于Servlet API(目标虽是如此,但是在实现的时候确实是依赖于Servlet的)

l          可以任意使用各种视图技术,而不仅仅局限于JSP

l          支持各种请求资源的映射策略

l          它应是易于扩展的

Spring 易于使用吗?我不这么觉得,尤其是它的配置文件。各种业务逻辑,基础设施也许会拥挤在一个配置文件里.而如事务处理这些基础设施应该是由容器管理而不是开发人员,就算把这些分开到几个配置文件里,逻辑上虽然清晰了,但是基础设置却还是暴露在外边。

Spring易于测试吗?对Spring进行单元测试很容易,测试起来很方便

l          应该在多个层次上提供接口

Spring提供了很多接口,而几乎每个接口都有默认的抽象实现,每个抽象实现都有一些具体实现,所以在可扩展性这点上Spring无疑是很优秀的

l          框架内部和框架外部应该被区别对待

框架内部可以很复杂,但是使用起来一定要简单,Spring的内部比较麻烦,但是它很好的隐藏了这种复杂性,使用起来很舒服,比如设置一个bean的属性.仅仅是setPropertyValue(String propertyName, Object value)就完成,至于怎么去设置,Spring完全隐藏了这种复杂性


 Spring Web框架基本流程

知道了Spring MVC框架,现在来看看它的流程

Spring MVC Framework大至流程如下:

当web程序启动的时候,ContextLoaderServlet会把对应的配置文件信息读取出来,通过注射去初始化控制器DispatchServlet. 而当接受到一个HTTP请求的时候, DispatchServlet会让HandlerMapping去处理这个请求.HandlerMapping根据请求URL(不一定非要是URL,完全可以自定义,非常灵活)来选择一个Controller. 然后DispatchServlet会在调用选定的Controller的handlerRequest方法,并且在这个方法前后调用这个Controller的interceptor(假如有配置的话),然后返回一个视图和模型的集合ModelAndView.框架通过ViewResolver来解析视图并且返回一个View对象,最后调用View的render方法返回到客户端

DispatcherServlet

这是框架的控制器,是一个具体类,它通过运行时的上下文对象来初始化.控制器本身并不去控制流程,而只是是Controller的”控制器”,他只是把处理请求的责任委托给了对应的Controller.

 控制器继承自抽象基类FrameworkServlet,它的属性webApplicationContext就代表着这个web程序上下文,而这个上下文对象默认实现就是从一个XML文件读取配置信息(当然也可以是其他文件格式). WebApplicationContext其实是beans包的东西,这个包提供了这个Spring整个框架的基础结构,以后我会分析这个包的内容.但是现在仅仅需要知道WebApplicationContext代表一个web应用的上下文对象.

 现在来看看DispatchServlet是如何工作的:

DispatchServlet由于继承自抽象基类FrameworkServlet,而FrameworkServlet里的doGet(),doPost()方法里有调用serviceWrapper(),跳到serviceWrapper()里去看,结果发现它有把具体实现委托给了doService(request, response); 方法.所以现在已经很清楚了, DispatchServlet真正实现功能的是doService() 这个方法.特别的, FrameworkServlet的initFrameworkServlet()这个方法是控制器的初始化方法,用来初始化HandlerMappings之类的对象,这也是延迟到子类实现的.其实就是一个Template模式的实现.don’t call us, we will call u.总的看来,Spring就是通过这样来实现它的控制反转的:用框架来控制流程,而不是用户

 跳到doService()一看究竟,就会发现真正工作的又是另一个助手函数doDispatch(request, response),没办法,继续看下去,发现这样两行代码

HandlerExecutionChain mappedHandler = null;

         mappedHandler = getHandler(processedRequest, false);

看HandlerExecutionChain源码就发现它其实就是对Controller和它的Interceptors的进行了包装;

 getHandler()就是从HandlerMappings(这是一个List,存放的handlerMapping对象)中取出对应的handlerMapping对象, 每个HandlerMapping对象代表一个Controller和URL的映射(其实在运行的时候是一个HandlerExecutionChain和URL的映射,而HandlerExecutionChain对象其实就是对Controller和它interceptors的一个包装器,可以把HandlerMapping看成Controller和URL的映射).而这个HandlerMapping是通过配置文件在运行时注射进来的,一般是SimpleUrlHandlerMapping这个子类

 取得了HandlerMapping对象,继续向下看,发现:

                  if (mappedHandler.getInterceptors() != null) {

                                               for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {

                                                        HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];

                                                        if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {

                                                                 triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

                                                                 return;

                                                        }

                                                        interceptorIndex = i;

                                               }

                                     }

这里就是在调用Controller的拦截器,原理就是这句了:

         interceptor.preHandle(processedRequest, response, mappedHandler.getHandler(), mv);

preHandle方法传入了mappedHandler.getHandler()这个参数来实现递归调用!而interceptor.postHandle方法如此一般.只不过这个方法是在handleRequest方法后调用

 继续看下去:

         HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

发现Controller的handleRequest真正的操作又被代理给了HandlerAdapter的handle方法,并且返回一个ModelAndView,我想这里增加一层的意义应该是为了解除Controller和DispatchServlet的耦合吧.

 接着就很简单了,调用render()方法,在这个方法里面由ViewResoler解析出视图名,再调用视图对象的render方法把合适的视图展现给用户

 到此,控制器的流程就OVER了。

HandlerMapping

通过使用HandlerMapping,控制器可以用URL和某一个Controller进行标准的映射,而实现URL映射的具体子类的UrlHandlerMapping.

Spring还允许我们自定义映射,比如通过Session,cookie或者用户状态来映射.而这一切仅仅只需要实现HandlerMapping接口而已.不过URL映射已经能满足大部分的要求

Controller

Controller 类似Structs的Action, Controller接口只有一个方法handleRequest(),放回一个ModelAndView对象,如同设计目标所说的那样,每个Controller都是一个java组件,所以它可以在上下文环境中任意配置,组件属性都会在初始化的时候被配置.Spring自己提供了几个具体的实现.方便我们使用

ViewResolver

Controller通常返回包含视图名字而不是视图对象的ModelAndView对象.从而彻底的解除了控制器和视图之间的耦合关系,并且在这里还可以提供国际化的支持.

在你的配置文件中你可以:

welcomeView.class = org.springframework.web.servlet.view. InternalResourceView

welcomeView.url=/welcome.jsp

也可以

welcomeView.class = org.springframework.web.servlet.view.xslt. XsltView

welcomeView.url=/xslt/default.xslt

 

View

这也是一个java组件,它不做任何请求处理或是业务逻辑,它仅仅获取模型传递的数据,并把数据显示出来.它里面的 render方法按照如下流程工作:

l          设置模型的数据到request作用域

l          取得视图的URL

l          转发到对应的URL




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值