Springmvc工作原理详解

SpringMVC是什么

把名词分开来说,Spring与MVC可以更好地解释什么是SpringMVC,MVC为现代web项目开发的一种很常见的模式,简言之C(控制器)将V(视图、用户客户端)与M(模块,业务)分开构成了MVC ,业内常见的mvc模式的开发框架有Struts1,Struts2等。spring作为专业的开发web项目的开源框架,springMvc为内部的一个模块环节,同样采取mvc设计模式。 所以在使用spring开发web项目时,mvc是核心环节。


Springmvc和Spring是什么关系呢?

在百度百科上有一个很好的解释:意思是说,springMVC是spring的一个后续产品,其实就是spring在原有基础上,又提供了web应用的MVC模块,可以简单的把springMVC理解为是spring的一个模块(类似AOP,IOC这样的模块),网络上经常会说springMVC和spring无缝集成,其实springMVC就是spring的一个子模块。

入门实例

pom.xml配置文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <packaging>war</packaging>

  <name>springmvc_day01_start</name>
  <groupId>com.dynamic.cn</groupId>
  <artifactId>springmvc_day01_start</artifactId>
  <version>1.0-SNAPSHOT</version>

<!--  版本锁定-->
  <properties>
    <project.build.sourceEncodidng>UTF-8</project.build.sourceEncodidng>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>

  <dependencies>
      <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>
      <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
      </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.7</version>
        <configuration>
          <connectors>
            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
              <port>8888</port>
              <maxIdleTime>30000</maxIdleTime>
            </connector>
          </connectors>
          <webAppSourceDirectory>${project.build.directory}/${pom.artifactId}-${pom.version}</webAppSourceDirectory>
          <contextPath>/</contextPath>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
前端控制器web.xml配置文件:
	<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <!-- Servlet Filters ================================================ -->
<display-name>Archetype Created Web Application</display-name>
<!--    配置前端控制器-->
<!--  前端控制器servlet 加载配置文件-->
  <servlet>
<!--    DispatcherServlet 这个类第一次发请求的时候创建对象 添加上load-on-startup标签后 服务器启动则创建该类对象-->
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--    给DispatcherServlet这个类的contextConfigLocation属性传值 classpath:springmvc.xml-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
<!--    启动服务器创建DispatcherServlet对象;加载SpringMVC配置文件,Springmvc配置文件中扫描包生效,controller中的类就会被扫描到;变成bean对象;发送请求 执行方法-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!-- Servlet Context Listener ======================================= -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>
</web-app>
        
springmvc.xml配置文件:
	<?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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--  开启注解扫描-->
    <context:component-scan base-package="com.dynamic.controller"/>

    <!--    视图解析器对象-->
    <bean id="InternalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--        配置的参数  找这个目录下的需要的文件(也就是返回的success)-->
        <property name="prefix" value="/WEB-INF/pages/"/>
        <!--        查找该目录下哪种文件,即文件的后缀名是啥-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--    开启SpringMVC框架注解的支持-->
    <mvc:annotation-driven />
</beans>
index.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
	<head>入门</head>
	<body>
		<h2>Hello World!</h2>
		<a href="user/hello">入门程序</a>
	</body>
</html>
HelloController:

//控制器类
    @Controller
    @RequestMapping(path = "/user")
public class HelloController {
        @RequestMapping(path = "/hello")
    public String sayHello(){
        System.out.println("hello world!");
        return "success";
        //返回success SpringMVC框架有一个默认规则,即 返回success.jsp文件
//            该方法走完 应该找到success.jsp页面。如何找呢?需要在SpringMVC中配置视图解析器
    }
}
success.jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java"  isELIgnored="false" %>
<html>
	<head>
	    <title>入门案例</title>
	</head>
	<body>
	    <h3>入门成功</h3>
	</body>
</html>

上述实例执行时序图:

在这里插入图片描述

文字说明:
  1. 当启动Tomcat的时候,应用被加载,读取到web.xml中的配置,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象(否则会在客户端第一次发送请求的时候创建对象),就会加载springmvc.xml配置文件;
  2. 读取到springmvc.xml中的配置信息。因为开启了注解扫描,会创建spring容器并且初始化容器中的对象。所以HelloController对象就会被创建(还有其他的对象);
  3. 浏览器从index.jsp页面(默认情况)发送请求。请求会先到达DispatcherServlet核心控制器,该Servlet并不处理请求,而是把请求转发出去。转发的路径是根据请求的url,根据@RequstMapping注解找到处理该请求执行的具体方法;
  4. 根据执行方法的返回值,再根据配置的视图解析器InternalResourceViewResolver,去指定目录下查找执行名称的jsp文件,找到对应的结果视图;
  5. Tomcat服务器渲染结果视图,响应给浏览器。

处理流程架构图:

在这里插入图片描述

Springmvc的几大组件:

1、前端控制器(DispatcherServlet):不需要工程师开发,由框架提供。用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。相当于电脑的CPU。

2、处理器映射器(HandlerMapping):不需要工程师开发,由框架提供。根据URL去查找处理器。HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

3、处理器(Handler):需要工程师开发。编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确职系那个Handler。它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。由于Handler涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler,即Controller。

4、处理器适配器(HandlerAdapter):不需要工程师开发,由框架提供。按照特定规则(HandlerAdapter要求的规则)去执行Handler。会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用)。

5、视图解析器(ViewResovler):不需要工程师开发,由框架提供。View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由工程师根据业务需求开发具体的页面。

6、视图View:需要工程师开发。前端界面,展现给用户的。

核心架构具体执行流程文字说明:
  1. 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
  2. DispatcherServlet——>HandlerMapping, HandlerMapping 将会把请求映射为HandlerExecutionChain 对象(包含一个Handler 处理器(页面控制器)对象、多个HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
  3. DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
  4. HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);
  5. ModelAndView的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
  6. View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
  7. 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值