Spring MVC: 一种简洁且强大的Web应用框架

简介: 这篇文章介绍Spring MVC,Spring MVC是现在基本所有Java程序的主流开发框架,这篇文章主要介绍三部分内容:实现用户和程序的映射(在浏览器输入URL地址之后,能够在程序中匹配到相应方法)。服务器端得到用户的请求参数服务器端将结果返回给用户(前端)

1.什么是Spring MVC?


1.1 MVC的定义


MVC是Model View Controller的缩写,它是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个部分。


微信图片_20230111204241.png

Model(模型) 是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存储数据。

View(视图) 是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。

Controller(控制器) 是应用程序中处理用户交互的部分。通常控制器负责从视图中读取数据,控制用户输入,并向模型发送数据


1.2 MVC和Spring MVC的关系


MVC是一种思想,而Spring MVC是对MVC思想的具体实现。就类似于我们在学习Spring时的IoC和DI一样,IoC是一种思想,而DI是具体的实现。


1.3 Spring、Spring Boot、Spring MVC三者的关系


Spring是包含了众多工具方法的IoC容器。


Spring Boot是为了简化Spring开发而产生的脚手架。


Spring MVC是一个基于MVC设计模式和Servlet API实现的Web项目,同时Spring MVC又是Spring框架中的一个Web模块,它是随着Spring的诞生而存在的一个框架。


2.使用用户和程序的映射


Spring MVC项目创建和Spring Boot创建项目相同(Spring MVC使用Spring Boot),在创建的时候选择了Spring Web就相当于创建了Spring MVC的项目。

先完成Spring MVC项目的创建,再进行下边的工作:


2.1 @RequestMapping注解


@RequestMapping是Spring Web应用程序中最常用到的注解之一,它是用来注册接口的路由映射的。


路由映射:当用户访问一个url时,将用户的请求对应到应用程序的某个类的某个方法中的过程就叫做路由映射。


@RequestMapping基础使用如下:

微信图片_20230111204236.png

@RequestMapping既可以修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类+方法对应的url。访问结果如下图:


微信图片_20230111204233.png

默认情况下,@RequestMapping既支持POST请求方式,也支持GET请求方式。但如果想要只支持一种请求,也可以指定哪种请求,如下代码所示:


@RequestMapping(value="/sayhi",method=RequestMethod.GET)
@RequestMapping(value="/sayhi",method=RequestMethod.POST)

2.2 @GetMapping和@PostMapping


如果既想要只支持一种访问方式,还想要更简单的写法,就可以使用下边的方式:


GET请求


@GetMapping("/sayhi")

POST请求


@PostMapping("/sayhi")

3.服务端得到用户的请求参数


3.1 获取单个参数


微信图片_20230111204229.png

使用postman来构造请求:

微信图片_20230111204226.png

注意,整形建议设置类型为包装类(Integer),在设置为包装类时,如果没有传参数,则该参数只是为空,而如果设置的是int类型,不传参数将会报错。


微信图片_20230111204223.png

微信图片_20230111204217.png


3.2 获取多个参数


代码:


微信图片_20230111204214.png

构造请求:


微信图片_20230111204210.png

注意:


在获取多个参数的时候,前端传来的参数顺序没影响,参数是按照Key-Value来赋值的,只要保证前后端参数的名称Key一致即可。

在进行交互时一般参数命名都用小写,防止出现解析错误的情况。


3.3 参数重命名


在3.2中获取到多个参数的前提,是要保证前后端参数的命名相同(即Key值相同),但如果前端传来的参数并不合理,可以通过参数重命名的方法,将前端传来的参数映射到自己命名的参数上,进一步完成后续的开发。


方法为使用@RequestParam注解;

比如在3.2中的示例中,前端传来的参数是name,而不是username,就需要进行重命名,代码演示如下:


微信图片_20230111204207.png


构造请求:

微信图片_20230111204204.png

注意事项:

在加了@RequestParam注解以后,那么前端一定要传递此参数,否则就会报错,如果想要解决此问题,可以给@RequestParam里面添加required=false。


微信图片_20230111204201.png

微信图片_20230111204158.png


3.4 获取对象


在程序中编写对象类,前端传来参数就给对象完成了初始化。


User类:


微信图片_20230111204156.png

获取对象:


微信图片_20230111204150.png


基于form表单构造请求:


微信图片_20230111204142.png

注意:在对象中的整形,Integer类不传参数默认为null,int类不传参数默认为0,并不会报错。


构造JSON格式请求:

微信图片_20230111204139.png

我们发现如果构造JSON格式的请求,并不能获取到参数,我们用Fiddler来进行抓包


微信图片_20230111204135.png

我们可以发现,请求报文中确实是有参数,但并没有被获取到,需要在参数列表中加上@RequestBody注解才能解决这个问题。


微信图片_20230111204132.png

微信图片_20230111204129.png


