和开振学Spring boot 3.0之Spring MVC:④获取参数(上)

之前,我反复说过处理器封装了控制器,HandlerMapping的机制找到处理器后,通过处理器就能运行控制器,那么处理器增强了控制器什么功能呢?

我们用脑子想一下,要运行控制器之前,我们需要做什么?那必须是方法的参数嘛。所以处理器第一步就是要根据我们的方法来获取参数。

只是获取参数的内容有点多,我打算分三篇文章进行讲解,所以这里的标题添加了一个“上”

1、Spring MVC是如何获得调用控制器方法参数的?

对于控制器来说参数可能来自于很多方面,比如Session,HTTP请求参数,HTTP请求头,系统参数,请求路径等当然还有特殊的请求体(可以是文件或者JSON,后面我们会再谈)。为了能处理控制器参数,Spring MVC处理器方法参数解析器(HandlerMethodArgumentResolver),通过它能够解析来自各方面的参数。获得参数后,就能够调用控制器的方法了。

为此,我们先来看Spring MVC为我们提供了哪些处理器方法参数解析器(HandlerMethodArgumentResolver),如下图所示。

处理器方法参数解析器(HandlerMethodArgumentResolver)

 请注意到上图,我加红色框的都是我们常用的解析器,只是Spring MVC会把这步擦除,让我们不知不觉的使用了它们而已。我们这里稍微记住这个机制,下面的内容就与它们有关。

2、在无注解下获取参数

为了讲解,我这里先给出一段代码如下:

package com.csdn.mvc.chapter1.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@Controller
// 这个注解可以配置在类或者方法上
@RequestMapping("/param")
public class ParameterController {
    /**
     * 在无注解下获取参数,要求参数名称和HTTP请求参数名称一致,此时允许参数为空
     * @param intVal  -- 整数
     * @param longVal -- 长整型
     * @param strVal --字符串
     * @return 响应JSON参数
     */
    // HTTP GET请求
    @GetMapping("/no/annotation")
    @ResponseBody
    public Map<String, Object> noAnnotation(
            Integer intVal, Long longVal, String strVal) {
        var paramsMap = new HashMap<String, Object>();
        paramsMap.put("intVal", intVal);
        paramsMap.put("longVal", longVal);
        paramsMap.put("strVal", strVal);
        return paramsMap;
    }


}

 请注意这里的方法带有参数名称分别为“intVal”“longVal”“strVal”,只要我们的HTTP带上这些参数请求,就可以获取了。而方法标注了@ResponseBody,就意味着将返回的东西变为JSON数据集。

也就是在默认的情况下,Spring MVC会自动给同名的请求参数匹配上控制器方法的参数。这就是处理器方法参数解析器(HandlerMethodArgumentResolver)起到的作用,只是Spring MVC屏蔽了这个过程,让我们体会不到而已。

@RequestMapping("/param")标注在类上,说明该类所有请求都需要加入“/param”前缀,而@GetMapping是HTTP的GET请求。在Spring 4.3的版本之后,为了简化method配置项的配置新增了几个注解,如@GetMapping、@PostMapping、@PatchMapping、@PutMapping和@DeleteMapping。分别对应HTTP的GET、POST、PATCH、PUT和DELETE请求,关于这些在REST风格请求中,我会再讨论。

没有注解的参数是允许为空的,比如我们请求:http://localhost:8080/param/no/annotation?intVal=1&longVal=1

可以得到这样的结果。(注意:strVal参数为空

3、使用@RequestParam获取参数

上面是无注解下拿到参数,而事实是还可以从请求参数中拿到参数。因为HTTP请求参数与控制器方法参数不同名的比比皆是,所以需要建立一个机制,从HTTP请求参数中获取控制器参数。那么就要使用注解@RequestParam了。它会启用RequestParamMethodArgumentResolver去获取参数。

我们在ParameterController 添加一个方法来测试,如下。

/**
 * 通过@RequestParam获取参数,此时默认不允许参数为空
 * @param intVal  -- 整数
 * @param longVal -- 长整型
 * @param strVal --字符串
 * @return 响应JSON参数
 */
// HTTP GET请求
@GetMapping("/annotation")
@ResponseBody
public Map<String, Object> annotation(
        @RequestParam("int_val") Integer intVal,
        @RequestParam("long_val") Long longVal,
        @RequestParam("str_val") String strVal) {
    var paramsMap = new HashMap<String, Object>();
    paramsMap.put("intVal", intVal);
    paramsMap.put("longVal", longVal);
    paramsMap.put("strVal", strVal);
    return paramsMap;
}

@RequestParam代表从HTTP请求参数中获取参数给控制器,“int_val”“long_val”“str_val”代表参数名称,然后可以将控制器的参数命名为自己想要的intVal、longVal和strVal等。@RequestParam可以通过名称将它们对应起来。

只是大家需要注意,@RequestParam标注的参数默认是不能为空的,如果为空,那么就会抛出异常。如果你允许它为空,那么可以修改进行配置,如下。

@RequestParam(value="int_val", required = false) Long intVal

代码中的required配置项默认值为true,也就是不能缺省,如果修改为false,那么就允许缺省了。当然在大部分情况下,我都不建议你配置了,以避免抛出臭名昭著的NullPointerException。

4、从URL中获取参数

在REST请求中很多时候,我们需要从URL中获取参数,比如请求:

GET http://localhost:8080/user/1

代表我们获取编号为1用户的用户信息,这样编号需要从URL中获取。这个时候需要使用@PathVariable和URL的结合来实现。为此我们在ParameterController 添加一个方法来测试,如下。

@GetMapping("/path/{intVal}/{longVal}/{strVal}")
@ResponseBody
public Map<String, Object> path(
        @PathVariable("intVal") Integer intVal,
        @PathVariable("longVal") Long longVal,
        @PathVariable("strVal") String strVal) {
    var paramsMap = new HashMap<String, Object>();
    paramsMap.put("intVal", intVal);
    paramsMap.put("longVal", longVal);
    paramsMap.put("str", strVal);
    return paramsMap;
}

这里的@GetMapping的路径是“/path/{intVal}/{longVal}/{strVal}”,这些{paramName}格式是定位参数的位置,从而可以在path()方法使用@PathVariable({paramName})就能够获取对应URL中的参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值