SpringMVC之请求参数的获取方式

SpringMVC之请求参数的获取方式

常见的一个web服务,如何获取请求参数?java

通常最多见的请求为GET和POST,get请求的参数在url上能够获取,post请求参数除了url上还有可能在表单中,文件上传时,获取方式又和通常的参数获取不同web

本篇则主要集中在不一样请求方式下,获取参数的使用姿式ajax

首先须要搭建一个后端的请求,为了快速演示spring

利用spring-boot建立了一个机器简单的工程,依赖版本 1.5.4.RELEASE后端

I. GET请求参数获取

get请求参数,通常都是直接挂在请求的url上,因此获取这些参数仍是比较简单的spring-mvc

1. 经过 HttpServletRequest获取参数

这个能够说是最基本最多见的的方式了,javax.servlet.ServletRequest#getParameter 来获取对应的参数,下面各处一个实例mvc

@RestController
@RequestMapping(path = "webs/demo")
public class DemoController {

    @RequestMapping(path = "req1")
    public String req1(HttpServletRequest request) {
        String user = request.getParameter("user");
        String password = request.getParameter("password");
        return "req1 user: " + user + " pwd: " + password;
    }
}

根据上面暴露的接口,咱们测试的case就很简单了app

http://127.0.0.1:8080/webs/demo/req1?user=小灰灰Blog&password=123456
## 输出  req1 user: 小灰灰Blog pwd: 123456

http://127.0.0.1:8080/webs/demo/req1?user=小灰灰Blog
## 输出  req1 user: 小灰灰Blog pwd: null

说明curl

  • 这是一个最基本的获取参数的方式,get,post请求都适用的,一般在filter,intercepter中也是能够经过HttpServletRequest对象来获取请求参数ide

  • 除了获取常见的请求参数以外,HttpServletRequest能够获取请求头的完整信息

  • 在一次请求的生命周期内,能够经过下面的方式获取Request对象(固然也能够获取response对象)

    HttpServletRequest httpServletRequest = ((ServletRequestAttributes) 
        RequestContextHolder.getRequestAttributes()).getRequest();

2. 直接方法参数获取

直接给出case, 这个方法依然是放在上面的DemoController下面的

@RequestMapping(path = "req2")
public String req2(String user, String password) {
    return "req2 user: " + user + " pwd: " + password;
}

请求验证

http://127.0.0.1:8080/webs/demo/req2?user=%E5%B0%8F%E7%81%B0%E7%81%B0Blog&password=123456
## 输出: req2 user: 小灰灰Blog pwd: 123456


http://127.0.0.1:8080/webs/demo/req2?password=123456
## 输出: req2 user: null pwd: 123456


http://127.0.0.1:8080/webs/demo/req2?password=123456&User=blog
## 输出: req2 user: null pwd: 123456

注意:

  • 上面这种使用方式,至关于直接将url参数映射到了Controller方法的参数上了
  • 方法参数名必须和url参数名彻底一致(区分大小写)
  • 顺序无关
  • 若参数没传,则默认为null

一个疑问

上面的demo中Controller的方法参数都是String还好,若是将password改为int,会出现什么状况

代码稍做修改

@RequestMapping(path = "req2")
public String req2(String user, int password) {
    return "req2 user: " + user + " pwd: " + password;
}

实际测试

# case1 
http://127.0.0.1:8080/webs/demo/req2?password=123456&user=blog
## 输出: req2 user: blog pwd: 123456


# case 2
http://127.0.0.1:8080/webs/demo/req2?password2=123456&user=blog
## 输出: 报错, Optional int parameter 'password' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type


# case 3
http://127.0.0.1:8080/webs/demo/req2?password=abc&user=blog
## 输出:报错, "Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "abc""

结果说明

  • 若是请求参数与方法参数类型不一致,会抛出转换异常
  • 若是方法参数为非封装基本类型,则url参数必须存在,不然报错

3. RequestParam注解方式获取请求参数

经过@RequestParam注解获取参数的方式和上面的一种比较相似,case以下

@RequestMapping(path = "req3", method = RequestMethod.GET)
public String req3(@RequestParam("user") String username,
                   @RequestParam("password") String pwd) {
    return "req3 user: " + username + " pwd: " + pwd;
}