3.5 从URL地址中获取参数


注意,此处获取参数是通过URL地址,而不是从URL的参数获取


微信图片_20230111204126.png

实现需要通过注解@PathVariable,代码演示如下:


微信图片_20230111204122.png

构造请求:


微信图片_20230111204119.png

3.6 获取文件


实现获取文件的功能,需要用到注解@RequestPart。


因为在不同的环境下图片的保存位置不同,所以需要在配置文件中声明图片的保存路径,配置文件设置如下:


微信图片_20230111204115.png

防止图片由于路径的相同而导致图片被覆盖,还需要给图片名增添随机性,就是使用UUID,整体实现代码如下:


微信图片_20230111204112.png

使用Postman模拟上传文件(基于form-data格式上传文件)


微信图片_20230111204109.png

3.7 获取Cookie


因为Spring MVC是基于Servlet API实现的,所以其天然支持Servlet API,在Spring MVC项目中的每个方法,都可以获取到HttpServletRequest和HttpServletResponce对象。


所以获取Cookie有传统的基于Servlet的方法,和使用Spring MVC中注解的方法来获取Cookie


a)基于Servlet的方式获取Cookie


微信图片_20230111204106.png

为了防止空指针异常,我们先在浏览器随便加上一些Cookie。


微信图片_20230111204101.png

然后刷新页面,看idea控制台的日志信息打印:


微信图片_20230111204058.png

b)使用@CookieValue注解实现Cookie的读取


微信图片_20230111204055.png

请求访问:


微信图片_20230111204052.png

3.8 获取Header


a)基于Servlet的方式获取请求头中的信息


微信图片_20230111204049.png

微信图片_20230111204046.png


b)使用@RequestHeader注解来实现


微信图片_20230111204043.png

微信图片_20230111204040.png



3.9 存储和获取Session


存储Session的实现,Servlet和Spring MVC的操作方法相同,代码如下:


微信图片_20230111204037.png


存储成功后,浏览器的cookie中会多出一条记录(如下图),红框记录的Key-Value中的Value就是sessionID,可以根据这个sessionID来找到session会话,对应的session中就是我们刚刚通过setAttribute()方法存进去的session属性Key-Value。


微信图片_20230111204034.png

获取session还是有两种方法:


a)基于Servlet


微信图片_20230111204030.png

微信图片_20230111204027.png


b)使用@SessionAttribute注解


微信图片_20230111204024.png

红框中的代码通常要加,如果不加的话,那么当session中不存在此属性的时候程序就会报错。


构造请求:


微信图片_20230111204020.png

4.服务端返回结果给用户


4.1 返回静态页面


在1.1 中我们就提到了Spring MVC的MVC架构模式(如下图),因为Spring MVC是随着Spring的诞生而诞生的,在那个时期并没有将前后端分离开来,所以在View层也就不存在前后端视图的说法,所以,在Spring MVC的方法中,默认返回的都是静态页面的名称。


微信图片_20230111204017.png

我们先在resource资源文件路径下新建前端页面


微信图片_20230111204014.png

前端代码如下:


微信图片_20230111204010.png

后端代码:


微信图片_20230111204007.png

浏览器访问路径:


微信图片_20230111204003.png

4.2 返回非静态页面数据


因为在4.1中我们提到了Spring MVC方法默认返回的是一个静态页面,如果我们想要返回非静态页面的数据,就需要通过注解@ResponseBody或者组合注解@RestController来实现。


@ResponseBody

与4.1相同的代码,加上@ResponseBody注解,我们再来看浏览器访问的结果


微信图片_20230111204000.png

再次通过浏览器进行访问,就会发现返回的是非静态页面的数据了。


微信图片_20230111203956.png

注意:

@ResponseBody注解既可以修饰类,又可以修饰方法,如果加在类上:表示当前类中所有方法都会返回一个非静态页面的数据;但如果加在方法上:表示当前方法返回的是一个非静态页面数据。


@RestController

@RestController注解相当于@Controller+@ResponseBody,所以它的效果就相当于两个注解的效果和。


微信图片_20230111203952.png

4.3 返回JSON对象


在Spring MVC的方法中,服务器给前端返回一个JSON格式的对象,要比Servlet的方式简单很多,直接返回存储了键值对的HashMap对象给前端,Spring就能让其自动识别转变为JSON格式返回给前端。


代码如下:


微信图片_20230111203949.png

构造请求,结果如下:


微信图片_20230111203945.png

4.4 综合练习


计算器

前端使用form表单的方式提交参数,在后端实现计算器的功能返回结果给前端。


前端代码如下:

微信图片_20230111203941.png

后端代码:

微信图片_20230111203939.png

浏览器构造请求演示:


微信图片_20230111203935.gif

登录

前端使用ajax请求传递参数,后端返回状态给前端,实现登录的功能。


