springMVC源码分析 从DispatcherServlet说起
来源:互联网 发布:linux 红旗 价钱 编辑:程序博客网 时间:2024/06/05 15:59
1.SpringMVC的Controller能够接受请求,是因为使用了DispatcherServlet作为所有请求的入口,事先要把这个Servlet配置到web.xml,并且把想走SpringMVC的请求的url(用通配符方式比如*.json)也配置到web.xml
2.如下就是doDispatch方法。
先加载bean
然后执行切面前置方法: 先执行preHandle,如果有preHandle失败的,就把失败的这个切面之前的已经成功的切面,按倒序逐个执行一下afterCompletion方法,然后就return了。
然后执行handle方法,这里面就会通过反射调用到打了RequestMapping注解的你的业务方法了。
然后执行切面后置方法。当然了,要按照倒序执行所有切面。
然后执行afterCompletion。(所以说不管成功失败都会执行这个)
/** * Process the actual dispatching to the handler. * <p>The handler will be obtained by applying the servlet's HandlerMappings in order. * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters * to find the first that supports the handler class. * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers * themselves to decide which methods are acceptable. * @param request current HTTP request * @param response current HTTP response * @throws Exception in case of any kind of processing failure */protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;int interceptorIndex = -1;try {ModelAndView mv;boolean errorView = false;try {processedRequest = checkMultipart(request);// Determine handler for the current request.mappedHandler = getHandler(processedRequest, false);if (mappedHandler == null || mappedHandler.getHandler() == null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request.HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (logger.isDebugEnabled()) {String requestUri = urlPathHelper.getRequestUri(request);logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);}if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}// Apply preHandle methods of registered interceptors.HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();if (interceptors != null) {for (int i = 0; i < interceptors.length; i++) {HandlerInterceptor interceptor = interceptors[i];if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);return;}interceptorIndex = i;}}// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// Do we need view name translation?if (mv != null && !mv.hasView()) {mv.setViewName(getDefaultViewName(request));}// Apply postHandle methods of registered interceptors.if (interceptors != null) {for (int i = interceptors.length - 1; i >= 0; i--) {HandlerInterceptor interceptor = interceptors[i];interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);}}}catch (ModelAndViewDefiningException ex) {logger.debug("ModelAndViewDefiningException encountered", ex);mv = ex.getModelAndView();}catch (Exception ex) {Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);mv = processHandlerException(processedRequest, response, handler, ex);errorView = (mv != null);}// Did the handler return a view to render?if (mv != null && !mv.wasCleared()) {render(mv, processedRequest, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}else {if (logger.isDebugEnabled()) {logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +"': assuming HandlerAdapter completed request handling");}}// Trigger after-completion for successful outcome.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);}catch (Exception ex) {// Trigger after-completion for thrown exception.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);throw ex;}catch (Error err) {ServletException ex = new NestedServletException("Handler processing failed", err);// Trigger after-completion for thrown exception.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);throw ex;}finally {// Clean up any resources used by a multipart request.if (processedRequest != request) {cleanupMultipart(processedRequest);}}}
3.如下方法是getHandle,其实就是加载一个bean的核心方法:
如果不是懒加载,则所有bean会在容器启动时就加载好了。
如果是懒加载,则到这里可能还没有加载,需要加载一下。
如果传进来的是一个bean名字,那就加载之。调用AbstractBeanFactory#doGetBean
如果没实例化过,可能调用的是CglibSubclassingInstantiationStrategy,利用反射实例化bean
/** * Register the specified handler for the given URL path. * @param urlPath the URL the bean should be mapped to * @param handler the handler instance or handler bean name String * (a bean name will automatically be resolved into the corresponding handler bean) * @throws BeansException if the handler couldn't be registered * @throws IllegalStateException if there is a conflicting handler registered */protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {Assert.notNull(urlPath, "URL path must not be null");Assert.notNull(handler, "Handler object must not be null");Object resolvedHandler = handler;// Eagerly resolve handler if referencing singleton via name.if (!this.lazyInitHandlers && handler instanceof String) {String handlerName = (String) handler;if (getApplicationContext().isSingleton(handlerName)) {resolvedHandler = getApplicationContext().getBean(handlerName);}}Object mappedHandler = this.handlerMap.get(urlPath);if (mappedHandler != null) {if (mappedHandler != resolvedHandler) {throw new IllegalStateException("Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");}}else {if (urlPath.equals("/")) {if (logger.isInfoEnabled()) {logger.info("Root mapping to " + getHandlerDescription(handler));}setRootHandler(resolvedHandler);}else if (urlPath.equals("/*")) {if (logger.isInfoEnabled()) {logger.info("Default mapping to " + getHandlerDescription(handler));}setDefaultHandler(resolvedHandler);}else {this.handlerMap.put(urlPath, resolvedHandler);if (logger.isInfoEnabled()) {logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));}}}}
0 0
- springMVC源码分析 从DispatcherServlet说起
- Spring Framework源码(九):SpringMVC之从DispatcherServlet说起
- SpringMVC源码分析(一)从配置文件说起
- SpringMVC源码分析(二)从框架设计说起
- SpringMVC源码分析 DispatcherServlet请求处理过程
- SpringMVC源码分析(一)之DispatcherServlet
- SpringMVC DispatcherServlet执行流程及源码分析
- SpringMVC提高篇(四):从Servlet到DispatcherServlet源码分析
- slab源码分析--从slab初始化说起
- WindowManager源码分析-从悬浮窗说起
- SpringMVC源码深度分析DispatcherServlet核心的控制器(初始化)
- springMVC源码分析--容器初始化(二)DispatcherServlet
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
- springMVC源码分析--DispatcherServlet请求获取及处理
- SpringMVC源码分析(3)DispatcherServlet的请求处理流程
- springMVC源码分析--容器初始化(二)DispatcherServlet
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
- springMVC源码分析--DispatcherServlet请求获取及处理
- java实现zip的压缩和解压(支持中文文件名)
- CentOS7安装开源跳板机(堡垒机)
- IIS站点在重新启动的时候,显示提示信息
- snprintf函数
- Android检查设备是否可以访问互联网,判断Internet连接,测试网络请求,解析域名
- springMVC源码分析 从DispatcherServlet说起
- 大规模数据分析-HW2 part2 GraphLigte相关操作
- java.util.ConcurrentModificationException 解决办法
- 为什么重写equals方法要重写hashCode
- D3介绍
- 深度学习中Dropout优化的原理分析
- crc8 c语言源程序
- 15. Hibernate_基于主键映射的1-1关联关系
- MapReduce简介