测试case

# case1 
http://127.0.0.1:8080/webs/demo/req3?password=123456&user=blog
## 输出: req3 user: blog pwd: 123456


# case2
http://127.0.0.1:8080/webs/demo/req3?password=123456
## 输出:报错, Required String parameter 'user' is not presen

说明

  • 不指定注解的name或value属性时,等同于第二种使用姿式
  • 注解的name属性或value属性,用实际的参数名来指定
  • controller的参数名与url参数名没有强关联(区别第二种方式)
  • 参数类型须要保证一致(通第二种方式)
  • 若是url参数可选,请设置require属性为false,以下
    @RequestParam(name = "user",  required = false) String username

4. Bean方式获取参数

对于请求参数比较复杂的状况下,我比较喜欢这种使用姿式,管理起来方便简单

@Data
public static class UserDO {
    String user;
    String password;
}

@RequestMapping(path = "req4", method = RequestMethod.GET)
public String req4(UserDO userDO) {
    return "req4 userDO: " + userDO;
}

测试case

# case1
http://127.0.0.1:8080/webs/demo/req4?password=123456&user=%E5%B0%8F%E7%81%B0%E7%81%B0Blog
## 输出: req4 userDO: DemoController.UserDO(user=小灰灰Blog, password=123456)


# case2
http://127.0.0.1:8080/webs/demo/req4?password=123456
## 输出: req4 userDO: DemoController.UserDO(user=null, password=123456)

说明

  • 定义一个bean,内部属性和请求参数对应
  • 容许参数不存在的状况,会使用null代替(因此,尽可能不要使用非封装基本类型,不然参数不传时,会抛异常)
  • bean的属性,能够根据实际状况指定类型

5. ModelAttribute注解方式

@ModelAttribute注解的方法,会优于Controller以前执行,通常更常见于向视图传输数据使用,此处不详细展开,正常来说,专门的获取参数不太会用这这种方式来玩

6. Path参数

Path参数,专指的是请求路径的参数,如

http://127.0.0.1:8080/webs/demo/req4?password=123456

上面这个url中,password是咱们传统意义上的请求参数,其中path参数则是指其中 req4, demo这种path路径中的一环;对此,最多见的一个case就是常见的博客中,如开源中国的一个博客连接

https://my.oschina.net/u/566591/blog/1601400
  • 566591 : 这个参数主要用来区分用户
  • 1601400 : 这个参数则主要是表示对应的博文

通常path参数的获取方式以下

@RequestMapping(path = "req6/{user}/info")
public String req6(@PathVariable(name = "user") String user) {
    return "req6 user: " + user;
}

测试case

# case1 
http://127.0.0.1:8080/webs/demo/req6/blog/info?user=haha
## 输出:req6 user: blog

# case2
http://127.0.0.1:8080/webs/demo/req6/blog?user=haha
## 输出: 404

# case3
http://127.0.0.1:8080/webs/demo/req6/info?user=haha
## 输出: 404

注意:

  • path参数的使用,须要确保参数存在且类型匹配
  • path参数和url参数不会相互影响

II. POST请求参数获取

POST请求参数,更多的是看提交表单参数是否能够获取到,以及如何获取,主要的手段依然是上面几种方式,下面验证下是否ok

1. HttpServletRequest方式获取参数

测试case,能够借助curl来实现post请求

# case1 
curl -d "user=小灰灰Blog&password=123456" "http://127.0.0.1:8080/webs/demo/req1"
## 输出: req1 user: 小灰灰Blog pwd: 123456

# case2
curl -d "user=小灰灰Blog" "http://127.0.0.1:8080/webs/demo/req1?password=123456"
## 输出:req1 user: 小灰灰Blog pwd: 12345


# case3
curl -d "user=小灰灰Blog" "http://127.0.0.1:8080/webs/demo/req1?user=greyBlog"
## 输出:req1 user: greyBlog pwd: null

curl也能够换成js请求测试方式

var formData = new FormData();
formData.append("user", "小灰灰Blog");

