Spring MVC 工作原理

Spring MVC 工作原理

1.Spring MVC 原理图

1.Request发送请求
2.请求查找Handler
3.返回一个执行链
4.请求适配器
5. 执行
6.返回ModelAndView
7.返回ModelAndView
8.请求执行视图解析
9.返回View
10.视图渲染将模型数据填充到Reuqest域中
客户端
前端控制器DispathcherServlet接受用户请求
处理器映射器HandlerMapping
处理器适配器HandlerAdapter
Hanlder处理器Controller
视图解析器viewResolver
视图Jsphtml

2.原理图中涉及的各个组件。

  • DispacherServlet : 前端控制器,整个流程的控制中心,由它调用其他组件处理用户请求。
  • HandlerMapping: 处理器映射器,负责根据用户的URL找到相应的Handler处理器
  • HandlerAdapter: 处理器适配器,根据处理器适配器映射器(HandlerMapping)找到Handler相关信息,根据特定的规则执行相关的处理器Handler
  • Handler: 处理器,负责执行用户的请求,Controller便是处理器。
  • ViewResolver: 视图解析器,根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成View 视图对象,最后对View进行渲染,并将结果通过页面返回给用户。
  • ModelAndView: 使用ModelAndView类用来存储处理完的结果数据,以及显示该数据的视图。当控制器处理请求后,通常控制器会将包含视图名称的以及一些模型属性的ModelAndView对象返回给DispatcherServlet

3.接下来介绍SpringMVC的工作原理

  1. 用户向服务器发送请求至前段控制器DispatcherServlet。
  2. DispathcherServlet 调用HandlerMapping,由此得知哪个Handler(Controller) 处理该请求
  3. HandlerMapping 找到具体的处理器,生成处理器对象以及处理器拦截器一并返回给DispathcherServlet.
  4. DispathcherServlet 调用 HandlerAdapter。
  5. HandlerAdapter 经过适配调用具体的Handler(也叫控制器Controller)。
  6. Handler 处理完请求后返回ModelView
  7. HandlerAdapter 将后端处理器结果(ModelView ) 反馈给DispathcherServlet。
  8. DispathcherServlet 将ModelView 传递给 视图解析器ViewResolver。
  9. ViewResolver 根据ModelView 中的视图名称返回具体的View。
  10. DispathcherServlet 将ModelView 中的模型数据填充到视图中,渲染视图。
  11. DispathcherServlet 将结果响应给用户。

4.下面创建一个Spring MVC 入门程序。

创建Maven Web工程

mvn archetype:generate -DgroupId=com.zdy -DartifactId=SpringMVC001 -DarchetypeArtifactId=maven-archetype-webapp

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>
<groupId>com.zdy</groupId>
<artifactId>SpringMVC001</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SpringMVC001 Maven Webapp</name>
<url>http://maven.apache.org</url>

<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.3.5</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/javax.servlet.jsp-api -->
<dependency>
  <groupId>javax.servlet.jsp</groupId>
  <artifactId>javax.servlet.jsp-api</artifactId>
  <version>2.3.3</version>
  <scope>provided</scope>
</dependency>


  <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/javax.servlet.jsp.jstl-api -->
  <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>javax.servlet.jsp.jstl-api</artifactId>
      <version>1.2.2</version>
  </dependency>
  <dependency>
      <groupId>cn.itlym.shoulder</groupId>
      <artifactId>lombok</artifactId>
      <version>0.1</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-server -->


</dependencies>

<build>
<finalName>SpringMVC001</finalName>
    <plugins>
        <plugin>
            <!--jetty maven 插件,为 maven 提供运行 web 程序的能力-->
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>9.4.12.v20180830</version>
            <configuration>
                <scanIntervalSeconds>10</scanIntervalSeconds>
                <webApp>
                    <contextPath>/</contextPath>
                </webApp>
            </configuration>
        </plugin>
    </plugins>
</build>
</project>

web.xml配置文件

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!-- 配置 Spring MVC DispatchcerServlet 前端控制器 -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!-- contextConfigLocation 是参数名称,该参数的值包含 Spring MVC 的配置文件路径 -->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc-config.xml</param-value>
    </init-param>
    <!-- 在 Web 应用启动时立即加载 Servlet -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- Servlet 映射声明 -->
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!-- 监听当前域的所有请求 -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
    <welcome-file-list>
    <welcome-file>register.jsp</welcome-file>
  </welcome-file-list>
