快捷搜索:  汽车  科技

springmvc在项目中的应用流程(SpringMVC介绍之Spring)

springmvc在项目中的应用流程(SpringMVC介绍之Spring)package org.springframework.web.servlet; import java.util.Locale; public interface ViewResolver { View resolveViewName(String var1 Locale var2) throws Exception; } View : 视图package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface HandlerAdapter { boolean supports(Object var1); ModelAndView handle(Http

点关注,不迷路;持续更新Java相关技术及资讯!!!

pring MVC是Spring的一个模块,包含Web MVC、Framework,Web Views,JSP等等。

其中MVC分别对应:Model,View,controller,本质上SpirngMVC还是使用servlet进行处理,并在其基础上进行了封装,简化了开发流程,提高易用性,并使得逻辑结构变得非常清晰。

springmvc在项目中的应用流程(SpringMVC介绍之Spring)(1)

Spring MVC对比Servlet简化开发流程的方面有:

  • 基于注解的url映射
  • http表单参数转换
  • 全局统一异常处理
  • 拦截器的实现
  • 等等。

Spring MVC 体系结构

HandlerMapping : url与控制器的映射

package org.springframework.web.servlet; import javax.servlet.http.HttpServletrequest; public interface HandlerMapping { String PATH_WITHIN_handleR_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() ".pathWithinHandlerMapping"; String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() ".bestMatchingPattern"; String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() ".introspectTypeLevelMapping"; String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() ".uriTemplateVariables"; String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() ".matrixVariables"; String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() ".producibleMediaTypes"; HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception; }

HandlerAdapter : 控制器与执行适配器

package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface HandlerAdapter { boolean supports(Object var1); ModelAndView handle(HttpServletRequest var1 HttpServletResponse var2 Object var3) throws Exception; long getLastModified(HttpServletRequest var1 Object var2); }

ViewResolver : 视图仓库

package org.springframework.web.servlet; import java.util.Locale; public interface ViewResolver { View resolveViewName(String var1 Locale var2) throws Exception; }

View : 视图

package org.springframework.web.servlet; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface View { String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() ".responseStatus"; String PATH_VARIABLES = View.class.getName() ".pathVariables"; String SELECTED_CONTENT_TYPE = View.class.getName() ".selectedContentType"; String getContentType(); void render(Map<String ?> var1 HttpServletRequest var2 HttpServletResponse var3) throws Exception; }

HandlerExceptionResolver : 异常捕捉器

package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface HandlerExceptionResolver { ModelAndView resolveException(HttpServletRequest var1 HttpServletResponse var2 Object var3 Exception var4); }

HandlerInterceptor : 拦截器

package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface HandlerInterceptor { boolean preHandle(HttpServletRequest var1 HttpServletResponse var2 Object var3) throws Exception; void postHandle(HttpServletRequest var1 HttpServletResponse var2 Object var3 ModelAndView var4) throws Exception; void afterCompletion(HttpServletRequest var1 HttpServletResponse var2 Object var3 Exception var4) throws Exception; }

Spring MVC 执行流程

先看个简单的demo

web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>spring-mvc</display-name> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:/spring-mvc.xml </param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> </web-app>

spring-mvc.xml

<?xml version="1.0" encoding="GBK"?> <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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <bean id="simple" class="com.demo.spring.mvc.control.SimpleControl"></bean> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <props> <prop key="/hello.do">simple</prop> </props> </property> </bean> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 视图仓库 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/page/"/> <property name="suffix" value=".jsp"/> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> </bean> </beans>

userView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>userView</title> </head> <body> ${name} </body> </html>

SimpleControl.java

package com.demo.spring.mvc.control; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * com.demo.spring.mvc.control * * @author Zyy * @date 2019/2/20 22:47 */ public class SimpleControl implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest HttpServletResponse httpServletResponse) throws Exception { ModelAndView modelAndView = new ModelAndView("userView"); modelAndView.addObject("name" "ayang"); return modelAndView; } }

启动后访问localhost:8080/hello.do 就可以显示我们jsp中我们返回的name了。

整个mvc流程如下:

浏览器访问/hello.do -> 请求dispatcher servlet -> 然后找到SimpleUrlHandlerMapping -> 然后根据配置找到/hello.do对应simple ref -> 然后根据simple ref找到 simple这个control bean -> 然后根据control会找到对应的适配器SimpleControllerHandlerAdapter -> 基于适配器执行业务处理 -> 然后返回给dispatcher Servlet -> 然后找到视图仓库InternalResourceViewResolver -> 然后视图仓库根据viewName找到对应的视图解析JstlView ->然后返回给view

Spring MVC 体系结构UML

springmvc在项目中的应用流程(SpringMVC介绍之Spring)(2)

从上图可以看出,其中最主要的就是DispatcherServlet,看一下相关的源码。

org.springframework.web.servlet.DispatcherServlet

核心的方法:

protected void doDispatch(HttpServletRequest request HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { try { ModelAndView mv = null; Object dispatchException = null; try { processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; //获取mappedHandler mappedHandler = this.getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { this.noHandlerFound(processedRequest response); return; } //根据handler获取HandlerAdapter HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request mappedHandler.getHandler()); if (this.logger.isDebugEnabled()) { this.logger.debug("Last-Modified value for [" getRequestUri(request) "] is: " lastModified); } if ((new ServletWebRequest(request response)).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest response)) { return; } //HandlerAdapter找到我们配置的SimpleControllerHandlerAdapter, //然后由此找到我们自己的SimpleControl mv = ha.handle(processedRequest response mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } this.applyDefaultViewName(processedRequest mv); mappedHandler.applyPostHandle(processedRequest response mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new NestedServletException("Handler dispatch failed" var21); } this.processDispatchResult(processedRequest response mappedHandler mv (Exception)dispatchException); } catch (Exception var22) { this.triggerAfterCompletion(processedRequest response mappedHandler var22); } catch (Throwable var23) { this.triggerAfterCompletion(processedRequest response mappedHandler new NestedServletException("Handler processing failed" var23)); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest response); } } else if (multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }

其中首先根据request进行getHandler(HttpServletRequest request) 方法,返回一个HandlerExecutionChain ,方法是遍历 handlerMappings,然后从handlerMappings中获取HandlerExecutionChain,相关代码如下:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Iterator var2 = this.handlerMappings.iterator(); HandlerExecutionChain handler; do { if (!var2.hasNext()) { return null; } HandlerMapping hm = (HandlerMapping)var2.next(); if (this.logger.isTraceEnabled()) { this.logger.trace("Testing handler map [" hm "] in DispatcherServlet with name '" this.getServletName() "'"); } handler = hm.getHandler(request); } while(handler == null); return handler; }

上面方法中 HandlerMapping.getHandler(request) 源码如下:

org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = this.getHandlerInternal(request); if (handler == null) { handler = this.getDefaultHandler(); } if (handler == null) { return null; } else { if (handler instanceof String) { String handlerName = (String)handler; handler = this.getApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = this.getCorsConfiguration(handler request); CorsConfiguration config = globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig; executionChain = this.getCorsHandlerExecutionChain(request executionChain config); } return executionChain; } }

上面方法中 getHandlerExecutionChain(handler request) 源码如下:

protected HandlerExecutionChain getHandlerExecutionChain(Object handler HttpServletRequest request) { HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); Iterator var5 = this.adaptedInterceptors.iterator(); while(var5.hasNext()) { HandlerInterceptor interceptor = (HandlerInterceptor)var5.next(); if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor; if (mappedInterceptor.matches(lookupPath this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; }

继续回到doDispatch,根据获取到的handler进行继续获取适配器,方法:getHandlerAdapter 相关源码如下:

org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { Iterator var2 = this.handlerAdapters.iterator(); HandlerAdapter ha; do { if (!var2.hasNext()) { throw new ServletException("No adapter for handler [" handler "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); } ha = (HandlerAdapter)var2.next(); if (this.logger.isTraceEnabled()) { this.logger.trace("Testing handler adapter [" ha "]"); } } while(!ha.supports(handler)); return ha; }

回去到适配器之后,做handle处理,相关方法:

mv = ha.handle(processedRequest response mappedHandler.getHandler()); org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#handle public ModelAndView handle(HttpServletRequest request HttpServletResponse response Object handler) throws Exception { return ((Controller)handler).handleRequest(request response); }

其中 handleRequest(request response) 的实现方法就是我们自己写的SimpleControl中的handleRequest方法:

@Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest HttpServletResponse httpServletResponse) throws Exception { ModelAndView modelAndView = new ModelAndView("userView"); modelAndView.addObject("name" "ayang"); return modelAndView; }

handleRequest 处理完成之后,就会返回一个ModelAndView,接下来会用到resolveViewName,由viewName来获取到view,然后 view 再进行解析,相关源码如下:

org.springframework.web.servlet.DispatcherServlet#resolveViewName protected View resolveViewName(String viewName Map<String Object> model Locale locale HttpServletRequest request) throws Exception { Iterator var5 = this.viewResolvers.iterator(); View view; do { if (!var5.hasNext()) { return null; } ViewResolver viewResolver = (ViewResolver)var5.next(); view = viewResolver.resolveViewName(viewName locale); } while(view == null); return view; }

整个 mvc 执行流程如下:

dispatcherServlet -> handlermapping ->基于url查找handler -> handlerAdapter -> 基于handler找到adapter -> 由adapter找到我们的 handler -> 执行业务处理返回 modelAndView -> viewResolver -> 基于viweName找到view -> 执行视图解析 -> 返回前端

本文到这里就结束了,喜欢的朋友可以帮忙转发和关注一下,感谢支持!

关注、转发、评论头条号每天分享java 知识,私信回复“源码”赠送Spring源码分析、Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式资料

公众号:Java大型网站架构

springmvc在项目中的应用流程(SpringMVC介绍之Spring)(3)

猜您喜欢: