*:first-child {
margin-top: 0 !important;
}

body>*:last-child {
margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
font-size: inherit;
}

h1 {
font-size: 28px;
color: #000;
}

h2 {
font-size: 24px;
border-bottom: 1px solid #ccc;
color: #000;
}

h3 {
font-size: 18px;
}

h4 {
font-size: 16px;
}

h5 {
font-size: 14px;
}

h6 {
color: #777;
font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
color: #4183C4;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
padding-left: 30px;
}

ul li > :first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}

dl {
padding: 0;
}

dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}

dl dt:first-child {
padding: 0;
}

dl dt>:first-child {
margin-top: 0px;
}

dl dt>:last-child {
margin-bottom: 0px;
}

dl dd {
margin: 0 0 15px;
padding: 0 15px;
}

dl dd>:first-child {
margin-top: 0px;
}

dl dd>:last-child {
margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}

pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}

pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}

pre code, pre tt {
background-color: transparent;
border: none;
}

kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}

blockquote>:first-child {
margin-top: 0px;
}

blockquote>:last-child {
margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}

/* IMAGES
=============================================================================*/

img {
max-width: 100%
}
-->

Spring MVC中的HandlerMapping与HandlerAdapter的关系

最近和同事讨论一个spring mvc的问题,问到HandlerMapping与HandlerAdapter有什么关系?虽然使用spring mvc时间也不短,但是瞬间能起来的只有两个关键词:

  • @RequestMapping,这个经常用的,每个 Controller下面的action方法上一般都会定义一个特有的url路径。当HTTP请求请求发送到服务端后会根据url来查找应该执行哪个Controller下面的哪个action,我理解为url与java代码的一个路由关系。
    @RequestMapping(value = "/bss/{priceId}", method = RequestMethod.GET)
public ValueResult<ProductPrice> getProductPrice(HttpServletRequest request,
@Min(value = 1,message = "priceId不合法")
@PathVariable final long priceId) { //省略
}
  • HandlerInterceptor,这个也是经常用的,做请求拦截时比较常用。

上面两个关键词尽管与问题有所关联,但很明显不是主要的,核心还是这两个接口都是做什么的,两者之间有什么互动。于是我们可以从一个请求开始调试下spring mvc的调用过程,以此来分析它们的作用以及关系。

Spring MVC配置

两个配置文件:

  • 应用程序级别的applicationContext.xml,一般加载非web的配置,比如数据库配置,redis配置等等。
  • web级别的mvc-dispatcher-servlet.xml,这里专注mvc的配置。
XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setConfigLocations(new String[]{"classpath*:applicationContext.xml","classpath*:spring/mvc-dispatcher-servlet.xml"}); ServletContextHandler spingMvcHandler = new ServletContextHandler();
spingMvcHandler.setContextPath(appConfig.getContext());
spingMvcHandler.addEventListener(new ContextLoaderListener(context));
spingMvcHandler.addServlet(new ServletHolder(new DispatcherServlet(context)), "/*");

这里引用《张开涛》同学的图来说明上面两个配置的作用以及关系:

两个核心类

  • ContextLoaderListener
    这的作用主要是在启动web容器时加载ApplicationContext的信息,用来创建ROOT ApplicationContext的,可以接收XML类型的,比如XmlWebApplicationContext,它将从XML配置文件中加载配置信息。

