Spring mvc

Spring mvc

1. DispatcherServlet(前端控制器)

  负责拦截所有的URL 并分发给其他组件

2. HandlerMapping(处理器映射器)

处理映射器通过URL 找到相应的处理器

3. Handler(处理器)

处理器调用Service 层

4. HandlerAdapter(处理器适配器)

处理器适配器负责根据特定的规则对处理器进行执行,它可以**执行多种类型的处理器** 

5. ViewResolver(视图解析器)

viewResolver 可以将处理结果生成View(视图)并展示给用户

6. View:视图

MVC 流程

    <servlet>
        <servlet-name>Dispatch</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:config.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>Dispatch</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--    包扫喵-->
    <context:component-scan base-package="top.spacexist"/>
    <!-- 开启注解驱动-->
    <mvc:annotation-driven/>
    <!-- 释放静态资源 css-->
    <mvc:default-servlet-handler/>

    <mvc:interceptors>
        <bean class="top.spacexist.interceptor.testInterceptor"></bean>
    </mvc:interceptors>
</beans>


  1. 客户端发出一个HTTP请求,Web应用服务器接收这个请求,如果Web应用的配置文件中指定有DispatcherServlet的映射路径,那么服务器将该请求交给DispatchserServlet处理。

  2. DispatchserServlet接收到请求后,将根据包括URL、方法、报文头和参数在内的请求信息以及HandlerMapping的配置解析出目标Handler

  3. 在解析出目标Handler后,DispatchserServlet将通过相应的HandlerAdapter来调用Handler并完成业务逻辑的处理。

  4. 在成业务逻辑处理后,代表处理结果的ModelAndView会被返回到DispatchserServlet,ModelAndView中包含逻辑视图名和模型数据信息。

  5. DispatcherServlet通过ViewResolver完成逻辑视图名到真实View对象的解析。

  6. 获得真实的View对象后,DispatcherServlet将模型数据传给View对象并通过View对象对模型数据进行视图渲染

  7. DispatcherServlet将最终的View对象响应给客户端并展示给用户。

	mappedHandler = getHandler(processedRequest);
//进入DistpatchServlet 调用这个方法
		if (mappedHandler == null) {
			noHandlerFound(processedRequest, response);
			return;
			}//如果没有对应mapper 就返回NOFOUND
	        //mappedHandler = {HandlerExecutionChain@5825} "HandlerExecutionChain with [top.spacexist.hello#hello(String)] and 2 interceptors"
             //handler = {HandlerMethod@5513} "top.spacexist.hello#hello(String)"
             //interceptorList = {ArrayList@5826}  size = 2
             //interceptorIndex = -1  // 和Chain 中内容一样
	
	// Determine handler adapter for the current request. 现在开始寻找处理适配器
	HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
	String method = request.getMethod();
	boolean isGet = HttpMethod.GET.matches(method);
				if (isGet || HttpMethod.HEAD.matches(method)) {//判断ISget
	                //lastModifed = -1;
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return; // to4
					}
				}
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
	//实际调用handler 从这里开始
	mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// to 6
	applyDefaultViewName(processedRequest, mv);
	mappedHandler.applyPostHandle(processedRequest, response, mv); //应用后置拦截器 to 8
	
private List<HandlerMapping> handlerMappings; //处理器映射为Array
private List<HandlerAdapter> handlerAdapters; //处理器适配器


	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request); 
                //匹配当前request 所对应的hander 
				if (handler != null) {
					return handler;   //return 了一个 HanderExecutionChain
 类型的hander 
				}
			}
		}
		return null;
	}
//hander : top.spacexist.hello#hello(String); top.spacexist.hello 为handler
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);javadoc
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));        
//第一步判断 是否为Handler 强制转换为HanderExecutionChain
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
		// 匹配拦截器 如果匹配上了 就丢入Chain中
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(request)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
		
		
// Chain 主要有那些呢?
chain = {HandlerExecutionChain@5825} "HandlerExecutionChain with [top.spacexist.hello#hello(String)] and 0 interceptors"
     handler = {HandlerMethod@5513} "top.spacexist.hello#hello(String)"
     interceptorList = {ArrayList@5826}  size = 0
     interceptorIndex = -1
