Spring处理请求参数的几个小细节

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xuxiaoyinliu/article/details/50349011

之前一直对spring参数的处理有些地方不明白,今天做了下测试
后台服务器的处理方法如下:
一点说明:
1.表单提交时会保留参数的所有的空格,这一点与直接输入地址不太一样,后者会去掉最后一个参数后面的所有空格!其他参数的空格则保留。
2.spring调用set方法赋值时不区分大小写

http://localhost:8080/AdminSession/index.do?p1=   a b  &p2=  3   2

上述地址中p1的所有空格会保留下来而p2只会保留2前面的空格,后面的会省略掉。
用到的实体类代码

public class Book {

private String name;
private Integer pu_time;
private int read_time;

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public Integer getPu_time() {
    return pu_time;
}
public void setPu_time(Integer pu_time) {
    this.pu_time = pu_time;
}
public int getRead_time() {
    return read_time;
}
public void setRead_time(int read_time) {
    this.read_time = read_time;
}
@Override
public String toString() {
    return "Book [name=" + name + ", pu_time=" + pu_time + ", read_time=" + read_time + "]";
}

测试方法为直接在地址中输入相关请求参数
服务器处理方法的几种情况:

1.参数为基本类型

@RequestMapping("emp")
public String execute(int s)

A.参数正确,参数中可有空格,处理时会自动去除

http://localhost:8080/ZwebTest/emp.do?s=3

服务器得到的s为3

B.参数为空后面可有空格

http://localhost:8080/ZwebTest/emp.do?s=

网页报错400;The request sent by the client was syntactically incorrect.

C.参数类型不符

http://localhost:8080/ZwebTest/emp.do?s=ABC

和B结果相同

D.省略参数

http://localhost:8080/ZwebTest/emp.do?

错误500,Request processing failed; nested exception is java.lang.IllegalStateException: Optional int parameter ‘s’ 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.
即参数s省略时服务器会试图自动将空值给s,但s为基本类型,无法转换成功

2.参数为String类型

@RequestMapping("emp")
public String execute(String s)

A.参数正确

http://localhost:8080/ZwebTest/emp.do?s=ABC

服务器得到s为ABC,如果有空格会被保留,即s= ABC 前面和字符串中的空格会保留下来尾部的会被去除

B.参数为空后面可有空格

http://localhost:8080/ZwebTest/emp.do?s=

使用StringUtil.isEmpty()结果为true,进一步判断发现其不为空null
则s为空字符串

C.省略参数

http://localhost:8080/ZwebTest/emp.do?

服务器得到s=null

3.非String引用类型

@RequestMapping("emp")
public String execute(Integer s)

A.参数正确时

http://localhost:8080/ZwebTest/emp.do?s=3

服务器得到s=3

B.

http://localhost:8080/ZwebTest/emp.do?s=ABC

报错400,The request sent by the client was syntactically incorrect.
C.空值

http://localhost:8080/ZwebTest/emp.do?s=

服务器得到s=null

D.省略参数

http://localhost:8080/ZwebTest/emp.do?

服务器得到s=null

4.参数为实体类时

@RequestMapping("emp")
public String execute(Book s)

这种情况服务器会将Book类实例化(所以如果没有@RequestParam(required=false)实体引用类参数在服务器端得到的结果不可能为null),在该类中找到其set方法所对应的所有属性,如果地址中有对应的属性就会对其赋值,反之采用默认值,这时参数相当于

@RequestMapping("emp")
public String execute(String name,Integer pu_time,int read_time)

要注意的是这里的read_time并不是必须的,可以省略,这一点与第一种情况有所不同

还有一点要注意的是若参数中使用了这个注解,@RequestParam,比如更改下代码为:

public String execute( @RequestParam(value="s",required=true)Integer a,Book s)

要注意的是这里的s指的是非实体类引用变量,也就是说这个s 并不指的Book 参数s这个应该很好理解
所以现在如果发起这个请求会报错

http://localhost:8080/ZwebTest/emp.do?a=J&name=ABC

错误:400 Required String parameter ‘b’ is not present .The request sent by the client was syntactically incorrect.
因此这里必须再加上一个s参数,而且这个参数还必须能被转换为a所对应的类型
比如:

http://localhost:8080/ZwebTest/emp.do?a=J&name=ABC&s=7

关于@RequestParam注解:

1.用于引用类型时

public String execute( @RequestParam(value="t",required=true)Integer  s,String t){}

就上述代码而言,s是必须的所以t也是必须的,不能省略且s的值取决于t

public String execute( @RequestParam(value="t",required=false)Integer  s,String t){}

更改为false后s可以省略t也可以省略,但s的值还是看t是否存在,即使在地址中指定了s服务器端还是会取t的值而非s

2.用于基本类型时

对于基本类型来说,无论required=false还是true,t都不可省略且不能为空,参考第一种情况,如下面的代码

public String execute( @RequestParam(value="t",required=false)int  s,String t){}

3.用于实体类

public String execute( @RequestParam(required=true)Book b){}

和前面相同,@RequestParam指的并不是实体类,所以这里的required针对的b并非实体类b,这种写法实际上就是

public String execute( @RequestParam(value="b",required=true)Book b){}

但是这样写问题又来了,如果地址中存在b参数但还是会报错,因为无法将String类转换为Book类(Spring认为参数都是String类型?)
那么这样写呢?

public String execute( @RequestParam(required=false)Book b){}

这句话的意思是Book 类b,在b(非Book类)参数不存在时不会进行实例化,这时服务器端b=null,但若b(非Book类)存在时肯定会报类型转换错误,因为无法将String类转换为Book类
所以,我们可以得出结论,实体引用类默认是一定会实例化的不必也不能加 @RequestParam(required=true),但可以通过加上
@RequestParam(required=false)不进行实例化,但要注意参数的处理

此外,对于 其他类型@RequestParam省略value的形式

public String execute( @RequestParam(required=false/true)Integer s,String t){}

只表示其后面的参数不可省略
最后,如果地址中多个参数名相同且该参数名与实体类set方法对应的某个属性相同,那么在对实体类参数进行实例化时只会取这些值中的第一个
对上述过程大概写了个流程,感觉越写越乱,错误百出,但可以保证的是其中的结论是测试过的,权且当个新手的参考吧,图可能不太清楚,请打开链接或下载后查看,欢迎大家批评。

小结

这里写图片描述

展开阅读全文

没有更多推荐了,返回首页