zoukankan      html  css  js  c++  java
  • springMVC源码分析

    image

    1. 发起请求到前端控制器(DispatcherServlet)
    2. 前端控制器请求处理器映射器(HandlerMapping)查找Handler(可根据xml配置、注解进行查找)
    3. 处理器映射器(HandlerMapping)向前端控制器返回Handler
    4. 前端控制器调用处理器适配器(HandlerAdapter)执行Handler
    5. 处理器适配器(HandlerAdapter)去执行Handler
    6. Handler执行完,给适配器返回ModelAndView(Springmvc框架的一个底层对象)
    7. 处理器适配器(HandlerAdapter)向前端控制器返回ModelAndView
    8. 前端控制器(DispatcherServlet)请求视图解析器(ViewResolver)进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
    9. 视图解析器(ViewResolver)向前端控制器(DispatcherServlet)返回View
    10. 前端控制器进行视图渲染,即将模型数据(在ModelAndView对象中)填充到request域
    11. 前端控制器向用户响应结果
    pom依赖文件
          <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>4.2.4.RELEASE</version>
            </dependency>
            
            <dependency>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-catalina</artifactId>
                <version>7.0.78</version>
            </dependency>
    
    在web.xml配置文件
     <!-- springmvc 前端控制器  -->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器、适配器等等)
              若不配置,默认加载WEB-INF/servlet名称-servlet(springmvc-servlet.xml)
            -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <!--
            第一种:*.action,访问以.action三结尾,由DispatcherServlet进行解析
            第二种:/,所有访问的地址由DispatcherServlet进行解析,对静态文件的解析需要配置不让DispatcherServlet进行解析,
                    使用此种方式和实现RESTful风格的url
            第三种:/*,这样配置不对,使用这种配置,最终要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,
                    不能根据jsp页面找到handler,会报错
            -->
            <url-pattern>*.action</url-pattern>
        </servlet-mapping>
    

    springmvc.xml

     <!-- 配置Handler -->
        <bean id="itemsController" name="/queryItems.action" class="com.iot.ssm.controller.ItemsController"/>
    
    
    <!-- 处理器映射器
        将bean的name作为url进行查找,需要在配置Handler时指定beanname(就是url)
        所有的映射器都实现了HandlerMapping接口
         -->
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    
        <!-- 简单url映射-->
        <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <props>
                    <!-- 对 itemsController进行url映射-->
                    <prop key="/queryItems1.action">itemsController</prop>
                    <prop key="/queryItems2.action">itemsController</prop>
                </props>
            </property>
        </bean>
        
        
        <!-- 处理器适配器
         所有处理器适配器都实现了HandlerAdapter接口
         -->
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
        <!-- 另一个非注解的适配器-->
        <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
        
        <!-- 视图解析器
        解析jsp,默认使用jstl,classpath下要有jstl的包
        -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
    
    

    itemsController实现了Controller接口

    public interface Controller {
    
    	/**
    	 * @param request current HTTP request
    	 * @param response current HTTP response
    	 * @return a ModelAndView to render, or {@code null} if handled directly
    	 * @throws Exception in case of errors
    	 */
    	ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
    
    }

    进入DispatcherServlet的父类HttpServlet

    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
    
            HttpServletRequest  request;
            HttpServletResponse response;
    
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
            service(request, response);
    }
    
    //进入FrameworkServlet
    protected void service(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
    		if (HttpMethod.PATCH.matches(request.getMethod())) {
    			processRequest(request, response);
    		}
    		else {
    			super.service(request, response);
    		}
    	}
    	
    	//进入HttpServlet
    	protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
    
            String method = req.getMethod();
    
            if (method.equals(METHOD_GET)) {
                long lastModified = getLastModified(req);
                if (lastModified == -1) {
                    // servlet doesn't support if-modified-since, no reason
                    // to go through further expensive logic
                    doGet(req, resp);
              }
            }
            ...
                
        }
            
        //进入FrameworkServlet
        protected final void doGet(HttpServletRequest request, HttpServletResponse response)
    		throws ServletException, IOException {
    		processRequest(request, response);
    	}
    	
    	protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
                ...
    			doService(request, response);
    	}
    	
    	//进入DispatcherServlet
    	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	    ....
    		doDispatch(request, response);
        }
        
        protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		HttpServletRequest processedRequest = request;
    		HandlerExecutionChain mappedHandler = null;
    		boolean multipartRequestParsed = false;
    
    		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
    		try {
    			ModelAndView mv = null;
    			Exception dispatchException = null;
    
    			try {
    				processedRequest = checkMultipart(request);
    				multipartRequestParsed = (processedRequest != request);
    
    				mappedHandler = getHandler(processedRequest); //handlerMapping里去找handler,与拦截器一起被封装成 HandlerExecutionChain 
    				if (mappedHandler == null || mappedHandler.getHandler() == null) {
    					noHandlerFound(processedRequest, response); //没有找到handler会发404
    					return;
    				}
    
    				// Determine handler adapter for the current request.
    				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//适配器模式,统一handler
    
                    ...
                    
    				if (!mappedHandler.applyPreHandle(processedRequest, response)) {//拦截器前置处理
    					return;
    				}
    
    				mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //执行handler
    
    				if (asyncManager.isConcurrentHandlingStarted()) {
    					return;
    				}
    
    				applyDefaultViewName(processedRequest, mv); //mv没设view话根据request设
    				mappedHandler.applyPostHandle(processedRequest, response, mv); //拦截器后置处理
    			}
    			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);//根据mv写到view
    		}
    		...
    	}
    	
          
    
    寻找拦截器链
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    		for (HandlerMapping hm : this.handlerMappings) { //handlerMappings在bean里配置过了
    			HandlerExecutionChain handler = hm.getHandler(request); //根据请求获取拦截器
    			if (handler != null) {
    				return handler; //按照配置顺序,如果先找到了映射地址就返回了
    			}
    		}
    		return null;
    	}
    	
    	//进入AbstractHandlerMapping
    	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    		Object handler = getHandlerInternal(request);
    		if (handler == null) {
    			handler = getDefaultHandler();
    		}
    		if (handler == null) {
    			return null;
    		}
    		// Bean name or resolved handler?
    		if (handler instanceof String) {
    			String handlerName = (String) handler;
    			handler = getApplicationContext().getBean(handlerName);
    		}
    
    		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    		...
    		return executionChain;
    	}
    	
    	protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
    		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); //获得查询路径
    		Object handler = lookupHandler(lookupPath, request); //查询匹配的handler
    		if (handler == null) {
    			Object rawHandler = null;
    			if ("/".equals(lookupPath)) {
    				rawHandler = getRootHandler();
    			}
    			if (rawHandler == null) {
    				rawHandler = getDefaultHandler();//没配置返回空
    			}
    			if (rawHandler != null) {
    				if (rawHandler instanceof String) {
    					String handlerName = (String) rawHandler;
    					rawHandler = getApplicationContext().getBean(handlerName);
    				}
    				validateHandler(rawHandler, request);
    				handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
    			}
    		}
    		return handler;
    	}
    	
    	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
    		Object handler = this.handlerMap.get(urlPath); //直接匹配
    		if (handler != null) {
    			// Bean name or resolved handler?
    			if (handler instanceof String) {
    				String handlerName = (String) handler;
    				handler = getApplicationContext().getBean(handlerName);
    			}
    			validateHandler(handler, request);
    			return buildPathExposingHandler(handler, urlPath, urlPath, null);
    		}
            ...
    	}
    	
    	protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
    			String pathWithinMapping, Map<String, String> uriTemplateVariables) {
    
    		HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
    		chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping)); // 添加拦截器
    		...
    		return chain;
    	}
    	
    	
    	public HandlerExecutionChain(Object handler) { //创建拦截器链
    		this(handler, null);
    	}
    
    	public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) {
    		if (handler instanceof HandlerExecutionChain) {
    			HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
    			this.handler = originalChain.getHandler();
    			this.interceptorList = new ArrayList<HandlerInterceptor>();
    			CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
    			CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
    		}
    		else {
    			this.handler = handler;
    			this.interceptors = interceptors;
    		}
    	}
    	
    	
    	//执行拦截器
    	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		if (getInterceptors() != null) {
    			for (int i = 0; i < getInterceptors().length; i++) {
    				HandlerInterceptor interceptor = getInterceptors()[i];
    				if (!interceptor.preHandle(request, response, this.handler)) {
    					triggerAfterCompletion(request, response, null);
    					return false;
    				}
    				this.interceptorIndex = i;
    			}
    		}
    		return true;
    	}
    
    业务处理
    //获取adapter
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    		for (HandlerAdapter ha : this.handlerAdapters) {
    			if (ha.supports(handler)) {
    				return ha;
    			}
    		}
    		throw new ServletException("No adapter for handler [" + handler +
    				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    	}
    	
    	//比如 SimpleControllerHandlerAdapter
    	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    			throws Exception {
    		return ((Controller) handler).handleRequest(request, response); //执行业务逻辑
    	}
    	
    	
    	//进入自己的实现的Controller
    	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //返回ModelAndView
            ModelAndView modelAndView = new ModelAndView();
            //相当于request的setAttribute方法,在jsp页面中通过itemsList取数据
            modelAndView.addObject("xx", 1);
    
            //指定视图
            modelAndView.setViewName("/WEB-INF/jsp/xx.jsp");
    
            return modelAndView;
        }
    
    寻找视图
    	
    	private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) throws Exception {
    		if (mv != null && !mv.hasView()) {
    			mv.setViewName(getDefaultViewName(request));
    		}
    	}
    	
    	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
    			HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
    
    		boolean errorView = false;
    
            ...
    		// Did the handler return a view to render?
    		if (mv != null && !mv.wasCleared()) {
    			render(mv, request, response); //页面渲染
    			if (errorView) {
    				WebUtils.clearErrorRequestAttributes(request);
    			}
    		}
            ...
    		if (mappedHandler != null) {
    			mappedHandler.triggerAfterCompletion(request, response, null);
    		}
    	}
    	
    	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    		// Determine locale for request and apply it to the response.
    		Locale locale = this.localeResolver.resolveLocale(request);
    		response.setLocale(locale);
    
    		View view;
    		if (mv.isReference()) {  //string名称引用,beanFactory进行管理
    			view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
    		}
    		else {
    			view = mv.getView();
    			if (view == null) {
    				throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
    						"View object in servlet with name '" + getServletName() + "'");
    			}
    		}
    
    		view.render(mv.getModelInternal(), request, response);
    	}
    	
    	//进入AbstractView
    	public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    	    ...
    
    		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); //转成map
    		prepareResponse(request, response); //针对下载文件处理一下
    		renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
    	}
    	
    	//进入InternalResourceView
    	protected void renderMergedOutputModel(
    			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    		exposeModelAsRequestAttributes(model, request); //将kv放入request的属性里
    
    		// Expose helpers as request attributes, if any.
    		exposeHelpers(request);
    
    		// Determine the path for the request dispatcher.
    		String dispatcherPath = prepareForRendering(request, response);
    
    		RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath); //从tomcat获取转发器
    		...
    
    		// If already included or response already committed, perform include, else forward.
    		if (useInclude(request, response)) {
    			response.setContentType(getContentType());
    			rd.include(request, response);
    		}
    
    		else {
    			rd.forward(request, response);
    		}
    	}
  • 相关阅读:
    面向对象程序设计(JAVA) 第14周学习指导及要求
    面向对象程序设计(JAVA) 第13周学习指导及要求
    面向对象程序设计(JAVA) 第12周学习指导及要求
    让小球做圆周运动,你有几种办法?
    💥2020面试准备系列(一):JS
    秒懂js的垃圾回收
    jqgrid计算表单
    CSS揭秘实用技巧总结
    利用css 实现 视觉差效果
    前端经典面试题解密:JS的new关键字都干了什么?
  • 原文地址:https://www.cnblogs.com/wangsong/p/10274842.html
Copyright © 2011-2022 走看看