IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 深入理解 Spring MVC Controller —— 请求参数获取 -> 正文阅读

[Java知识库]深入理解 Spring MVC Controller —— 请求参数获取

前言

接上篇《深入理解 Spring MVC Controller —— 请求映射》,上篇主要介绍了处理器方法及请求映射的定义。有了处理器方法 Spring MVC 就可以对请求进行处理,有了请求映射 Spring MVC 就能知道哪些请求应该由哪些处理器方法来处理。

Spring MVC 中对请求进行处理,除了定义处理器方法以及请求映射,我们还需要关心的一个问题是如何接收请求有关的参数,因为不同的参数往往伴随着不同的业务逻辑。

由于请求参数获取的内容较多,这篇我们先来了解 Spring MVC 常见的参数获取方式,下篇我们再深入分析并实战如何利用请求参数优雅获取登录用户信息。

前方高能预警:作为基础内容,本篇篇幅略长,可先收藏等有时间再查阅。

请求参数获取

传统的 Java Web 项目,我们通常通过 HttpServletRequest 来获取请求相关的参数。Spring MVC 简化了请求参数的获取方式,直接将请求参数定义为处理器方法参数即可。

当处理器方法被 Spring MVC 调用时,Spring MVC 会尝试根据请求上下文信息解析出给定类型的方法参数值,并自动进行类型转换参数校验,因此方法参数还可以定义为除字符串类型的其他类型。默认情况下处理器方法中可以定义的请求参数如下。

表单参数

表单参数可能是在 Spring MVC 中使用最频繁的请求参数之一了。

Http 协议中的表单大概可以分为两类,一类是 application/x-www-from-urlencoded,请求中只能携带字符串形式的参数值,另一类是 multipart/form-data,请求中除了携带字符串形式的参数值还可以携带文件。

Spring MVC 对字符串参数值和文件参数值有不同的处理方式。

表单单个普通参数获取

  • @RequestParam 注解指定请求参数

对于表单的单个普通参数获取,可以直接在处理器方法参数上添加 @RequestParam 注解并指定参数名,接收的是 GET 请求方式查询字符串上的参数或 POST 请求方式表单上的某一个参数。

Spring MVC 并未限制 @RequestParam 标注的处理器方法参数的类型,只要内部支持类型转换即可,方法参数类型通常来说为简单类型。简单类型包括基本类型及其包装类型、Enum、CharSequence、Number、Date、Temporal、URI、URL、Locale、Class 类型。

示例代码如下。

    @PostMapping("/login")
    public Result<LoginBO> login(@RequestParam("username") String username, @RequestParam("password") String password) {
        return Result.ok(userService.login(username, password));
    }

示例代码提供了登录功能,并获取了用户名和密码。

如果 JDK 版本在 1.8 以上使用 javac 编译时还可以添加 -parameters 参数,这样 @RequestParam 可以省略参数名,Spring MVC 会根据方法参数名获取参数值。

注意:如果想使用 Map 作为方法类型接收单个参数值,@RequestParam 必须指定参数名,否则 Map 方法参数接收的是所有的表单参数。

  • 简单类型直接接收请求参数

类型为简单类型的处理器方法参数可以直接接收表单中的单个参数,方法参数名就是接收的参数名,注意此时方法参数上不能存在 @RequestParam 注解及 @RequestPart 注解。

表单单个文件参数获取

  • @RequestPart 指定文件参数

如果想要接收用户上传的文件,可以将 Multipart 相关类型直接定义为处理器方法参数的类型,然后使用 @RequestPart 指定请求参数名。

Multipart 相关的参数类型如下:

  1. MultipartFile、Collection<MultipartFile>、List<MultipartFile>、MultipartFile[] 类型参数。
  2. Part、Collection<Part>、List<Part>、Part[] 类型参数。

示例代码如下。

    @PostMapping("/upload")
    public Result<UploadBO> upload(@RequestPart("file") MultipartFile file) {
        return Result.ok(fileService.upload(file));
    }
  • Multipart 相关类型直接接收文件参数

除了使用 @RequestPart 注解指定参数名,还可以直接将 Multipart 相关类型直接定义为处理器方法参数,方法参数名就是请求参数名,注意此时方法参数上不能携带 @RequestParam 注解及 @RequestPart 注解。

所有表单参数获取

如果想要一次性获取所有的请求参数,而不是根据请求参数名获取,可以将处理器方法参数定义为 Map 或 MultiValueMap,然后使用 @RequestParam 注解标注方法参数,此时 @RequestParam 不能指定参数名。