</web-app>

springmvc-config.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-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">

    <!-- 开启注解 -->
    <mvc:annotation-driven />
    <!-- 配置自动扫描的包,完成 Bean 的创建和自动依赖注入的功能 -->
    <context:component-scan base-package = "com.zdy.mvc.controller" />
    <!-- 默认静态资源处理 -->
    <mvc:default-servlet-handler/>
    <!-- 配置视图解析器 -->
    <bean id = "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name = "prefix" value = "/WEB-INF/views/"/>
        <property name = "suffix" value = ".jsp"/>
    </bean>
</beans>

新建实体类

User.java

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
}

新建控制器UserController.java

@Controller
public class UserController{
    @PostMapping("/register")
   public String registUser(User user, Model model){
       model.addAttribute("user",user);
        return "success";
   }
}

配置注册页面register.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>register page</title>
</head>
<body>
<form action = "register" method = "post">
    <h5>User registration</h5>
    <p>
        <label>name </label> <input type = "text" id = "username" name = "username"
                                    tabindex = "1">
    </p>

    <p>
        <label>password </label> <input type = "text" id = "password" name = "password"
                                        tabindex = "2">
    </p>

    <p>
        <label>age </label> <input type = "text" id = "age" name = "age"
                                   tabindex = "3">
    </p>
    <p id = "buttons">
        <input id = "submit" type = "submit" tabindex = "4" value = "register">
        <input id = "reset" type = "reset" tabindex = "5" value = "reset">
    </p>
</form>
</body>
</html>

配置成功页面

success.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">
<%--支持el 表达式--%>
<%@ page isELIgnored="false" %>
    <html>
        <head>
            <meta http-equiv = "Content-Type" content = "text/html; charset = UTF-8">
            <title>success page</title>
        </head>
        <body>
            <h5>login was successful</h5>
            <p>
                name:${requestScope.user.username}<br /> password:${requestScope.user.password}<br /> age:${requestScope.user.age}<br />
            </p>
        </body>
    </html>

执行 mvn jetty:run 访问 https://locahost:8080/register.jsp

填入相应的用户信息,并提交自动跳转到成功页面回显。

热门文章

暂无图片
编程学习 ·

那些年让我们目瞪口呆的bug

程序员一生与bug奋战&#xff0c;可谓是杀敌无数&#xff0c;见怪不怪了&#xff01;在某知识社交平台中&#xff0c;一个“有哪些让程序员目瞪口呆的bug”的话题引来了6700多万的阅读&#xff0c;可见程序员们对一个话题的敏感度有多高。 1、麻省理工“只能发500英里的邮件” …
暂无图片
编程学习 ·

redis的下载与安装

下载redis wget http://download.redis.io/releases/redis-5.0.0.tar.gz解压redis tar -zxvf redis-5.0.0.tar.gz编译 make安装 make install快链方便进入redis ln -s redis-5.0.0 redis
暂无图片
编程学习 ·

《大话数据结构》第三章学习笔记--线性表(一)

线性表的定义 线性表&#xff1a;零个或多个数据元素的有限序列。 线性表元素的个数n定义为线性表的长度。n为0时&#xff0c;为空表。 在比较复杂的线性表中&#xff0c;一个数据元素可以由若干个数据项组成。 线性表的存储结构 顺序存储结构 可以用C语言中的一维数组来…
暂无图片
编程学习 ·

对象的扩展

文章目录对象的扩展属性的简洁表示法属性名表达式方法的name属性属性的可枚举性和遍历可枚举性属性的遍历super关键字对象的扩展运算符解构赋值扩展运算符AggregateError错误对象对象的扩展 属性的简洁表示法 const foo bar; const baz {foo}; baz // {foo: "bar"…
暂无图片
编程学习 ·

让程序员最头疼的5种编程语言

世界上的编程语言&#xff0c;按照其应用领域&#xff0c;可以粗略地分成三类。 有的语言是多面手&#xff0c;在很多不同的领域都能派上用场。大家学过的编程语言很多都属于这一类&#xff0c;比如说 C&#xff0c;Java&#xff0c; Python。 有的语言专注于某一特定的领域&…
暂无图片
编程学习 ·

