Spring3 MVC请求参数获取的几种方法

来源:互联网 发布:君自故乡来 应知故乡事 编辑:程序博客网 时间:2024/06/03 07:27

一、      通过@PathVariabl获取路径中的参数

复制代码
    @RequestMapping(value="user/{id}/{name}",method=RequestMethod.GET)    public String printMessage1(@PathVariable String id,@PathVariable String name, ModelMap model) {                System.out.println(id);        System.out.println(name);        model.addAttribute("message", "111111");        return "users";    }
复制代码

例如,访问user/123/lei路径时,执行以上方法,其中,参数id=123,name=lei

 

二、      @ModelAttribute获取POST请求的FORM表单数据

JSP表单如下

<form method="post" action="hao.do">    a: <input id="a" type="text"   name="a"/>    b: <input id="b" type="text"   name="b"/>    <input type="submit" value="Submit" /> </form>

 

Java  Pojo如下

    public class Pojo{        private String a;        private int b;    }

 

Java Controller如下

@RequestMapping(method = RequestMethod.POST) public String processSubmit(@ModelAttribute("pojo") Pojo pojo) {         return "helloWorld"; }

三、      直接用HttpServletRequest获取

@RequestMapping(method = RequestMethod.GET) public String get(HttpServletRequest request, HttpServletResponse response) {    System.out.println(request.getParameter("a"));     return "helloWorld"; }

 

四、      用注解@RequestParam绑定请求参数

用注解@RequestParam绑定请求参数a到变量a

当请求参数a不存在时会有异常发生,可以通过设置属性required=false解决,

例如: @RequestParam(value="a", required=false)

Controller如下

@RequestMapping(value = "/requestParam", method = RequestMethod.GET) public String setupForm(@RequestParam("a") String a, ModelMap model) {    System.out.println(a); return "helloWorld";

}

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

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

上述地址中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;}@Overridepublic String toString() {    return "Book [name=" + name + ", pu_time=" + pu_time + ", read_time=" + read_time + "]";}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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

1.参数为基本类型

@RequestMapping("emp")public String execute(int s)
  • 1
  • 2
  • 1
  • 2

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

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

服务器得到的s为3

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

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

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

C.参数类型不符

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

和B结果相同

D.省略参数

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

错误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)
  • 1
  • 2
  • 1
  • 2

A.参数正确

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

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

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

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

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

C.省略参数

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

服务器得到s=null

3.非String引用类型

@RequestMapping("emp")public String execute(Integer s)
  • 1
  • 2
  • 1
  • 2

A.参数正确时

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

服务器得到s=3

B.

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

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

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

服务器得到s=null

D.省略参数

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

服务器得到s=null

4.参数为实体类时

@RequestMapping("emp")public String execute(Book s)
  • 1
  • 2
  • 1
  • 2

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

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

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

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

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

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

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

错误: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
  • 1
  • 1

关于@RequestParam注解:

1.用于引用类型时

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

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

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

更改为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){}
  • 1
  • 1

3.用于实体类

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

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

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

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

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

这句话的意思是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){}
  • 1
  • 1

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

小结

这里写图片描述


0 0
原创粉丝点击