前端代码如下:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/jquery.min.js"></script>
    <title>登录</title>
    <script>
        // ajax提交
        function mysub(){
            // 1.判空
            let username=jQuery("#username");
            let password=jQuery("#password");
            if(jQuery.trim(username.val())=="") {
                alert("请先输入用户名!");
                username.focus();// 光标重置到此处
                return;
            }
            if(jQuery.trim(password.val())=="") {
                alert("请先输入密码!");
                password.focus();// 光标重置到此处
                return;
            }
            jQuery.ajax({
                url:"/login",
                type:"POST",
                data:{"username":username.val(),
                "password":password.val()},
                success:function(body) {
                    alert(JSON.stringify(body));
                }
            });
        }
    </script>
</head>
<body>
    <div style="text-align: center;">
        <h1>登录</h1>
        用户:<input id="username"><br>
        密码:<input id="password" type="password"><br>
        <input type="button" value="提交" onclick="mysub()" style="margin-top: 20px;margin-left: 50px;">
    </div>
</body>
</html>


后端代码:


微信图片_20230111203931.png

浏览器构造请求演示运行:


微信图片_20230111203928.gif


4.5 请求转发或请求重定向


forward VS redirect

return 不但可以返回视图或者数据,还可以实现跳转,跳转的方式有以下两种:


forward实现请求转发

redirect实现请求重定向

两者的理解可以用一个借钱的例子来理解,张三向李四借钱,李四没有钱,但他向王五借来钱,又给了张三,这就是请求转发的过程,李四代为完成了张三的请求;但如果李四没有钱,他告诉张三王五有钱,让张三去找王五借钱,这个过程就是请求重定向的过程。


微信图片_20230111203925.png


分别来看两种方法的请求结果:


forward

微信图片_20230111203922.png

redirect

微信图片_20230111203919.png


可以发现两个方法都跳转成功到了同一个界面,但两者又有不同,具体区别如下:

【参考文章链接跳转】


经典面试题:请求转发和请求重定向的区别

1.定义不同


请求转发(forward)发生在服务端程序内部,当服务端收到一个客户端的请求之后,会先将请求转发给目标地址,再将目标地址返回的结果转发给客户端。

而请求重定向(redirect)是指服务端接受到客户端的请求以后,会给客户端返回一个临时响应头,这个临时响应头中记录了客户端需要再次发送请求(重定向)的URL地址,然后客户端按照这个URL再次发送请求。


2.请求方不同

请求转发(forward)是服务端的行为,而请求重定向(redirect)是客户端的行为。

交互流程如下图所示:


微信图片_20230111203915.png

3.数据共享不同

请求转发(forward)是由服务端实现的,所以整个执行流程中,客户端只发送了一次请求,因此整个交互过程中都是同一个Request对象和一个Response对象,所以请求和返回的数据是共享的;而请求重定向(redirect)是向由客户端发送两次完全不同的请求,所以两次请求中的数据是不同的。


4.最终URL地址不同

在上边的浏览器访问结果中我们也可以看出,虽然访问到的是同一个界面,诞生两次访问的最终URL地址是不同的。这是因为请求转发(forward)是在服务器端代为完成的,整个过程URL地址不变,而请求重定向(redirect)是服务器端告诉客户端另一个地址,客户端进行了再一次访问,而非刚开始请求的地址,所以URL地址发生了改变。


5.代码实现不同

微信图片_20230111203907.png

相关文章
|
21天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
21天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
21天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
11天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
554 6
|
8天前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
9天前
|
XML 前端开发 Java
控制spring框架注解介绍
控制spring框架注解介绍
|
9天前
|
存储 NoSQL Java
Spring Session框架
Spring Session 是一个用于在分布式环境中管理会话的框架,旨在解决传统基于 Servlet 容器的会话管理在集群和云环境中的局限性。它通过将用户会话数据存储在外部介质(如数据库或 Redis)中,实现了会话数据的跨服务器共享,提高了应用的可扩展性和性能。Spring Session 提供了无缝集成 Spring 框架的 API,支持会话过期策略、并发控制等功能,使开发者能够轻松实现高可用的会话管理。
Spring Session框架
|
16天前
|
Java 应用服务中间件 开发者
深入探索并实践Spring Boot框架
深入探索并实践Spring Boot框架
27 2
|
16天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
25天前
|
运维 NoSQL Java
SpringBoot接入轻量级分布式日志框架GrayLog技术分享
在当今的软件开发环境中,日志管理扮演着至关重要的角色,尤其是在微服务架构下,分布式日志的统一收集、分析和展示成为了开发者和运维人员必须面对的问题。GrayLog作为一个轻量级的分布式日志框架,以其简洁、高效和易部署的特性,逐渐受到广大开发者的青睐。本文将详细介绍如何在SpringBoot项目中接入GrayLog,以实现日志的集中管理和分析。
104 1
下一篇
无影云桌面