这篇它不是重点至此主止。

  • DispatcherServlet
    也叫前端控制器,它是Spring MVC的统一访问入口,负责职责的分配以及工作调试,由于它的功能复杂这里只关心与HandlerMapping与HandlerAdaper的内容。下面是初始化的功能,其中有初始化HandlerMapping与HandlerAdaper。
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
} /**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
//其它初始化
initHandlerMappings(context);
initHandlerAdapters(context);
//其它初始化
}

initHandlerMappings,主要是调用BeanFactoryUtils.beansOfTypeIncludingAncestors,其中一种非常重要的HandlerMapping是RequestMappingHandlerMapping,我们通过在Controller方面上加@RequestMapping注释来配合使用,系统会将我们配置的RequestMapping信息注册到其中,详细数据参数此图:mappingRegistry中包含了所有的请求路由信息。

代码如下:

private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null; if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
//不加载全部的先省略 //加载默认的逻辑先省略
}

DispatcherServlet核心方法:doDispatch,三个重要步骤:

  • getHandler,获取页面处理器,通俗点就是获取由哪个Controller来执行,包含方法信息以及方法参数等信息。
  • getHandlerAdapter,获取HandlerAdapter,它包含一个handle方法,负责调用真实的页面处理器进行请求处理并返回一个ModelAndView。HandlerAdpter里面有一些常见的处理,比如消息转移,参数处理等,详见此图:里面的argumentResolvers可以用来处理请求的参数,messageConverts是作消息转换等等。

  • HandlerAdapter.handle,执行真实页面处理器的处理请求。

请求时序图(只关注HandlerMapping与HandlerAdapter)

doDispath获取页面处理器,然后根据页面处理器获取对应的HanlerAdapter,最后由HanlerAdaper来调用页面处理器的方法。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//初始化省略 try {
ModelAndView mv = null;
Exception dispatchException = null; try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request); // Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
} // Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); //其它逻辑省略 // Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //其它逻辑省略
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
//异常逻辑省略
}

具体的调用逻辑比较复杂,只选取与HandlerMapping与HandlerAdaper的部分,时序图图如下:

引用

http://jinnianshilongnian.iteye.com/blog/1602617

Spring MVC中的HandlerMapping与HandlerAdapter的更多相关文章

  1. Spring MVC 中的基于注解的 Controller【转】

    原文地址:http://my.oschina.net/abian/blog/128028 终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 H ...

  2. Spring MVC中基于注解的 Controller

         终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法以响 ...

  3. spring mvc中DispatcherServlet如何得到ModelAndView的

    首先看下面这种张图,这张图说明了spring mvc整体的流程. 本文讲的就是如何从DispatcherServlet中得到ModerAndView的过程. 首先看DispatherServlet这个 ...

  4. Spring MVC 中的基于注解的 Controller(转载)

           终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法 ...

  5. Spring MVC中处理静态资源的多种方法

    处理静态资源,我想这可能是框架搭建完成之后Web开发的”头等大事“了. 因为一个网站的显示肯定会依赖各种资源:脚本.图片等,那么问题来了,如何在页面中请求这些静态资源呢? 还记得Spring MVC中 ...

  6. Spring MVC中的Controller是Serlvet吗?

    1. Controller不是Servlet DispatcherServler是Spring MVC中的唯一Servlet,(这点可通过查看FrameworkServlet的子类确认) Servle ...

  7. Spring MVC组件之HandlerMapping

    Spring MVC组件之HandlerMapping HandlerMapping概述 HandlerMapping组件的作用解析一个个Request请求,并找到相应处理这个Request的Hand ...

  8. Spring mvc中@RequestMapping 6个基本用法

    Spring mvc中@RequestMapping 6个基本用法 spring mvc中的@RequestMapping的用法.  1)最基本的,方法级别上应用,例如: Java代码 @Reques ...

  9. spring mvc中使用freemark的一点心得

    参考文档: FreeMarker标签与使用 连接http://blog.csdn.net/nengyu/article/details/6829244 freemarker学习笔记--指令参考: ht ...

随机推荐

  1. 用javascript把扑克牌理理顺!

    打扑克的人都知道,比如斗地主! 我们一般都会按照顺序把随机摸过来的牌从小到大的顺序在手上理整齐(记得小时候打牌两副牌手都抓不过来),这篇随笔就是想通过实现这个功能来熟悉下js中排序数组等相关知识. 用 ...

  2. [译]Java 设计模式之工厂

    (文章翻译自Java Design Pattern: Factory) 1.Java工厂模式的来历 工厂设计模式用于创建基于不同参数的对象.下面的例子就是在一个工厂里创建一个人.如果我们向工厂要一个b ...

  3. mysql支持的数据类型及其测试

    原文:mysql支持的数据类型及其测试 1.基础知识 1.1如何来查看mysql的帮助手册 ?int Help float; 1.2创建表的规则 CREATE TABLE [IF NOT EXISTS ...

  4. IEnumerable<T>转换为IList<SelectListItem>

    扩展方法IEnumerable<T>转换为IList<SelectListItem> ,提供@Html.DropDownList使用   由于在MVC中经常会使用到@Html. ...

  5. 远程连接mysql速度慢的解决方法

    最近在公司内部连mysql速度非常慢,一直还以为公司的网络有问题,后经查发现出现这种问题的主要原因是mysql默认开启了DNS的反向解析功能,连接时反向解析计算机名称时耗时严重,导致连接超慢.解决方法 ...

  6. 缓存,spring

    applicationcontext.xml xmlns:cache="http://www.springframework.org/schema/cache" xsi:schem ...

  7. JavaScript里的依赖注入

    JavaScript里的依赖注入 我喜欢引用这句话,“程序是对复杂性的管理”.计算机世界是一个巨大的抽象建筑群.我们简单的包装一些东西然后发布新工具,周而复始.现在思考下,你所使用的语言包括的一些内建 ...

  8. Linq无聊练习系列8---开放式并发事务,null和 DateTime,string操作练习

    /*********************开放式并发事务,null和 DateTime,string操作练习**********************************/ //所谓并发,就是 ...

  9. 正则表达式(c#)

      只能输入数字:"^[0-9]*$". 只能输入n位的数字:"^\d{n}$". 只能输入至少n位的数字:"^\d{n,}$". 只能输入 ...

  10. 一、SOAP简单对象访问协议讲解

    一.SOAP简单对象访问协议讲解 今天给大家讲讲SOAP的基本知识.下节给大家演示创建基于SOAP的Web Service. 更多SOA文章请查看我的个人博客. 首先,让我来简单一下入门SOAP所需的 ...