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

相关文章
|
19天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
42 4
|
28天前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
35 0
|
23天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
42 1
Spring 框架:Java 开发者的春天
|
15天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
15天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
65 1
|
23天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
29天前
|
人工智能 开发框架 Java
总计 30 万奖金,Spring AI Alibaba 应用框架挑战赛开赛
Spring AI Alibaba 应用框架挑战赛邀请广大开发者参与开源项目的共建,助力项目快速发展,掌握 AI 应用开发模式。大赛分为《支持 Spring AI Alibaba 应用可视化调试与追踪本地工具》和《基于 Flow 的 AI 编排机制设计与实现》两个赛道,总计 30 万奖金。
|
30天前
|
人工智能 Java API
阿里云开源 AI 应用开发框架:Spring AI Alibaba
近期,阿里云重磅发布了首款面向 Java 开发者的开源 AI 应用开发框架:Spring AI Alibaba(项目 Github 仓库地址:alibaba/spring-ai-alibaba),Spring AI Alibaba 项目基于 Spring AI 构建,是阿里云通义系列模型及服务在 Java AI 应用开发领域的最佳实践,提供高层次的 AI API 抽象与云原生基础设施集成方案,帮助开发者快速构建 AI 应用。本文将详细介绍 Spring AI Alibaba 的核心特性,并通过「智能机票助手」的示例直观的展示 Spring AI Alibaba 开发 AI 应用的便利性。示例源
|
1月前
|
Java 数据库连接 数据库
让星星⭐月亮告诉你,SSH框架01、Spring概述
Spring是一个轻量级的Java开发框架,旨在简化企业级应用开发。它通过IoC(控制反转)和DI(依赖注入)降低组件间的耦合度,支持AOP(面向切面编程),简化事务管理和数据库操作,并能与多种第三方框架无缝集成,提供灵活的Web层支持,是开发高性能应用的理想选择。
36 1

热门文章

最新文章