码迷,mamicode.com
首页 > 编程语言 > 详细

springMVC源码分析

时间:2019-01-16 00:13:48      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:arraylist   .com   pattern   std   rmi   image   intern   cep   direct   

技术分享图片

  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);
		}
	}

springMVC源码分析

标签:arraylist   .com   pattern   std   rmi   image   intern   cep   direct   

原文地址:https://www.cnblogs.com/wangsong/p/10274842.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!