9. Spring MVC

news2024/9/29 3:30:26

目录

1. Spring MVC 介绍

1.1 MVC 定义

1.2 MVC 和 Spring MVC 的关系

1.3  Spring、Spring Boot 和 Spring MVC 的关系

2. Spring MVC 的创建和连接

2.1 Spring MVC 项目返回视图 

2.2 Spring MVC 项目返回数据

2.3 @RequestMapping 是 post 还是 get 请求

3. 获取参数

3.1 接收单个参数

3.2 接收多个参数

3.3 接收对象

3.4 接收表单

3.5 后端参数重命名

3.6 改成非必传参数

3.7 接收 JSON 对象 

3.8 获取 url 中的参数

3.8 上传文件

3.9 获取 Cookie

3.10 获取 Session/header

3.11 获取 Header

4. 返回数据

4.1 返回静态页面

4.2 返回 text/html

4.3 返回 JSON 对象

4.4 请求转发或请求重定向


1. Spring MVC 介绍

Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从一开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来自其源模块的名称(Spring-webmvc),但它通常被称为“Spring MVC”。

由上述可知:

  1. Spring MVC 是一个 Web 框架
  2. Spring MVC 是基于 Servlet API 构建

1.1 MVC 定义

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

  • Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
  • View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
  • Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据, 控制用户输入,并向模型发送数据。

现在的 Spring MVC 更合适称之为 Spring Web,因为现在很多项目都使用了前后端分离。

1.2 MVC 和 Spring MVC 的关系

MVC 是⼀种思想,而 Spring MVC 是对 MVC 思想的具体实现。

总结来说,Spring MVC 实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。既然是 Web 框架,那么当用户在浏览器中输入了 url 之后,我们的 Spring MVC 项目就可以感知到用户的请求。

1.3  Spring、Spring Boot 和 Spring MVC 的关系

  • Spring:包含了众多工具的 IoC 容器;
  • Spring Boot:是简化 Spring 程序的;
  • Spring MVC:使程序具备了 web 的能力。

现在绝大部分的 Java 项目都是基于 Spring(或 Spring Boot)的,而 Spring 的核心就是 Spring MVC。也就是说 Spring MVC 是 Spring 框架的核心模块,而 Spring Boot 是 Spring 的脚手架

2. Spring MVC 的创建和连接

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

在 Spring MVC 中使用 @RequestMapping 来实现 URL 路由映射,也就是浏览器连接程序的作用。

接下来我们来创建 Spring MVC 项目:

2.1 Spring MVC 项目返回视图 

早期的 Spring MVC 项目返回的是视图。 

接下来,我们来看一下早期的 Spring MVC 项目是如何创建和连接的。

首先,导入 jar 包后,新建 WebController 类:

@RequestMapping("/web")
public class WebController {
    
    @RequestMapping("/index")
    public String index(){
        return "hello,Spring MVC";
    }
}

 但是此时我们运行程序后,进行访问发现并不能成功访问:

因为我们只做了路径的映射,但是并没有交给 Spring 去管理,因此需要通过五大注解(@Bean)将 Bean 交给 Spring 去管理,修改代码如下:

@Controller
@RequestMapping("/web")
public class WebController {

    @RequestMapping("/index")
    public String index(){
        return "hello,Spring MVC";
    }
}

但是,可以看到依然无法进行访问:

因为现在的 Spring MVC 项目采用的是前后端分离的思想,返回的不再是视图而是数据,@Controller 表示的是返回一个视图,因此我们新建一个 html  文件来接收:

@Controller
@RequestMapping("/web")
public class WebController {

    @RequestMapping("/index")
    public String index(){
        return "/index.html";
    }
}

 此时可以看到视图可以返回:

2.2 Spring MVC 项目返回数据

在早期的 Spring MVC 项目中,返回的都是视图,那么如果我们想返回数据该怎么处理呢?

使用 @ResponseBody 注解

@Controller
@RequestMapping("/web")
public class WebController {
    @ResponseBody
    @RequestMapping("/index")
    public String indexData(){
        return "hello,Spring MVC";
    }
}

此时,我们可以看到成功返回了数据: 

通过 url:http://127.0.0.1:8080/web/indexData

我们可以知道 @RequestMapping 即是方法注解,又是类注解,访问的 url 等于类注解加上方法注解。

通过组合注解:@RestController = @ResponseBody + @Controller,同样可以实现返回数据:

@ResetController
@RequestMapping("/web")
public class WebController {

    @RequestMapping("/index")
    public String indexData(){
        return "hello,Spring MVC";
    }
}

@RestController 是类注解,表示该类下的所有方法返回的都是数据,而不是界面。

因此,如果一个类里面的方法,既有返回页面又有返回数据的,就不可以使用 @ResetController 注解。

那么既然是通过五大注解交给 Spring 管理的,我们可以把 @Controller 注解换成其他注解是否可以呢?

答案是否定的。因为只有 @Controller 才可以保证被外界访问到

2.3 @RequestMapping 是 post 还是 get 请求

我们通过 Postman 来测试一下: 

可以看到 @RequestMapping 同时支持 GET 和 POST 请求,那么如果只希望它支持 GET 请求呢?

@Controller
@RequestMapping("/web")
public class WebController {

    @ResponseBody
    @RequestMapping(value = "/indexData",method = RequestMethod.GET)
    public String indexData(){
        return "hello,Spring MVC";
    }
}

可以看到此时无法再使用 POST 请求:

设置为只可以使用 POST 请求: 

@Controller
@RequestMapping("/web")
public class WebController {

    @ResponseBody
    @RequestMapping(value = "/indexData",method = RequestMethod.POST)
    public String indexData(){
        return "hello,Spring MVC";
    }
}

只允许 GET 请求:

// 写法一
@RequestMapping("/indexData")
// 写法二
@RequestMapping(value = "/indexData",method = RequestMethod.GET)
// 写法三
@GetMapping("/indexData")

 只允许 POST 请求:

// 写法一
@RequestMapping(value = "/indexData",method = RequestMethod.POST)
// 写法二
@PostMapping("/indexData")

3. 获取参数

3.1 接收单个参数

在 Servlet 阶段,通过以下代码来获取参数:

@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get1")
    public String get1(HttpServletRequest request){
        String name = request.getParameter("name");
        return "name:"+name;
    }
}

我们运行后可以看到:

那么,在 Spring 中,我们如何获取参数呢?

@RestController
@RequestMapping("/param")
public class ParamController {

    @RequestMapping("/get2")
    public String get2(String name){
        return "name:"+name;
    }
}

可以看到通过以上代码,我们可以直接获取到:

3.2 接收多个参数

@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get3")
    public String get2(String name,Integer age){
        return "name:"+name + "| age:"+age;
    }
}

可以看到将两个参数的位置互换之后,结果依然不变:

也就是说参数的顺序和 url 传参的顺序无关。

@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get4")
    public String get4(Integer age){
        return "age:"+age;
    }
}

正确传参:正确响应

不传参:age = null

错误传参: age = aa 

3.3 接收对象

当参数非常多的时候,一个一个写不太现实,同时会导致数据之间的耦合度太高,因此,我们可以将参数封装成一个对象。

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
}
@RestController
@RequestMapping("/param")
public class ParamController {

    @RequestMapping("/get5")
    public String get5(Student student){
        return student.toString();
    }
}

3.4 接收表单

表单是前端传参的方式,与接收参数的方式无关。接下来我们通过 postman 模拟表单发送:

可以看到同样可以接收到数据,通过 fillder 抓包可以看到:

3.5 后端参数重命名

@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get6")
    public String get6(@RequestParam("n") String name){
        return "name: " +name;
    }
}

把调用方发送的参数 n 重命名为 name。

3.6 改成非必传参数

可以看到将 n 改为 name 进行传递时,会出现以下报错:

说明了 n 是一个必传参数,但是我们没有传递,才导致以上报错。因此,我们可以将 n 修改为非必传参数:

@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get7")
    public String get7(@RequestParam(name = "n",required = false) String name){
        return "name: " +name;
    }
}

 此时,页面显示如下:

3.7 接收 JSON 对象 

使用 postman 发送 json: 

使用 fillder 抓包:

可以看到成功传递了 json 对象。