目前 有这三个值两HandlerInterceptorArrayList 类型
	private List<HandlerAdapter> handlerAdapters; 
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
// 4
	public boolean checkNotModified(long lastModifiedTimestamp) {
		return checkNotModified(null, lastModifiedTimestamp);
    }
    public boolean checkNotModified(@Nullable String etag, long lastModifiedTimestamp) {
		HttpServletResponse response = getResponse();
		if (this.notModified /*-1*/ || (response != null && HttpStatus.OK.value() != response.getStatus())) {
			return this.notModified;
		}
//判断是不是为OK
		if (response != null) {
			boolean isHttpGetOrHead = SAFE_METHODS.contains(getRequest().getMethod());
			if (this.notModified) {
				response.setStatus(isHttpGetOrHead ?
						HttpStatus.NOT_MODIFIED.value() : HttpStatus.PRECONDITION_FAILED.value());
			}
			if (isHttpGetOrHead) {
				if (lastModifiedTimestamp > 0 && parseDateValue(response.getHeader(HttpHeaders.LAST_MODIFIED)) == -1) {
					response.setDateHeader(HttpHeaders.LAST_MODIFIED, lastModifiedTimestamp);
				}
				if (StringUtils.hasLength(etag) && response.getHeader(HttpHeaders.ETAG) == null) {
					response.setHeader(HttpHeaders.ETAG, padEtagIfNecessary(etag));
				}
			}
		} // 不知道干什么的以后再说
// 5 
	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		for (int i = 0; i < this.interceptorList.size(); i++) {
			HandlerInterceptor interceptor = this.interceptorList.get(i);
			if (!interceptor.preHandle(request, response, this.handler)) {
				triggerAfterCompletion(request, response, null);
				return false;
			} //匹配拦截器 解释了为什么preHandle 要返回return 
                //如果prehandle ->return false 直接进入
                //乳沟返回true 则进行一下个判断
			this.interceptorIndex = i;
		}
		return true;
	}
	void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
		for (int i = this.interceptorIndex; i >= 0; i--) {
			HandlerInterceptor interceptor = this.interceptorList.get(i);
			try {
				interceptor.afterCompletion(request, response, this.handler, ex);
			}
			catch (Throwable ex2) {
				logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
			}
		}
	}
//6 
	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}
// 7
private boolean synchronizeOnSession = false;
	@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav; // MV对象
		checkRequest(request);// check 一下request

		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) { //false
			HttpSession session = request.getSession(false); //获得seesion
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav; //mav{view:WEB-INF/web-resource/hello.html,...}
	}


// 8
	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
			throws Exception {

		for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
			HandlerInterceptor interceptor = this.interceptorList.get(i);
			interceptor.postHandle(request, response, this.handler, mv);
		}
	}

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		boolean errorView = false;

		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {  //true
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("No view rendering, null ModelAndView returned.");
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			// Exception (if any) is already handled..
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}


// 10
	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 != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		String viewName = mv.getViewName(); //{WEB-INF/web-resource/hello.html}
		if (viewName != null) {
			// We need to resolve the view name.
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			if (view == null) {//view:{url:viewname,....}
				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
						"' in servlet with name '" + getServletName() + "'");
			}
		}
		else {
			// No need to lookup: the ModelAndView object contains the actual View object.
			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() + "'");
			}
		}
        if (logger.isTraceEnabled()) {
			logger.trace("Rendering view [" + view + "] "); //日志trace
		}
		try {
			if (mv.getStatus() != null) { //
				request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, mv.getStatus());
				response.setStatus(mv.getStatus().value());
			}
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "]", ex);
			}
			throw ex;
		}
	}


```java
	{
			if (mv.getStatus() != null) { //
				request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, mv.getStatus());
				response.setStatus(mv.getStatus().value());
			}
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "]", ex);
			}
			throw ex;
		}
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值