handleradapter,SpringMVC4中RequestMappingHandlerAdapter为什么被创建了两个
handleradapter,SpringMVC4中RequestMappingHandlerAdapter为什么被创建了两个详细介绍
本文目录一览: handleradapter怎么读
handler-adapter 的读音
handler 单词音标:
英[?h?ndl?(r)] 美[?h?ndl?]
adapter 单词音标:
英[?'d?pt?] 美[??d?pt?]
Netty:ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter
服务端和客户端通讯,我们通常要绑定一个handler(Netty:Bootstrap的handler和childHandler)进行通道的监听,当收到数据时就会触发某个事件,从而进行进一步的处理。
channelReadComplete
channelRead执行后触发
exceptionCaught
出错是会触发,做一些错误处理
ChannelOutboundHandlerAdapter,看到了out,表示出去的动作,监听自己的IO操作,比如connect,bind等,在重写这个Adapter的方法时,记得执行super.xxxx,否则动作无法执行。
bind
服务端执行bind时,会进入到这里,我们可以在bind前及bind后做一些操作
connect
客户端执行connect连接服务端时进入
HandlerInterceptor处理器拦截器机制全解
所以说,很多功能其实Filter和HandlerInterceptor都能做,具体看你怎么选了,如果使用Spring MVC框架,那么建议使用HandlerInterceptor吧,它可以类似于普通bean直接注册到Spring容器中被管理。
关于Filter过滤器,我们在此前讲Java Web的时候就讲过了,在此不再赘述,我们主要讲Spring MVC的HandlerInterceptor。
HandlerMapping在根据request查找Handler时,最终会返回一个HandlerExecutionChain对象,字面翻译就是处理器执行链对象,其内部包含了一个Handler和可以应用于该Handler的HandlerInterceptor执行链。
所有的HandlerMapping实现都支持查找HandlerInterceptor链,想要自定义Handler的拦截器,必须实现org.springframework.web.servlet.HandlerInterceptor接口,此接口中有三个抽象方法,用于灵活的实现拦截器的功能:
preHandle方法返回boolean类型的值,可以使用此方法中断或继续处理执行链。当当前此方法返回true时,拦截器链将继续先后执行,即继续执行后续拦截器的preHandle方法。当当前某个拦截器的preHandle方法返回false 时,DispatcherServlet 会假定拦截器本身已处理完毕请求(例如,已经渲染了合适的视图),此时将尝试直接倒序执行此前已放行的拦截器链的afterCompletion 方法,随后retrun结束处理,不会继续执行执行链中的后续其他拦截器和Handler实际处理程序(业务逻辑)以及后续其他流程。
对于采用了@ResponseBody注解或者返回ResponseEntity的方法,postHandle后处理不太有效,因为在Handler执行成功时响应的数据(比如JSON数据)已经被写入response并且已被提交,并且是在postHandle方法被执行之前进行的!此时对于response的任何修改(比如添加额外的头部信息)都为时已晚。对于这种情况,我们可以实现ResponseBodyAdvice接口并且声明为ControllerAdvice,或者直接在RequestMappingHandlerAdapter中配置。
我们需要编写一个实现了拦截器接口HandlerInterceptor的类
我们可以为某个拦截器设置拦截或者不拦截的路径,拦截器的路径也可以使用通配符,如下:
基于Java的配置很简单。编写配置类并继承WebMvcConfigurer类,重写其中的方法 addInterceptors,并且将这个配置类交给Spring管理!
基于XML的配置如下!
有一个Controller:
我们测试访问/a/bbb/c和/a/b/c,发现请求都会被拦截:
而访问/b则不会!
我们可以配置多个拦截器并应用到一个请求中!
多个拦截器默认情况下是按照在XML或者JavaConfig中的定义的顺序执行的,如果想要指定Order排序,那么需要自己创建InterceptorRegistration。
我们将MyInterceptor1类复制一份并改为MyInterceptor2配置到拦截器链中:
我们测试访问/a/bbb/c,结果如下:
正常情况下,preHandle方法在拦截器链中会顺序执行,而postHandle和afterCompletion方法则会倒序执行。
如果我们在第二个拦截器中preHandle返回false,也就是不放行,对请求进行拦截,那么访问/a/bbb/c结果如下:
可以看到,Controller方法并没有被执行,拦截器链的postHandle方法也不会被执行,并且只执行了MyInterceptor1的afterCompletion方法。
实际上,如果某个拦截器不放行,那么后续的拦截器的preHandle预处理方法、Handler处理器、所有的postHandle后处理方法都不会被执行,并且在最后只会对此前放行成功的拦截器倒序执行afterCompletion方法。
拦截器的preHandle、postHandle、afterCompletion方法均支持forward、include、redirect转发到其他路径或者动态资源!但是要注意在跳转前如果响应已提交,那么可能会造成异常(比如response写了数据并且执行了PrintWriter或者OutputStream的flush或者close方法,比如调用了sendError、sendRedirect方法,那么将会抛出一个IllegalStateException,并且操作不会完成)!
基于这个特性,我们可以校验用户是否登陆,如果没有登陆,那么直接跳转到登录页面即可!
再次访问/a/bbb/c,结果如下,确实转发到了index.jsp中
SpringMVC 主要组件说明
1、前端控制器 DispatcherServlet(不需要开发,由框架提供【核心】)
DispatcherServlet 是 Spring MVC 的入口函数。接收请求,响应结果,相当于转发器,中央处理器。有了 DispatcherServlet ,可以大大减少其它组件之间的耦合度。
用户请求到达前端控制器,就相当于 mvc 模式中的 c,DispatcherServlet 是整个流程控制的中心,由它调用其它组件来处理用户的请求。
2、处理器映射器 HandlerMapping (不需要开发,由框架提供)
HandlerMapping 负责根据用户请求(URL),找到相应的 Handler 即处理器(Controller),SpringMVC 提供了不同映射器实现的不同映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、处理器适配器 HandlerAdapter (不需要开发,由框架提供)
按照特定规则(HandlerAdapter 要求的规则)去执行 Handler,通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行处理。
4、处理器 Handler (需要工程师开发)
Handler 是继 DispatcherServlet 前端控制器的后端控制器,在 DispatcherServlet 的控制下,Handler 对具体的用户请求进行处理。由于 Handler 涉及到具体的用户业务请求,所以一般情况下需要工程师根据业务需求来开发 Handler。
5、视图解析器 View Resolver (不需要开发,由框架提供)
作用:进行视图解析,根据逻辑视图名解析成真正的视图(View),View Resolver 负责将处理结果生成 View 视图。首先,根据逻辑视图名解析成物理视图名(即具体的页面地址),再生成 View 视图对象,最后对 View 进行渲染,将处理结果通过页面展示给用户。
Spring MVC 框架提供了很多的 View 视图类型,包括:jstlView、freemarkerView、pdfView 等。 一般情况下,需要通过页面标签或页面模版技术,将模型数据通过页面展示给用户,这需要由工程师根据业务需求开发具体的页面。
6、视图 View (需要工程师开发)
View 是一个接口,实现类才可以支持不同的View类型(jsp、freemarker、pdf...)
总结:处理器 Handler(也就是平常说的 Controller 控制器)以及视图层 View ,都是需要自行开发的。其他的一些组件,如:前端控制器 DispatcherServlet、处理器映射器 HandlerMapping、处理器适配器 HandlerAdapter 等都是由框架提供。
SpringMVC4中RequestMappingHandlerAdapter为什么被创建了两个
SpringMVC4中新增了UriComponentsContributor这个东东
解析annotation-driven时也会创建此组件的默认实例
所以你在写了
后又注入了RequestMappingHandlerAdapter
这时当然会出现两个,而且会默认使用解析
生成的
你要配置RequestMappingHandlerAdapter时写入
中就好了
另外,楼下的真是答非所问
前言 关于SpringMVC初始化ContextLoader中的XMLWebApplicationContext,以及DispatcherServlet初始化等等,这样的原理 已经有N多的前辈和牛人总结过了, 我就不在这里重复轮子了。~ 废话 Spring源码还是层次十分分明的,只要了解原理,相信看起来...
这个可能是因为你在springmvc配置文件中,同时配置了
和
RequestMappingHandlerAdapter的bean,所以最后springmvc上下文中就有了两个类型都为RequestMappingHandlerAdapter的bean,但两个不影响使用,因为它们其实是有优先级排序的(当DispatcherServlet初始化的时候会根据优先级排序)。在springmvc配置文件中,放在前面的优先级高。如果想改变自己添加的RequestMappingHandlerAdapter的bean的优先级,让它高。要么把它
后面;要么设置order属性,只要order属性小于Integer.MAX_VALUE,放的顺序就可以忽略,按order看优先级
spring mvc的工作流程是什么?
spring工作的流程
流程如下:
1、用户发起请求到前端控制器(DispatcherServlet),该控制器会过滤出哪些请求可以访问Servlet、哪些不能访问。就是url-pattern的作用,并且会加载springmvc.xml配置文件。
2、前端控制器会找到处理器映射器(HandlerMapping),通过HandlerMapping完成url到controller映射的组件,简单来说,就是将在springmvc.xml中配置的或者注解的url与对应的处理类找到并进行存储,用map
这样的方式来存储。
3、HandlerMapping有了映射关系,并且找到url对应的处理器,HandlerMapping就会将其处理器(Handler)返回,在返回前,会加上很多拦截器。
4、DispatcherServlet拿到Handler后,找到HandlerAdapter(处理器适配器),通过它来访问处理器,并执行处理器。
5、执行处理器
6、处理器会返回一个ModelAndView对象给HandlerAdapter
7、通过HandlerAdapter将ModelAndView对象返回给前端控制器(DispatcherServlet)
8、前端控制器请求视图解析器(ViewResolver)去进行视图解析,根据逻辑视图名解析成真正的视图(jsp),其实就是将ModelAndView对象中存放视图的名称进行查找,找到对应的页面形成视图对象
9、返回视图对象到前端控制器。
10、视图渲染,就是将ModelAndView对象中的数据放到request域中,用来让页面加载数据的。
11、通过第8步,通过名称找到了对应的页面,通过第10步,request域中有了所需要的数据,那么就能够进行视图渲染了。最后将其返回即可。
@RequestBody注解原理
从源码中可以看到,@RequestBody 用在方法参数上面,用来将请求参数绑定到request body中,通过 HttpMessageConverter 封装为具体的JavaBean。通俗点讲就是你在一个参数上加上该注解,spring就会将request body中的json/xml对象解析成该参数类型的Javabean对象。 作为RESTful开发中经常用到的注解,研究其原理有利于我们更好地理解并掌握它。 那么spring是如何做到这一点的呢?先来看DispatcherServlet。 作为springMVC处理请求的中央调度器,DispatcherServlet本身是一个servlet,所以我们看doService():
重点在doDispatch()方法,该方法先找到会找到合适的handler来处理当前请求:
HandlerAdapter是一个接口,具体处理方法在 RequestMappingHandlerAdapter 类中:
这里又调用了handleInternal()方法,RequestMappingHandlerAdapter重写了该方法: 进入该方法,
可以看到最终调用的都是invokeHandlerMethod()方法,此方法会处理@RequestMapping修饰的请求
进入该方法的 invocableMethod.invokeAndHandle(webRequest, mavContainer); ,来到ServletInvocableHandlerMethod,此类继承了InvocableHandlerMethod,可以处理请求的返回值。invokeAndHandle()方法:
重点在 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); ,通过请求调用并产生返回值。
getMethodArgumentValues() 方法的作用是获取方法参数,重点就在这里,
进入resolveArgument()方法,
@RequestBody修饰的参数会使用RequestResponseBodyMethodProcessor解析,
进入readWithMessageConverters()方法一路顺藤摸瓜,来到AbstractMessageConverterMethodArgumentResolver的readWithMessageConverters(),
可以看到使用文章开头提到的HttpMessageConverter解析参数并返回,而此处的HttpMessageConverter是在RequestMappingHandlerAdapter中设置解析器的时候添加到每个解析器中的。而json格式的数据使用AbstractJackson2HttpMessageConverter进行解析,内部使用jackson进行json数据的解析。
请求由DispatcherServlet处理,找到相应的HandlerAdapter进行处理,RequestMappingHandlerAdapter会处理@RequestMapping注解的请求,设置一系列参数解析器进行解析,如果参数使用@RequestBody注解,则使用RequestResponseBodyMethodProcessor进行解析,此参数解析器用HttpMessageConverter将HttpMessage封装为具体的JavaBean对象,json格式的数据使用AbstractJackson2HttpMessageConverter进行解析,内部使用jackson进行json数据的解析。
springmvc工作流程
springmvc工作流程:
1、 用户向服务端发送一次请求,这个请求会先到前端控制器DispatcherServlet(也叫中央控制器)。
2、DispatcherServlet接收到请求后会调用HandlerMapping处理器映射器。由此得知,该请求该由哪个Controller来处理(并未调用Controller,只是得知)。
3、DispatcherServlet调用HandlerAdapter处理器适配器,告诉处理器适配器应该要去执行哪个Controller。
4、HandlerAdapter处理器适配器去执行Controller并得到ModelAndView(数据和视图),并层层返回给DispatcherServlet。
5、DispatcherServlet将ModelAndView交给ViewReslover视图解析器解析,然后返回真正的视图。
6、DispatcherServlet将模型数据填充到视图中。
7、DispatcherServlet将结果响应给用户。
组件说明:
DispatcherServlet:前端控制器,也称为中央控制器,它是整个请求响应的控制中心,组件的调用由它统一调度。
HandlerMapping:处理器映射器,它根据用户访问的 URL 映射到对应的后端处理器 Handler。也就是说它知道处理用户请求的后端处理器,但是它并不执行后端处理器,而是将处理器告诉给中央处理器。
HandlerAdapter:处理器适配器,它调用后端处理器中的方法,返回逻辑视图 ModelAndView 对象。
ViewResolver:视图解析器,将 ModelAndView 逻辑视图解析为具体的视图(如 JSP)。
Handler:后端处理器,对用户具体请求进行处理,也就是我们编写的 Controller 类。
mvc模式中控制器如何控制页面的流转
1、用户发送请求至前端控制器DispatcherServlet。2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。3、处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。4、DispatcherServlet调用HandlerAdapter处理器适配器。5、HandlerAdapter经过适配调用具体的处理器。6、Controller执行完成返回ModelAndView。
第一次接触spring mvc怎么学习
Spring MVC属于SpringFrameWork的后续产品,它提供了构建 Web 应用程序的全功能 MVC 模块,与Struts2一样是一种优秀MVC框架,不同的是自Spring2.5引入了注解式controller及Spring 3以后的不断完善,使得采用Spring MVC框架开发结构清晰明了,效率大大提高。
注解式Spring MVC响应流程:
重要的接口和类的简单说明:
DispatcherServlet:前端控制器,用于接收请求。
HandlerMapping接口:用于处理请求的映射。
DefaultAnnotationHandlerMapping:HandlerMapping接口的实现,用于把一个URL映射到具体的Controller类上。
HandlerAdapter接口:用于处理请求的映射。
AnnotationMethodHandlerAdapter:HandlerAdapter接口的试下,用于把一个URL映射到对应Controller类的某个方法上。
ViewResolver接口:用于解析View。