Spring-MVC工作原理
Spring简介
Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。围绕Servlet设计,将请求发给控制器,然后通过模型对象,分派器来展示请求结果视图。其中核心类是DispatcherServlet,它是一个Servlet,顶层是实现的Servlet接口
运行原理
SpringMVC接口解释
-
DispatcherServlet:
Spring提供的前端控制器,本质上是一个servlet,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。
-
HandlerMapping:
能够完成客户请求到Controller映射。
-
Controller:
需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。
Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。
从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。
-
ModelAndView:
视图模型对象,由Controller返回,由视图解析器(ViewResolver)解析。
-
ViewResolver:
Spring提供的视图解析器(ViewResolver),在Web应用中查找View对象,从而将相应结果渲染给客户。
SpringMVC运行原理
1、客户端发起请求,直接请求到DispatcherServlet。
2、DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。
HandlerMapping接口 – 处理请求的映射HandlerMapping接口的实现类:SimpleUrlHandlerMapping 通过配置文件,把一个URL映射到ControllerDefaultAnnotationHandlerMapping 通过注解,把一个URL映射到Controller类上
3、解析到对应的Handler后,开始由HandlerAdapter适配器处理。
HandlerAdapter接口 – 处理请求的映射AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上
4、HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。
5、处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。
6、ViewResolver会根据逻辑View查找实际的View。
7、DispaterServlet把返回的Model传给View。
8、通过View返回给请求者(浏览器)
SpringMVC运行原理简单实现
- 新建项目导入依赖
<!--版本控制-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>5.3.4</spring.version>
</properties>
<dependencies>
<!--spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.0-M1</version>
<scope>test</scope>
</dependency>
</dependencies>
- 在web.xml中配置servlet
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联springMVC配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--匹配所有的请求,(不包括.jsp)-->
<!--陪陪所有的请求,(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 配置SpringMVC的配置文件:springmvc-servlet.xml
<!--处理器映射器,仅理解原理使用实际开发中一般不会这么干-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器,仅理解原理使用实际开发中一般不会这么干-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器:DispatcherServlet给他的mModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--Controller扫描-->
<bean id="/hello" class="[包名称].HelloController"/>
- 新建类HelloController,并实现Controller方法(此做法只是为了更好的理解运行原理),重写handleRequest方法,并返回ModelAndView给视图解析器解析
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
//调用业务层
mv.addObject("msg","HelloSpringMVC");
mv.setViewName("hello");
return mv;
}
}
- 新建hello.jsp文件测试。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 视图解析器会更具HelloController里面ModelAndView所携带的ViewName参数拼接.jsp视图路径。
找到之后进行渲染展示-->