具体可以使用的泛型类型如下。

  1. MultiValueMap<String, String>、MultiValueMap<String, MultipartFile>、MultiValueMap<String, Part>
  2. Map<String, String>、Map<String, Part>、Map<String, MultipartFile>

由于泛型的值只能为 String、MultipartFile、Part,因此普通表单参数和文件表单参数需要分别接收。

示例代码如下。

    @PostMapping("/upload")
    public Result<UploadBO> upload(@RequestParam Map<String, MultipartFile> files, @RequestParam Map<String, String> extra) {
        return null;
    }

可选请求参数

如果认为方法参数表示的表单请求参数是可选的,可以将 @RequestParamrequired 属性值指定为 false,表示该参数是可选的,除此之外还可以用 Optional 类型接收请求参数。示例代码如下。

    @PostMapping("/login")
    public Result<LoginBO> login(@RequestParam(value = "username", required = false) String username, @RequestParam("password") Optional<String> password) {
        return Result.ok(userService.login(username, password));
    }

请求头参数

Spring MVC 中,如果想要获取请求头中的单个参数值,可以使用 @RequestHeader 指定请求头,并标注在处理器方法参数上。与 @RequestParam 注解类似,请求头的名称也可以省略,此时将方法参数作为请求头的名称。示例代码如下。

    @PostMapping("/upload")
    public Result<UploadBO> upload(@RequestHeader("token") String token) {
        return null;
    }

如果想要一次性获取所有的请求头,可以使用 Map 类型作为处理器方法参数,Map 的 key 和 value 都为 String 类型,此时 @RequestHeader 注解不必指定请求头,示例代码如下。

    @PostMapping("/upload")
    public Result<UploadBO> upload(@RequestHeader Map<String, String> header1,@RequestHeader MultiValueMap<String, String> header2) {
        return null;
    }

默认情况 @RequestHeader 表示的请求头必须存在,如果是可选的,可以设置 @RequestHeader(required = false) 或使用 Optional 类型接收请求头。

Cookie 参数

请求头中可能包含多个 cookie 信息,如果直接获取 Cookie 请求头的值然后再解析会比较麻烦。

Spring MVC 支持使用 String 类型或 Cookie 类型作为处理器方法参数类型来接收 Cookie信息,在方法参数上添加 @CookieValue 注解指定 Cookie 的名称即可。

如果省略 Cookie 名称则方法参数名作为 Cookie 名称。示例代码如下。

    @PostMapping("/upload")
    public Result<UploadBO> upload(@CookieValue("username") String username, @CookieValue Cookie password) {
        return null;
    }

默认情况 @CookieValue 表示的 Cookie 必须存在,如果是可选的,可以设置 @CookieValue(required = false) 或使用 Optional 类型接收 Cookie。

路径变量

路径变量常用于 RESTFUL 风格的接口中,路径的值可以作为一个参数值,此时我们需要在映射路径中指定路径变量的名称,然后使用处理器方法参数接收。处理器方法参数上添加 @PathVariable 注解指定路径变量名即可,同样变量名也可以忽略,此时方法参数名作为路径变量名。示例代码如下。

    @GetMapping("/user/{userId}")
    public Result<?> getUser(@PathVariable("userId") String userId) {
        return null;
    }

默认情况 @PathVariable 表示的路径变量必须存在,如果是可选的,可以设置 @PathVariable(required = false) 或使用 Optional 类型接收路径变量。

矩阵变量

矩阵变量和路径变量类似,变量同样定义在路径中,但是使用较少。可以使用@MatrixVariable 注解标注的处理器方法参数接收矩阵变量,方法参数类型可以为简单类型,也可以为 Map。

Spring 5.2 版本及以下需要手动开启矩阵变量支持,配置如下。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

处理器方法参数类型为 Map 的情况,@MatrixVariable 如果指定了 name,则 Map 接收的是单个矩阵变量的值。处理器方法参数获取单个矩阵变量值的示例代码如下。

    @GetMapping("/user{basic}/info")
    public Result<?> getUser(@MatrixVariable(name = "basic") String basic) {
        return Result.ok(basic);
    }

对于请求路径 /user;basic=zhangsan;/info,处理器方法参数 basic 接收到的值为 zhangsan

处理器方法参数类型为 Map 的情况,@MatrixVariable 如果没有指定 name,可以使用 pathVar 指定请求映射路径中的变量名, 此时 Map 接收的是多个矩阵变量。处理器方法参数获取多个矩阵变量的示例代码如下。

    @GetMapping("/user{basic}/info")
    public Result<?> getUser(@MatrixVariable(pathVar = "basic") Map<String, String> basic) {
        return Result.ok(basic);
    }

对于请求路径 /user;name=zhangsan;age=20/info ,处理器方法参数 basic 接收到的值为 { "name": "zhangsan", "age": "20" }

默认情况 @MatrixVariable 表示的矩阵变量必须存在,如果是可选的,可以设置 @MatrixVariable(required = false) 或使用 Optional 类型接收矩阵变量。

请求体参数

对于请求体,可以使用 @RequestBody 标注的处理器方法参数接收。示例代码如下。

@Data
public class User {
    private Long id;
    private String name;
}

@RestController
public class UserController {

    @GetMapping("/user/update")
    public Result<?> updateUser(@RequestBody User user) {
        return null;
    }

}

默认情况 @RequestBody 表示的请求头必须存在,如果是可选的,可以设置 @RequestBody(required = false) 或使用 Optional 类型接收请求体。

其他处理器方法参数

除了用于接收请求参数的处理器方法参数,Spring MVC 还支持定义一些其他的处理器方法参数。这里简单做一些介绍。

Request 相关参数

Request 相关参数表示 request 本身或其基本信息。

  • Spring MVC 支持的与 request 有关的处理器方法参数类型包括:
    • WebRequest、ServletRequest、MultipartRequest、HttpSession、PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId。
    • HttpEntity、RequestEntity。
    • SessionStatus。
  • 除了上面的参数,Spring MVC 还支持获取 request attribute 中的参数,使用 @RequestAttribute 标注处理器方法参数即可,这可以获取过滤器或拦截中使用 ServletRequest#setAttribute 设置的参数。

Response 相关参数

resposne 相关参数表示 response 本身或其基本信息。

Spring MVC 支持的处理器方法参数类型包括: ServletResponse、OutputStream、Writer。

Model 相关参数

Model 是 MVC 中的概念,是 View 使用的数据,在 Spring MVC 中,不同的 View 实现,Spring 可能会将 Model 数据存至不同的地方,对于 JSP 页面来说,Spring MVC 就把 Model 数据存到了 request attribute 中。

Spring MVC 中可以使用 Model 或 Map 类型接收 model 参数,然后将数据存至 model 中即可。示例代码如下。

    @GetMapping("/user/update")
    public Result<?> updateUser(Model model1, Map<String, Object> model2) {
        return null;
    }

在处理器方法执行前,Spring MVC 还会先执行 controller advice bean 和当前 controller 标注了 @ModelAttribute 注解的方法,并将返回值存入 Model 中,由于目前 Model 使用较少,不再加以赘述。

校验相关参数

Spring MVC 中如果想对请求参数进行校验,直接在处理器方法参数上添加 @Validated 注解即可,校验结果则可以定义一个类型为 Errors 的处理器方法参数接收。更多参数校验内容,可以参考我前面文章《Spring 参数校验最佳实践及原理解析》

这里给出一个简单的示例代码。

@Data
public class User {

    @NotNull(message = "id不能为空")
    private Long id;

    @NotBlank(message = "名称不能为空")
    private String name;

}

@RestController
public class UserController {

    @GetMapping("/user/update")
    public Result<?> updateUser(@RequestBody @Validated User user, Errors errors) {
        if(errors.hasErrors()){
            return Result.fail("参数校验失败");
        }
        return null;
    }

}

表达式参数

Spring MVC 还支持 @Value 标注的注解获取环境变量或属性文件中的属性,可以使用表达式指定默认值或环境变量的名称。示例代码如下。

    @GetMapping("/environment")
    public Result<?> updateUser(@Value("${server.port}") String port) {
        return Result.ok(port);
    }

总结

Spring MVC 处理器方法由于未限制方法签名,因此较为灵活,Spring MVC 默认情况下支持了不同的处理器方法参数类型,有的用于获取请求参数,有的则用于其他功能。

为了支持良好的扩展性,Spring 内部其实是通过组合模式来实现的,Spring 通过 HandlerMethodArgumentResolver 接口解析处理器方法参数,默认的实现及能处理的方法参数我这里做了一个总结,见下图。欢迎留言交流。

在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-01-28 11:45:25  更:2022-01-28 11:46:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:18:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码