zoukankan      html  css  js  c++  java
  • servlet和Spring的DispatcherServlet详解

    Servlet是什么

    1. Servlet是服务器端运行的一个程序,是一个被编译好的Java类。它不是框架等。

    2. Web容器的启动,需要依赖Servlet。当web服务器开始执行时,servlet类就被初始化

    3. 当用户通过浏览器访问的时候,会输入URI,这个时候,web服务器就通过Servlet来分发请求执行不同的内容。

    Servlet是有一个Jar包,里面包含了一些Servlet的相关设计和细节。

    Spring的DispatcherServlet

    Spring主要通过DispatcherServlet实现了Servlet。DispatcherServlet最上层也是继承的是HttpServlet这个类。

    @Override
    	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		if (logger.isDebugEnabled()) {
    			String requestUri = urlPathHelper.getRequestUri(request);
    			logger.debug("DispatcherServlet with name '" + getServletName() + "' processing " + request.getMethod() +
    					" request for [" + requestUri + "]");
    		}
    
    		// Keep a snapshot of the request attributes in case of an include,
    		// to be able to restore the original attributes after the include.
    		Map<String, Object> attributesSnapshot = null;
    		if (WebUtils.isIncludeRequest(request)) {
    			logger.debug("Taking snapshot of request attributes before include");
    			attributesSnapshot = new HashMap<String, Object>();
    			Enumeration<?> attrNames = request.getAttributeNames();
    			while (attrNames.hasMoreElements()) {
    				String attrName = (String) attrNames.nextElement();
    				if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
    					attributesSnapshot.put(attrName, request.getAttribute(attrName));
    				}
    			}
    		}
    
    		// Make framework objects available to handlers and view objects.
    		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
    		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
    		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
    		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
    
    		FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
    		if (inputFlashMap != null) {
    			request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
    		}
    		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
    		request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    
    		try {
    			doDispatch(request, response); //这边最终也是调用了doDispatch方法,该方法主要用来处理SPring框架的具体业务分发逻辑。
    		}
    		finally {
    			// Restore the original attribute snapshot, in case of an include.
    			if (attributesSnapshot != null) {
    				restoreAttributesAfterInclude(request, attributesSnapshot);
    			}
    		}
    	}
            
            //Spring框架最终的分发都是通过该方法的
    	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;
    					}
    				}
    
    				// 这里是处理前置拦截器
    				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;
    					}
    				}
    
    				//处理最终的Action逻辑
    				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    				// Do we need view name translation?
    				if (mv != null && !mv.hasView()) {
    					mv.setViewName(getDefaultViewName(request));
    				}
    
                                    //处理后置拦截器
    				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);
    			}
    		}
    	}
  • 相关阅读:
    Jenkins + GitLab 通过 Webhook 自动触发构建爬坑记录
    Spring Cloud Eureka 学习记录
    [源码分析]ArrayList
    一个简单的统计问题(解决方案:Trie树)
    Redis基本数据类型命令汇总
    Redis的Pub/Sub客户端实现
    从ByteBuffer中解析整数
    学习T-io框架,从写一个Redis客户端开始
    折腾一下WebSocket的ArrayBuffer传输方式
    Ubuntu安装docker笔记
  • 原文地址:https://www.cnblogs.com/panxuejun/p/7096587.html
Copyright © 2011-2022 走看看