写论文注意事项

参考链接 给研究生修改了一篇论文后&#xff0c;该985博导几近崩溃…… 重点分析 摘要与结论几乎重合 这一条是我见过研究生论文中最常出现的事情&#xff0c;很多情况下&#xff0c;他们论文中摘要部分与结论部分重复率超过70%。对于摘要而言&#xff0c;首先要用一小句话引…
暂无图片
编程学习 ·

安卓 串口开发

上图&#xff1a; 上码&#xff1a; 在APP grable添加 // 串口 需要配合在项目build.gradle中的repositories添加 maven {url "https://jitpack.io" }implementation com.github.licheedev.Android-SerialPort-API:serialport:1.0.1implementation com.jakewhart…
暂无图片
编程学习 ·

2021-2027年中国铪市场调研与发展趋势分析报告

2021-2027年中国铪市场调研与发展趋势分析报告 本报告研究中国市场铪的生产、消费及进出口情况&#xff0c;重点关注在中国市场扮演重要角色的全球及本土铪生产商&#xff0c;呈现这些厂商在中国市场的铪销量、收入、价格、毛利率、市场份额等关键指标。此外&#xff0c;针对…
暂无图片
编程学习 ·

Aggressive cows题目翻译

描述&#xff1a; Farmer John has built a new long barn, with N (2 < N < 100,000) stalls.&#xff08;John农民已经新建了一个长畜棚带有N&#xff08;2<N<100000&#xff09;个牛棚&#xff09; The stalls are located along a straight line at positions…
暂无图片
编程学习 ·

剖析组建PMO的6个大坑︱PMO深度实践

随着事业环境因素的不断纷繁演进&#xff0c;项目时代正在悄悄来临。设立项目经理转岗、要求PMP等项目管理证书已是基操&#xff0c;越来越多的组织开始组建PMO团队&#xff0c;大有曾经公司纷纷建造中台的气质&#xff08;当然两者的本质并不相同&#xff0c;只是说明这个趋势…
暂无图片
编程学习 ·

Flowable入门系列文章118 - 进程实例 07

1、获取流程实例的变量 GET运行时/进程实例/ {processInstanceId} /变量/ {变量名} 表1.获取流程实例的变量 - URL参数 参数需要值描述processInstanceId是串将流程实例的id添加到变量中。变量名是串要获取的变量的名称。 表2.获取流程实例的变量 - 响应代码 响应码描述200指…
暂无图片
编程学习 ·

微信每天自动给女[男]朋友发早安和土味情话

微信通知&#xff0c;每天给女朋友发早安、情话、诗句、天气信息等~ 前言 之前逛GitHub的时候发现了一个自动签到的小工具&#xff0c;b站、掘金等都可以&#xff0c;我看了下源码发现也是很简洁&#xff0c;也尝试用了一下&#xff0c;配置也都很简单&#xff0c;主要是他有一…
暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

项目经理,你有什么优势吗?

大侠被一个问题问住了&#xff1a;你和别人比&#xff0c;你的优势是什么呢? 大侠听到这个问题后&#xff0c;脱口而出道&#xff1a;“项目管理能力和经验啊。” 听者抬头看了一下大侠&#xff0c;显然听者对大侠的这个回答不是很满意&#xff0c;但也没有继续追问。 大侠回家…
暂无图片
编程学习 ·

nginx的负载均衡和故障转移

#注&#xff1a;proxy_temp_path和proxy_cache_path指定的路径必须在同一分区 proxy_temp_path /data0/proxy_temp_dir; #设置Web缓存区名称为cache_one&#xff0c;内存缓存空间大小为200MB&#xff0c;1天没有被访问的内容自动清除&#xff0c;硬盘缓存空间大小为30GB。 pro…
暂无图片
编程学习 ·

业务逻辑漏洞

身份认证安全 绕过身份认证的几种方法 暴力破解 测试方法∶在没有验证码限制或者一次验证码可以多次使用的地方&#xff0c;可以分为以下几种情况︰ (1)爆破用户名。当输入的用户名不存在时&#xff0c;会显示请输入正确用户名&#xff0c;或者用户名不存在 (2)已知用户名。…