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

相关文章
|
11天前
|
安全 Java 开发者
如何在Spring框架中实现横切关注点的集中管理和重用?
【4月更文挑战第30天】如何在Spring框架中实现横切关注点的集中管理和重用?
18 0
|
11天前
|
安全 Java 程序员
Spring框架的核心特性是什么?
【4月更文挑战第30天】Spring 的特性
17 0
|
1天前
|
XML Java 数据库连接
Spring框架与Spring Boot的区别和联系
Spring框架与Spring Boot的区别和联系
8 0
|
3天前
|
前端开发 安全 Java
使用Spring框架加速Java开发
使用Spring框架加速Java开发
5 0
|
3天前
|
设计模式 数据采集 监控
Spring日志框架
Spring日志框架
7 0
|
3天前
|
前端开发 Java 应用服务中间件
Spring MVC框架概述
Spring MVC 是一个基于Java的轻量级Web框架,采用MVC设计模型实现请求驱动的松耦合应用开发。框架包括DispatcherServlet、HandlerMapping、Handler、HandlerAdapter、ViewResolver核心组件。DispatcherServlet协调这些组件处理HTTP请求和响应,Controller处理业务逻辑,Model封装数据,View负责渲染。通过注解@Controller、@RequestMapping等简化开发,支持RESTful请求。Spring MVC具有清晰的角色分配、Spring框架集成、多种视图技术支持以及异常处理等优点。
11 1
|
9天前
|
设计模式 前端开发 Java
19:Web开发模式与MVC设计模式-Java Web
19:Web开发模式与MVC设计模式-Java Web
19 4
|
11天前
|
SQL Java 数据库连接
Springboot框架整合Spring JDBC操作数据
JDBC是Java数据库连接API,用于执行SQL并访问多种关系数据库。它包括一系列Java类和接口,用于建立数据库连接、创建数据库操作对象、定义SQL语句、执行操作并处理结果集。直接使用JDBC涉及七个步骤,包括加载驱动、建立连接、创建对象、定义SQL、执行操作、处理结果和关闭资源。Spring Boot的`spring-boot-starter-jdbc`简化了这些步骤,提供了一个在Spring生态中更便捷使用JDBC的封装。集成Spring JDBC需要添加相关依赖,配置数据库连接信息,并通过JdbcTemplate进行数据库操作,如插入、更新、删除和查询。
|
11天前
|
SQL Java 数据库连接
Springboot框架整合Spring Data JPA操作数据
Spring Data JPA是Spring基于ORM和JPA规范封装的框架,简化了数据库操作,提供增删改查等接口,并可通过方法名自动生成查询。集成到Spring Boot需添加相关依赖并配置数据库连接和JPA设置。基础用法包括定义实体类和Repository接口,通过Repository接口可直接进行数据操作。此外,JPA支持关键字查询,如通过`findByAuthor`自动转换为SQL的`WHERE author=?`查询。
|
11天前
|
安全 Java 开发者
在Spring框架中,IoC和AOP是如何实现的?
【4月更文挑战第30天】在Spring框架中,IoC和AOP是如何实现的?
21 0