@Slf4j
@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get8")
    public String get8(@RequestBody Student student){
        log.info(student.toString());
        return student.toString();
    }
}

@RequestBody 表示接收的是 json 字符串。Spring 会将字符串转为 json 对象。

3.8 获取 url 中的参数

@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get9/{shopid}")
    public String get9(@PathVariable Integer shopid){
        return "shopid:" + shopid;
    }
}

 通过 postman 可以看到,成功从 url 中获取了参数:

还可以重新命名参数的名称:

@RestController
@RequestMapping("/param")
public class ParamController {
   @RequestMapping("/get9/{shopid}/{dealid}")
    public String get9(@PathVariable Integer shopid,@PathVariable("dealid")Integer dealId){
        return "shopId:" + shopid +"| dealId:" + dealId;
    }
}

同样可以获取到:

3.8 上传文件

@Slf4j
@RestController
@RequestMapping("/param")
public class ParamController {

    @RequestMapping("/get10")
    public String get10(@RequestPart("file") MultipartFile file) throws IOException {
        log.info(file.getOriginalFilename());
        file.transferTo(new File("D:/temp/"+file.getOriginalFilename()));
        return "success";
    }
}

此时,我们的文件夹下并没有任何文件: 

 

接下来,我们通过 postman 来上传文件:

此时看到 D 盘相应文件上传成功:

在 Fillder 中同样可以看到上传文件成功了:

3.9 获取 Cookie

@Slf4j
@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get11")
    public String get11(@CookieValue String value){
        return "value:"+value;
    }
}

可以看到出现以下报错:

接下来,我们按下 f12 进行设置:

然后刷新界面接可以看到获取到了 Cookie 值:

由上述可知:Cookie 是可以自行设置的。Cookie 是存在于客户端的,因此再次重启服务端(重新运行程序)获取的值依然不变。

3.10 获取 Session/header

@Slf4j
@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get12")
    public String get12(@SessionAttribute(required = false) String username){
        return "username:"+username;
    }
}

在 @SessionAttribute 注解加上:required = false(设置为非必传参数),可以看到在没有值时,不会进行报错,而是直接显示为 null。

运行上述代码后可以看到:

接下来,我们需要获取 Session 的值,Session 的值不能人为设置。

@Slf4j
@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get12")
    public String get12(@SessionAttribute(required = false) String username){
        return "username:"+username;
    }
    @RequestMapping("/set1")
    public String set1(HttpSession session){
        session.setAttribute("username","value");
        return "success";
    }
}

设置后,Cookie 中多了一个 Sessionid。此时,我们来获取这个 session :

3.11 获取 Header

@Slf4j
@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get13")
    public String get13(@RequestHeader("User-Agent") String userAgent){
        return "userAgent"+userAgent;
    }
}

 在 fidder 中可以看到两者值相同:

4. 返回数据

4.1 返回静态页面

在没有加上注解  @ResponseBody 时,返回的就是页面:

4.2 返回 text/html

4.3 返回 JSON 对象

@Slf4j
@RestController
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/get14")
    public Map<String,String> get14(){
        Map<String,String> map = new HashMap<>();
        map.put("k1","v1");
        map.put("k2","v2");
        map.put("k3","v3");
        map.put("k4","v4");
        map.put("k5","v5");
        return map;
    }
}

4.4 请求转发或请求重定向

return 不但可以返回一个视图还可以实现跳转,跳转的方式有两种:

  • forward:请求转发
  • redirect:请求重定向

forward 和 redirect 具体区别如下:

  1.  请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
  2.  请求重定向地址发生变化,请求转发地址不发生变化。
  3.  请求重定向与直接访问新地址效果一致,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问。 

也就是说,请求转发时服务器进行转发,是由服务器内部进行处理的;而请求重定向时请求资源重定向,是对外的。

@Controller
@RequestMapping("/index")
public class IndexController {
    @RequestMapping("/forward")
    public String forward(){
        return "forward:index.html";
    }
    @RequestMapping("/redirect")
    public String redirect(){
        return "redirect:index.html";
    }
}

请求转发(forward):

请求重定向(redirect):

可以看到,请求转发的 url 并未发生变化,而请求重定向的 url 跳转到了另一个界面。 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/803738.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PX4固件报错“Accel 0 clipping, not safe to fly!“

最近在使用PX4固件时&#xff0c;遇到了报错&#xff1a; “Accel 0 clipping, not safe to fly!” 这个报错我以前是从没遇到过的&#xff0c;可见是新版固件才会有的。 正常来说&#xff0c;只有山寨乞丐版飞控才会经常出现这类传感器的报错。 但是我手里的是5000多的X7 pro&…

使用多数据源dynamic-datasource-spring-boot-starter遇到的问题记录

记录使用多数据源dynamic-datasource-spring-boot-starter遇到的问题&#xff1a; 1、工程启动失败 缺少clickhouse连接驱动&#xff0c;引入对应的maven依赖 <!--ck连接驱动--><dependency><groupId>ru.yandex.clickhouse</groupId><artifactId>…

没有颜值插件的编辑器是没有灵魂的--【idea-theme插件】

文章目录 本系列校训idea安装程序员常用软件工具推荐1.JetBrains全家桶2.Microsoft Visual Studio3.eclise 系列 先看一下VS Code 的特色idea 系列 的颜值插件idea插件安装Material_ThemeMaterail 家自己的themes主题免费的版本在前面 本系列校训 颜值即正义&#xff01;你漂亮…

浅谈性能测试中的基准测试

在性能测试中有一种测试类型叫做基准测试。这篇文章&#xff0c;就聊聊关于基准测试的一些事儿。 1、定义 通过设计合理的测试方法&#xff0c;选用合适的测试工具和被测系统&#xff0c;实现对某个特定目标场景的某项性能指标进行定量的和可对比的测试。 2、特质 ①、可重…

SUI供应量等问题的说明以及终止与MovEX的合作声明

原生加密token是区块链经济系统的基石&#xff0c;对网络的安全、运作和增长至关重要。Sui的原生token SUI有如下四个关键用途&#xff1a; 质押给验证节点&#xff0c;以确保网络的安全&#xff0c;并赚取质押奖励用于支付gas费&#xff0c;以执行交易和其他操作作为原生资产&…

用python怎么输出个人信息,python怎么输出个人信息

大家好&#xff0c;给大家分享一下python输入自己的姓名,输出hello,某某某同学&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 1、python要求用户输入姓名并输出 name input("请输入姓名:") print("你好,"&#xff…

MSFCS互相联动

MSF&CS互相联动 1. 前言2. CS联动MSF2.1. 案例测试2.1.1. CS设置联动监听器2.1.2. CS设置联动MSF会话2.1.3. MSF设置监听 3. MSF联动CS3.1. 案例测试3.1.1. MSF生成木马3.1.2. 设置监听3.1.3. CS设置监听3.1.4. MSF转移会话3.1.5. 查看上线 4. 其它 1. 前言 在日常渗透测试…

【单片机】温控系统参数辨识及单片机PID控制

温控系统参数辨识及单片机PID控制 1. 温控系统组成2. matlab辨识系统参数2.1 采集阶跃响应信号导入matlab系统辨识模块 PID控制 1. 温控系统组成 半导体制冷片正向通电制冷&#xff0c;反向通电制热。系统采用半导体制冷片&#xff08;帕尔贴&#xff09;作为执行单元&#xf…

使用adb通过电脑给安卓设备安装apk文件

最近碰到要在开发板上安装软件的问题&#xff0c;由于是开发板上的安卓系统没有解析apk文件的工具&#xff0c;所以无法通过直接打开apk文件来安装软件。因此查询各种资料后发现可以使用adb工具&#xff0c;这样一来可以在电脑上给安卓设备安装软件。 ADB 就是连接 Android 手…

C++中对 this 指针的理解

引出 我们首先了解this指针&#xff0c;要先了解class&#xff08;类&#xff09;&#xff0c;类其实就相当于C语言中的结构体一样&#xff0c;也是创建了一个自定义类型。对于类而言该类型下面可以存放成员函数&#xff0c;成员变量。类可以声明一个变量&#xff0c;对该变量…

数据结构---LRU CACHE