$.ajax({
  url: 'http://127.0.0.1:8080/webs/demo/req1?password=123456',
  type: 'post',
  cache: false,
  data: formData,
  processData: false,
  contentType: false
});

说明

  • 对于HttpServletReuqest方式获取参数时,get和post没什么区别
  • 若url参数和表单参数同名了,测试结果显示使用的是url参数(待确认,固然最好不要这么干)

2. 方法参数获取

几个测试demo以下

# case 1
curl -d "user=小灰灰Blog&password=123456" "http://127.0.0.1:8080/webs/demo/req2"
## 输出: req2 user: 小灰灰Blog pwd: 123456


# case 2
curl -d "password=123456" "http://127.0.0.1:8080/webs/demo/req2"
## 输出:req2 user: null pwd: 123456


# case 3
curl -d "password=123456" "http://127.0.0.1:8080/webs/demo/req2?user=blog"
## 输出: req2 user: blog pwd: 123456

基本上使用姿式和get没什么区别

3. RequestParam注解方式

# case 1
curl -d "password=123456&user=blog" "http://127.0.0.1:8080/webs/demo/req3"
## 输出: req3 user: blog pwd: 123456


# case 2
curl -d "password=123456" "http://127.0.0.1:8080/webs/demo/req3?user=blog"
## 输出: req3 user: blog pwd: 123456


# case 3
curl -d "password=123456&user=blog" "http://127.0.0.1:8080/webs/demo/req3?password=900"
## 输出:req3 user: blog pwd: 900,123456

注意

  • 和前面的两种方式不一样的是,当post表单的参数和url参数同名时,会合并成一个字符串

4. Bean方式

## case1 
curl -d "password=123456&user=blog" "http://127.0.0.1:8080/webs/demo/req4?password=900"
## 输出 req4 userDO: DemoController.UserDO(user=blog, password=900,123456)


## case2
curl -d "password=123456&user=blog" "http://127.0.0.1:8080/webs/demo/req4"
## 输出 req4 userDO: DemoController.UserDO(user=blog, password=123456)


## case3
curl -d "password=123456" "http://127.0.0.1:8080/webs/demo/req4"
## 输出 req4 userDO: DemoController.UserDO(user=null, password=123456)

这种方式不区分get,post,因此彻底复杂的交互接口,彻底能够考虑用bean的方式来定义请求参数

5. PathVariable

这个无法玩...

III. 多媒体上传参数获取

上传文件的支持,对于传统的spring-mvc来讲,可能须要一些添加一些相关配置,不在本文的范畴内,下面默认已经配置好

1. 实例支持

@RequestMapping(path = {"wx/upload", "wx/wx/upload"}, method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS})
@ResponseBody
public String upload(HttpServletRequest request) {
    MultipartFile file = null;
    if (request instanceof MultipartHttpServletRequest) {
        file = ((MultipartHttpServletRequest) request).getFile("image");
    }

    if (file == null) {
        throw new IllegalArgumentException("图片不能为空!");
    }
    
    return "success";
}

简单来讲,主要是利用HttpServletRequest来获取上传的文件

注意:

  • 若是接口必需要求上传文件,能够直接把参数声明为 MultipartHttpServletRequest, 此时调用方若是不传参数,会被异常拦截(能够经过@ControllerAdvice来拦截全局异常)
  • 若是能够不上传文件,则能够用上面的这种猥琐姿式,内部进行判断
  • ((MultipartHttpServletRequest) request).getFile(xxx)来获取指定名的上传文件

IV. 小结

1. 五种获取参数的姿式

方式 注意事项
HttpServletRequest获取参数 最多见通用
方法参数与请求参数同名 注意参数名统一,注意类型一致,尽可能不用非包装基本类型
@RequestParam注解 同上,可注解内指定http参数名
Bean方式 定义一个bean,会将同名的http参数赋值进去,推荐
@PathVariable 注解 请求url参数

2. 传文件使用姿式

使用MultipartHttpServletRequest来获取上传的文件,固然也能够获取基本的请求参数

V. 其余

声明

尽信书则不如,已上内容,纯属一家之言,因本人能力通常,看法不全,若有问题,欢迎批评指正

扫描关注,java分享

QrCode

相关文章
相关标签/搜索