Spring Web MVC 详解(1)

news2024/11/25 2:04:45

目录

一、介绍 MVC

二、Spring MVC 的三个基本功能

1.1 连接功能

1.2 Spring MVC 的创建和使用

1.3  @RequestMappig 介绍

1.4 Spring MVC 实现用户和 Spring 程序的连接

1.5 @GetMapping 和 @ PostMaping 注解

1.6 Get 和 Post请求注解的多种写法

2.1 获取请求中参数的功能

2.2 获取7种类型的参数

(1)获取一个参数

(2)获取多个参数

(3)获取一个对象

(4)获取一个 json 对象

(5)获取 URL中携带的参数

(6)上传一个文件

(7)参数重命名

1. 参数少传递:

2. 参数传递名称不一样:

3. 参数传递的顺序不同:

(8)Cookie 和 Session 以及 Header 的获取


前言

    Spring Web MVC 通常被称为 Spring MVC,是基于 Servlet API 构建的一个 Web 框架,前文介绍过的 Spring 项目的使用还不够,Spring 只是一个 IoC容器,将各种方法和类托管给 Spring,之后就需要和前端建立连接,所以 Spring MVC 可以实现和前端的交互,Spring MVC 就是 Spring 框架的核心模块,而 Spring Boot 是 Spring 框架的脚手架,是为了快速开发 Spring 项目的,这就是三者的区别。

一、介绍 MVC

    MVC 就是三个模块的缩写:Model(数据库模块),View(视图,也就是前端),Conller(控制器,校验前端请求的数据并向后端数据库发送数据)。

    MVC是一种模式,而 Spring MVC 是这种模式的具体实现,Spring MVC 实现了这种思想,并且基于 Servlet API 构建,形成的一个 Web 框架,有了Spring MVC 我们就可以和前端建立连接,然后基于 Spring MVC,实现一些业务逻辑。

二、Spring MVC 的三个基本功能

  • 1. 和浏览器建立连接
  • 2. 获取 URL 或请求中的参数
  • 3. 输出数据给浏览器

1.1 连接功能

     将浏览器和 Java 程序连接起来,当用户访问一个地址时,Spring MVC 可以帮我们实现 URL 和 Spring 中的业务代码连接起来

1.2 Spring MVC 的创建和使用

    首先创建一个 Spring 项目:

    然后添加起步依赖:(在添加完 devTools 外部 jar 包之后就已经是 Spring MVC 项目了)

      最后点击 Finish 即可。

1.3  @RequestMappig 介绍

    @RequestMapping 注解也是开发中很常用的注解,可以实现路由注册,所谓路由注册就是用户在浏览器中输入了一个 URL 之后,可以将用户的请求对应到 Spring MVC 项目中的某个类的某个方法,这个映射的过程就是 路由注册。

1.4 Spring MVC 实现用户和 Spring 程序的连接

    建立 UserController 类,写入 sayHi()方法,加上 @RequestMapping 和 @RestController 注解,如下代码:

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController2 {
    @RequestMapping("/user/sayHi")
    public String sayHi() {
        return "do sayHi()";
    }
}

    然后在程序启动类中启动项目,记住日志信息中的端口号,最后在浏览器中访问 路由映射的 url:

     注:可以看到上述代码是将 @RequestMapping 注解中的参数 设置了两个层级的路由,这是一种方式,还可以在类上加 @RequestMapping 注解然后设置 一个类的 路由地址,如果在一个类上设置了 @RequestMapping 注解,url 的格式就是 类 + 方法 的路由地址。

1.5 @GetMapping 和 @ PostMaping 注解

    在网络协议中介绍过,请求的方式有很多种,有get,post,put,delete 方法,而常用的请求方法就是 get 和 post 方法,那此时 @RequestMapping属于什么方式呢。可以使用 fiddle 抓包工具看一下:

     上图所示:请求的方法是 Get 方法,那如果是 Post 方法是否可行。可以使用 postman 模拟请求工具试一下,下图所示:

    注:在浏览器中输入的url 默认就是一个 Get 方法,所以要使用 Post 方式构造 http 请求就需要借助工具。

     上图所示,@RequestMapping 注解可以实现两种 http 请求 方式,但是如果某种业务需求下如果只能使用 Get 或者 Post 一种请求方式,此时就需要使用@GetMapping 和 @ PostMaping 注解或者给 @RequestMapping 加一个参数 来限制用户请求只能使用一种方式构造 http 请求:

     重启项目,再去访问 sayHi()方法之后:可以看到报405状态码,显示 get 方法请求不能访问:

1.6 Get 和 Post请求注解的多种写法

    Get请求的三种使用注解写法:

    @RequestMapping(value = "/user/sayHi", method = RequestMethod.GET)
    @GetMapping("/user/sayHi")
    @RequestMapping("/user/sayHi")

    Post请求的两种使用注解写法:

@RequestMapping("/user/sayHi")
@RequestMapping(value = "user/sayHi", method = RequestMethod.POST)

    使用上述请求方法的写法可以达到同样的效果。

2.1 获取请求中参数的功能

    当用户输入 URL后可以在 URL 中,也可以是在 http 请求中携带数据,这部分数据就是用户传过来的参数,Spring MVC 可以帮我们获取到这些各种各样的参数

2.2 获取7种类型的参数

(1)获取一个参数
(2)获取一个表单参数  /  获取多个参数
(3)获取一个普通对象
(4)获取一个 json 格式的对象
(5)获取 URL 中携带的参数
(6)上传一个文件
(7)Session 的存储和获取
  • (1)获取一个参数

package com.example.demo.controller;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController2 {
    @RequestMapping("/user/sayHi")
    public String sayHi(String name) {
        return "do sayHi() --> " + name;
    }
}

    注:此时在 URL 中传递的参数必须和 传递的形参名保持一致,否则无法获取到这个参数。

    浏览器访问 url 中加上 name 参数:

  • (2)获取多个参数

@RestController
public class UserController2 {
    @RequestMapping("/user/sayHi")
    public String sayHi(String name, String password) {
        return "do sayHi() --> " + name + "  " + password;
    }
}

     浏览器访问 url 中加上 name 和 passpord 参数:

     获取一个表单参数和获取多个参数是同样的写法,此处不再介绍。

  • (3)获取一个对象

    获取一个对象,首先在程序中要有一个实体类来作为数据传输的载体:

package com.example.demo.entity;
import lombok.Data;

@Data
public class Userinfo {
    private int id;
    private String name;
    private String password;
    private int age;
}

    之后在 Controller 层写入获取对象的方法:

@RequestMapping("/reg")
    public Object reg(Userinfo userinfo) {
        System.out.println(userinfo);
        return userinfo;
    }

     之后在浏览器中传入响应的参数即可 (注:此时不需要传递一个真正的对象,只需要把响应的参数写对,之后 Spirng MVC 框架就会帮我们自动实现 参数 和 对象属性 之间的映射,而且参数在返回的时候也是不需要指定返回的类型,因为 Object 类是所有类的父类,此时 框架在数据返回的时候也会帮我们进行 数据类型的判断,最后返回一个合适的类型

      我们可以写另一个方法来验证上述注意中的结论是否正确:

      在 Controller 层中写入方法:

@RequestMapping("/h1")
    public Object getH1() {
        return "<h1>我是h1标签</h1>";
    }

     可以看到上述代码中的 geth1 方法的返回类型是一个 Object 类型,但是通过下图中的抓包可以看到 响应的数据正文中的类型已经是 html 格式的类型了,所以不用设置 响应的数据类型,这些事情 Spring MVC 框架已经帮我们实现好了。

  •  (4)获取一个 json 对象

    注:如果前端传递的数据是一个json 对象,此时用一个 普通的对象来接收这个 json 对象是不可以拿到参数的。

    前端传递一个对象有两种方式:1. 构造一个 Ajax 请求来封装一个 json 对象。   2. 使用 postman 模拟请求工具构造一个带有 json 格式的对象 的请求。

    第二种方式是最简单的构造一个 json 对象,所以介绍下用 postman 来传递一个 json 对象:

    先在 Controller 层中写入 方法,此时用一个普通的对象这种形参是拿不到 json 格式的对象的;需要加一个 @RequestBody 注解来实现接收一个 json 对象 。

    @RequestBody 注解也很好理解:就是在一个请求正文中获取一个对象。

//传递一个json 对象
    //使用 @RequestBody 来获取
    @RequestMapping("/user/reg")
    public Object getJson(@RequestBody Userinfo userinfo) {
        System.out.println(userinfo);
        return userinfo;
    }

    用 postman 构造一个带有 json 对象的请求:

     用 fiddle 抓包工具抓以下看一下前端传递的是否是一个 json 对象:

  • (5)获取 URL中携带的参数

    注:此处的获取 URL 中的参数不是从 URL 参数部分获取参数,而是就在一个 URL 中获取参数。

    获取 URL 中的参数需要使用注解 @PathVariable,就是从路径中获取一个变量的 意思

     先在Controller 层中写入方法:

// 获取一个 URL 中的参数
    @RequestMapping("/reg2/{name}/{password}")
    public Object reg2(@PathVariable String name,@PathVariable String password) {
        return "name --> " + name + " password --> " + password;
    }

     之后在浏览器输入 URL:

     注:一种参数是 query string 的形式,在 ” ?“ 之后的参数,一种是在 url 中的参数,第一种方式的参数更加简洁,而且浏览器抓取关键字优先级更高(就是在浏览器中会在页面种优先显示),第二种 query string 的格式更适合传递多个参数。

    所以,如果是很少的参数,推荐使用第一种方式,如果参数很多,不推荐使用第一种方式。

  • (6)上传一个文件

    上传一个文件也需要使用注解:@RequestPart

//上传一个文件
    @RequestMapping("/myUpload")
    public Object upload(@RequestPart("myImg")MultipartFile file) {
        File saveFile = new File("D:\\home\\myImg.png");
        try {
            file.transferTo(saveFile);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

     使用 postman 模拟一个上传文件的请求:

      如果上传的文件不是图片或者有下沟通的文件名要上传两份,上述代码的写法就不合适了,就需要生成不同的文件名,最主要的就是文件名后缀,上传的文件可以是各种各样的文件,所以后缀名不能是固定的,应该是如下代码:

   (UUID中的 randomUUID() 方法可以生成一个唯一的文件名)

   (在文件IO中有 getOriginalFilename() 方法,就是获取原始的文件名,这个文件名中就包含了文件后缀名,然后通过字符串截取的方式来获取文件后缀名)

//上传一个文件
    @RequestMapping("/myUpload")
    public Object upload(@RequestPart("myImg")MultipartFile file) {
        String fileName = UUID.randomUUID() + //文件名
                file.getOriginalFilename().substring(// 文件名后缀
                        file.getOriginalFilename().lastIndexOf("."));
        File saveFile = new File("D:\\home\\myImg" + fileName);
        try {
            file.transferTo(saveFile);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    注:需要注意上传文件大小是有限制的,单次上传文件大小不能超过 1 MB,否则会报异常;如果上传的文件大小超过 1MB,此时可以在配置文件中设置 最大上传的文件大小;如下代码:

spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
  • (7)参数重命名

    上述几种传递参数的方式如果前端的参数没有传递过来 或者 传递的形参名称不一样 以及 参数的顺序不一致 会怎么样呢?

例如:在传递多个参数时,可以看下图的执行结果:

1. 参数少传递:

 2. 参数传递名称不一样:

 3. 参数传递的顺序不同:

     解决方法:加注解 @RequestParam 来实现后端参数的 映射 并且 设置 参数是否必须传递。

    如下代码:

 //传递多个参数
    @RequestMapping("/user/sayHi")
    public String sayHi(@RequestParam String name,@RequestParam String password) {
        return "do sayHi() --> " + name + "  password = " + password;
    }

    加注解之后,此时的参数就必须传递:

     如果参数名不一致,可以在注解的参数中设置重命名,然后设置一个参数是否为必须传递的参数:

//传递多个参数  & 参数重命名
    @RequestMapping("/user/sayHi")
    public String sayHi(@RequestParam String name,@RequestParam(value = "pwd", required = false) String password) {
        return "do sayHi() --> " + name + "  password = " + password;
    }

     @RequestParam 注解中的参数 required 默认值 就是 True,也就是只要后端有这个参数,在前端就必须传递过来;设置为 false 之后, pwd 这个参数就不是 必传的参数了

  • (8)Cookie 和 Session 以及 Header 的获取

    获取Cookie:

    此时需要加注解 @CookieValue,就是获取到 Cookie 中的 value 值,然后在前端设置 Cookie 字段即可(因为已经在注解的参数中指定 Cookie 的key 值了,所以在前端设置的 name 必须和此处是一样的)

//获取一个 cookie 对象
    @RequestMapping("/getCookie")
    public Object getSession(@CookieValue(name = "java", required = false) String java) {
        return java;
    }

    获取 Header:

    通过注解 @getHeader来实现 获取请求头部信息

//获取 Header 中的信息
    @RequestMapping("/getHeader")
    public String getHeader(@RequestHeader("User-Agent") String userAgent) {
        return "userAgent : " + userAgent;
    }

     在浏览器中找一个请求 Header 查看头部信息,之后将 Key 值复制到 代码中注解的参数中即可;如下图中运行结果:

     获取 Session:

    首先要想存储一个Session,需要先进行存储,之后才能获取到这个Session,但是存储Session 对象不能使用注解,前文中已经介绍过:Spring MVC 是基于 Servlet API 封装的框架,所以在存储 Session 会话时依然可以使用 servlet API 来存储 Session。如下代码:

private static final String SESSION_KEY = "USERINFO_SESSION_KEY";
    //存储一个 Session
    @RequestMapping("/setSession")
    public void doPostConstruct(HttpServletRequest request) {
        //此处需要允许创建一个 Session 会话,因为用户第一次登录是需要创建一个 Session 会话的,
        //只有在之后的用户再次的登录的校验中才不允许创建一个会话
        HttpSession session = request.getSession();//通过这个请求获取一个 Session
        session.setAttribute(SESSION_KEY, "张三");
    }

    //获取一个Session
    @RequestMapping("/getSession")
    public Object getSession(@SessionAttribute(SESSION_KEY) String name) {
         return "session -- > " + name;
    }

     由于 Spring MVC框架在进行初始化的时候,初始化的时机是在创建 HttpServletRequest 对象之前的,所以不能将 存储 Session 的业务写在初始化的方法中,因为在 Spring MVC 注入对象时,如果一个方法中有这个参数,就必须在初始化的时候将这个 参数 传递过来,所以我们需要用访问 路由的方式先存储一个 Session,然后再获取 Session 中的Key值,如下图所示:

     注:本文中没有介绍热部署,所以在获取参数时,修改代码之后需要重启项目才能看到正确的运行结果。

    最后就只剩下数据的返回了,下一篇文章再进行详细介绍。

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

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

相关文章

Redis的内存回收与内存淘汰策略

对于redis这样的内存型数据库而言&#xff0c;如何删除已过期的数据以及如何在内存满时回收内存是一项很重要的工作。 常见的redis内存回收的工作主要分为两个方面&#xff1a; 清理过期的key在内存不足时回收到足够的内存用以存储新的key 清理过期的key 我们很少在redis中…

直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序——“数据结构与算法”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是数据结构与算法啦&#xff0c;是排序&#xff01;&#xff01;&#xff01;下面&#xff0c;让我们进入七大排序的世界吧&#xff01;&#xff01;&#xff01; 排序的概念及其运用 排序的概念 排序&#xff1a;所谓排序…

算法提高-动态规划-斜率优化DP

斜率优化DP AcWing 300. 任务安排1AcWing 301. 任务安排2AcWing 302. 任务安排3AcWing 303. 运输小猫 AcWing 300. 任务安排1 #include <iostream> #include <cstring>typedef long long LL;using namespace std;const int N 5e3 10;int st[N], sc[N]; LL f[N];…

全志F1C200S嵌入式驱动开发(基于usb otg的spi-nor镜像烧入)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面既然已经搞定了spi-nor驱动,那么下一步考虑的就是怎么从spi-nor flash上面加载uboot、kernel和rootfs。目前spi-nor就是一块白片,上面肯定什么都没有,那么这个时候,我们要做…

贤鱼的刷题日常-P3375 【模板】KMP 字符串匹配

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;例题讲解P3375 【模板】KMP 字符串匹配 ✅创作者&#xff1a;贤鱼 ⏰预计时间&#xff1a;25分钟 &#x1f389;个人主页&#xff1a;贤鱼的个人主页 &#x1f525;专栏系列&#xff1a;c &#x1f341;贤鱼的个人社区&…

(css)清除el-table背景色

(css)清除el-table背景色 效果&#xff1a; <el-table:data"gridData":header-cell-style"{text-align:center,color: #fff}":cell-style"{text-align:center,color: #fff }" ><el-table-column type"index" label"序号…

linux下 UART串口相关

RS232的串口设备在linux 上会被识别为 /dev/ttyS* 或者 ttymxc* 一、串口简介 操作串口我们一般通过以下指令&#xff1a; 1、查看串口波特率等信息&#xff1a; stty -F /dev/ttyS0 -a #ttyS0为要查看的串口 2、设置串口参数&#xff1a; stty -F /dev/ttyS0 ispeed 115…

Qt实现双控制柄的Slider

目标 实现带有左右两个控制柄的滑动条&#xff1b;控件可设定最小值和最大值&#xff1b;控件可设定控制柄的最小距离&#xff1b; 效果演示 思路 1. 标准的Slider控件只有一个Handle&#xff0c;所以想要通过改造QSlider来实现两个Handle是非常困难的&#xff0c;“自绘”…

SpringBoot+jasypt-spring-boot-starter实现配置文件明文加密

1.使用环境 springboot:2.1.4.RELEASE JDK:8 jasypt-spring-boot-starter:3.0.2 2.引入依赖 !-- 配置文件加密 --> <dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><ver…

rust学习-智能指针

适用场景 有一个在编译时未知大小的类型&#xff0c;想在需要确切大小的上下文使用该类型值 示例1 无意义的例子&#xff1a;将一个单独的值存放在堆上并不是很有意义&#xff0c;b更应该放到栈上 fn main() {let b Box::new(5);// box 在 main 的末尾离开作用域时&#x…

R语言 PCA筛选变量

#PCA-筛选变量 X <- data[,2:415] pca <- prcomp(X, center TRUE, scale. TRUE) # 进行主成分分析 summary(pca) # 查看各个主成分的解释方差比例 library(factoextra) #碎石图依赖-fviz fviz_eig(pca,addlabelsT) #碎石图 X_selected <- pca$x[,1:20] # 选择前n个主…

pytorch实现图像投影变换

import cv2 import torchdef cpu_remap(numpy_img,mapx,mapy):return cv2.remap(numpy_img,mapx,mapy,cv2.INTER_LINEAR)def gpu_remap(numpy_img,map_tensor):numpy_img:原始图像格式为ndarraymap_tensor:[N,H,W,C]用于grid_sample的map参数&#xff0c;需要规制到-1到1# 准备…

opencv直方图

#include "iostream" #include "opencv2/opencv.hpp" using namespace std; using namespace cv;int main() {Mat img, gray;img imread("r4.jpg");cvtColor(img, gray, COLOR_BGR2GRAY);int nimages 1;//图片数量const int channels[] { 0 …

信捷PLC RC低通滤波器(C语言实现)

PLC信号处理系列之RC低通滤波器算法详细介绍请参考下面文章: PLC信号处理系列之一阶低通(RC)滤波器算法_plc滤波算法程序_RXXW_Dor的博客-CSDN博客1、先看看RC滤波的优缺点 优点:采用数字滤波算法来实现动态的RC滤波,则能很好的克服模拟滤波器的缺点; 1、在模拟常数要求较…

位域与共用体在通讯领域的应用

最近看到些代码&#xff0c;定义变量还能指定位宽&#xff0c;很有意思。像这样 unsigned int bit1 : 1;冒号 (&#x1f603; 后面的数字1表示变量的位宽或大小。 像这样的大小声明在低级编程和位操作中常被使用&#xff0c;以便精确控制变量的大小。 通讯协议解析用的多。 下面…

电脑安装双系统ubuntu18.04+windows后开机直接进入Windows解决方法

电脑型号&#xff1a;联想拯救者Y9000K2021H 系统&#xff1a;Windows11Ubuntu18.04双系统 问题&#xff1a;笔记本安装双系统后&#xff0c;Windows系统下处理word或者看论文&#xff1b;Ubuntu18.04系统安装ros进行机械臂控制等的研究。但最近开机后发现没有系统选项了&#…

【mars3d】将mars3d中的示例拷贝到自己项目中

mars3d 的功能示例 - 感觉做了很多的处理&#xff1b; 1、头部的按钮作用 重置和运行 - 这就是字面意思&#xff0c;都能理解哈&#xff1b; js - 顾名思义&#xff0c;js代码&#xff0c;也是我们可以改动的部分&#xff1b; 旁边那个 - 是vue部分&#xff0c;是不能修改的…

J2EE通用分页01

目录 一.总体思路 二.分页信息实体&#xff08;PageBean&#xff09; 三.后台分页数据查询 3.1 处理流程 流程图&#xff1a; 3.2 实现 Student实体&#xff0c;及对应的数据库表可自行准备 四.重构-提取公用方法 1.为了进行公共方法的抽取&#xff0c;需要找出上面实…

Transformer 模型实用介绍:BERT

动动发财的小手&#xff0c;点个赞吧&#xff01; 在 NLP 中&#xff0c;Transformer 模型架构是一场革命&#xff0c;极大地增强了理解和生成文本信息的能力。 在本教程[1]中&#xff0c;我们将深入研究 BERT&#xff08;一种著名的基于 Transformer 的模型&#xff09;&#…

uniapp app运行到ios详细流程

uniapp运行到IOS真机调试&#xff08;windows系统&#xff09; 工具步骤1.首先数据线连接电脑和手机2.右键点击桌面上的HBuilder&#xff0c;打开文件所在位置3.打开HBuilder编辑器里要运行的项目&#xff0c;点击运行>运行到手机或模拟器>运行到IOS APP基座>勾选你的…