在学习SpringMVC之前,客户端的请求数据一般是靠request的getParameter方法获取,获取到的数据类型为String类型,需要强制转换为需要的数据类型。
在controller中也可以用这种方式获取客户端数据。
//浏览器访问路径为http://127.0.0.1:8001/web02/request?name=name @RequestMapping(path = "/request", method = RequestMethod.GET) public ModelAndView test01(HttpServletRequest request) { String name = request.getParameter("name"); System.out.println(name); return null; }
现在我们用MVC注解@RequestParam获取客户端请求数据
一 基本数据类型的获取
以int类型数据为例
//浏览器的访问路径为http://127.0.0.1:8001/web02/int?user_id=100 @RequestMapping(path = "/int", method = RequestMethod.GET) public ModelAndView getParam01(@RequestParam(name = "user_id") int id) { System.out.println(id); return null; }
@RequestParam注解有一个属性name,对应地址栏(form表单input标签的name值)上的变量名,获取到值后将值映射到参数中。
如果地址栏中并没有传递参数,这时会报如下错误:
HTTP Status 400 - Required int parameter 'user_id' is not present
这是由于@RequestParam注解还有一个属性required,默认值为true,表示地址栏中必须要有与name值相同的参数,否则就会报错,我们可以手动把这个属性值设置为false。
@RequestParam(name = "user_id", required = false) int id
重启tomcat,访问,然而又出现了错误:
java.lang.IllegalStateException: Optional int parameter 'user_id' 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.
很明显,地址栏未传值则默认值为null,而controller中参数类型为int,基本数据类型是不可以存空值的,所以会报上述错误,故在参数为基本数据类型时,一律使用其对应的包装类声明参数,除非可以确定获取的参数值一定不为null。
@RequestParam注解可以不显示使用
如果参数名与地址栏中的参数名一样,就可以实现自动映射而不必显示的使用@RequestParam注解映射:
//浏览器的访问路径为http://127.0.0.1:8001/web02/int?user_id=100 @RequestMapping(path = "/int", method = RequestMethod.GET) public ModelAndView getParam01(Integer user_id) { System.out.println(user_id); return null; }
注意,隐式的使用@RequestParam注解,默认required值为false,如果客户端没有传递参数,也没有使用基本类型定义的参数,则参数的值为null;而显示使用注解默认required值为true,客户端必须传递相关参数。
二 数组的获取
表单中诸如checkbox标签可传递多值,在controller中如何接值?
//地址栏http://127.0.0.1:8001/web02/array?hobbys=basketball&hobbys=football @RequestMapping(path = "/array", method = RequestMethod.GET) public ModelAndView getParam02(String[] hobbys) { if (hobbys != null) { for (String hobby : hobbys) { System.out.println(hobby); } } return null; }
三 自定义类的获取
定义一个USer类,成员变量user_id(int),account(String),password(String),user_name(String),并生成get、set方法,重写toString方法。现要实现将客户端数据封装到USer类中。
//地址栏http://127.0.0.1:8001/web02/object?user_id=1&account=dva&password=12345&user_name=dva @RequestMapping(path = "/object", method = RequestMethod.GET) public ModelAndView getParam03(User user) { System.out.println(user); return null; }
只需保证客户端数据与User中的成员变量名相同(实际上地址栏参数对应的是User类中set方法名的去掉set剩余部分的首字母小写),在controller方法的参数中直接声明类型为User的参数,即可自动将客户端的数据存入到User对象中。
当controller方法中的参数为包装类型时,如果客户端未传递数据,那么在controller中参数值为null;但是如果参数类型为类,即使客户端未传递参数,类也会被实例化,只不过类中的成员变量值没有赋值而已。
如,地址栏http://127.0.0.1:8001/web02/object,则控制台将输出:
User [account=null, password=null, user_id=0, user_name=null]
四 类关联类
现在定义一个新类Role,成员变量role_id(int),role_name(String);User中新添属性role(Role),生成get、set方法,重写toString方法。客户端传递用户信息及其对应的角色信息,controller又该如何获取数据?
<!--在object.jsp文件中创建表单--> <form action="object" method="post"> 用户ID<input name="user_id"><br><br> 账户<input name="account"><br><br> 密码<input name="password"><br><br> 用户名<input name="user_name"><br><br> 角色ID<input name="role.role_id"><br>< 角色名<input name="role.role_name"><br> <input type="submit" value="提交"> </form>
在controller中
@RequestMapping(path = "/object", method = RequestMethod.POST) public ModelAndView getParam03(User user) { System.out.println(user); return null; }
在地址栏中访问object.jsp文件,提交表单。