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天前
|
XML 安全 Java
|
24天前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
33 0
|
22天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
40 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
6天前
|
IDE Java 测试技术
互联网应用主流框架整合之Spring Boot开发
通过本文的介绍,我们详细探讨了Spring Boot开发的核心概念和实践方法,包括项目结构、数据访问层、服务层、控制层、配置管理、单元测试以及部署与运行。Spring Boot通过简化配置和强大的生态系统,使得互联网应用的开发更加高效和可靠。希望本文能够帮助开发者快速掌握Spring Boot,并在实际项目中灵活应用。
24 5
|
17天前
|
缓存 Java 数据库连接
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
47 8
|
27天前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
47 6
|
1月前
|
Java 数据库连接 数据库
不可不知道的Spring 框架七大模块
Spring框架是一个全面的Java企业级应用开发框架,其核心容器模块为其他模块提供基础支持,包括Beans、Core、Context和SpEL四大子模块;数据访问及集成模块支持数据库操作,涵盖JDBC、ORM、OXM、JMS和Transactions;Web模块则专注于Web应用,提供Servlet、WebSocket等功能;此外,还包括AOP、Aspects、Instrumentation、Messaging和Test等辅助模块,共同构建强大的企业级应用解决方案。
59 2
|
24天前
|
XML Java 网络架构
使用 Spring Boot 公开 SOAP Web 服务端点:详细指南
使用 Spring Boot 公开 SOAP Web 服务端点:详细指南
32 0
|
1月前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
112 1
|
1月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
33 0