什么是LRU 通过之前的学习我们知道计算机在处理任务的时候是先将数据从硬盘中提取出来加载进内存&#xff0c;然后再将内存中的数据加载进入cpu进行计算&#xff0c;但是这里存在一个问题cpu的计算速度非常快&#xff0c;而内存中加载数据的速度又很慢&#xff0c;所以为了提供…

Mysql-事务、视图和索引

目录 事务 操作 步骤 特性 并发事务问题 事务隔离级别 索引 作用 分类 主键索引&#xff08;PRIMARY KEY&#xff09; 唯一索引&#xff08;UNIQUE&#xff09; 常规索引&#xff08;INDEX&#xff09; 全文索引&#xff08;FULLTEXT&#xff09; 管理索引 数据…

2023-07-28 LeetCode每日一题(并行课程 III)

2023-07-28每日一题 一、题目编号 2050. 并行课程 III二、题目链接 点击跳转到题目位置 三、题目描述 给你一个整数 n &#xff0c;表示有 n 节课&#xff0c;课程编号从 1 到 n 。同时给你一个二维整数数组 relations &#xff0c;其中 relations[j] [prevCoursej, next…

CS5212/CS5202|国产DP转VGA芯片|DP转VGA单转方案芯片

CS5212/CS5202是集睿致远推出的一款国产DP转VGA方案芯片&#xff0c;可替代替代RTD2166&#xff0c;替代IT6516芯片方案&#xff0c;相比之下CS5212/CS5202外围器件少&#xff0c;设计版框尺寸小。 CS5212/CS5202 DP转VGA方案原理图 CS5202特性 支持2通道数字输入&#xff0c…

一封来自Java学姐的信

黑马JavaEE学科学姐想对学弟学妹们说&#xff1a;勤学如春起之苗&#xff0c;不见其增&#xff0c;日有所长。 辍学如磨刀之石&#xff0c;不见其损&#xff0c;日有所亏。 学科 | JavaEE 校区 | 太原 亲爱的学弟学妹们&#xff0c;在学校“混日子”的时间很快就过去了&…

虚拟演播室:Aximmetry Broadcast DE 2023 Crack

Aximmetry 的基于节点的编辑器可以根据您的特定项目进行塑造&#xff0c;从而在实现项目时提供更大的灵活性&#xff1b;无论是广播制作、虚拟活动、预可视化、基于 LED 墙的虚拟制作还是您可以想象的任何其他 3D 图形任务。有关 XR 的更多信息。Aximmetry 还拥有自己的先进色度…

matlab BP神经网络对iris数据集进行分类

iris数据集 本文所用数据集&#x1f449;&#x1f449;&#x1f449;iris分类数据集 1.数据预处理 %% 1.数据预处理 oridatareadtable(Iris.xls,Sheet,Sheet1); Xtable2array(oridata(:,(1:4))); % X转化为array类型 Ytable2array(oridata(:,5)); % Y因为包含中文字符&…

如何彻底卸载VMware

目录 第一章、停止并卸载VMware程序1.1&#xff09;停止VMware有关的服务1.2&#xff09;打开任务管理器停止进程1.3&#xff09;卸载VMware程序 第二章、残留文件删除2.1&#xff09;打开注册表2.2&#xff09;删除注册表残留文件2.3&#xff09;C盘文件删除 友情提醒&#xf…

单机环境下定时任务的基本原理和常见解决方案(二)之时间轮原理分析

单机环境下定时任务的基本原理和常见解决方案之时间轮原理分析 时间轮Netty时间轮使用Netty 时间轮 HashedWheelTimer 源码分析向时间轮里添加taskWorkerThread线程执行时间轮任务 多层时间轮总结 时间轮 生活中的时钟想必大家都不陌生&#xff0c;而时间轮的设计思想就是来源…

【3】-使用@task设置测试用例执行的权重

多个测试链路压测使测试任务按预想的比例执行 locust的task装饰器提供了入参weight&#xff0c;locust执行测试任务时&#xff0c;会根据weight的比例进行分配用户数 from locust import task, HttpUserclass MyTestUser(HttpUser):# test_01 : test_02 3 : 1task(3)def wei…