2018.5.31
1、使用pojo将数据从页面表单中接收到controller
绑定参数。
pojo:
public
class
Address {
private
String
province
;
private
String
city
;
|
public class
User
{
private String
username;
private String
password;
private String
email;
private Integer
age;
private
Address
address;
|
jsp:
<
form
action=
"save"
method=
"get"
>
<
label
for
=
""
>用户名:<
input
type
=
"text"
name=
"
username
"
/></
label
>
<
label
for
=
""
>密码:<
input
type
=
"text"
name=
"
password
"
/></
label
>
<
label
for
=
""
>年龄:<
input
type
=
"text"
name=
"
age
"
/></
label
>
<
label
for
=
""
>邮箱:<
input
type
=
"text"
name=
"
email
"
/></
label
>
<
label
for
=
""
>省份:<
input
type
=
"text"
name=
"
address.province
"
/></
label
>
<
label
for
=
""
>城市:<
input
type
=
"text"
name=
"
address.city
"
/></
label
>
<button>提交</button>
</
form
>
|
form controller:
@Controller
@RequestMapping("/user")
public
class
UserController
{
@RequestMapping("/form")
public
String form() {
return
"user/form"
;
}
|
save controller:
@RequestMapping("/save")
public
String save(User user) {
System.
out
.println(user);
return
"user/success"
;
}
|
2、ModelAndView
controller
@RequestMapping(
"/edit"
)
public ModelAndView edit() {
User
user
= new User();
user
.
set
Username(
"路咨询"
);
user
.
set
Password(
"山东"
);
user
.
set
Age(
18
);
user
.
set
Email(
"e1e1@qq.com"
);
Address address = new Address();
address.
set
Province(
"山东"
);
address.
set
City(
"青岛"
);
user
.
set
Address(address);
ModelAndView mav = new ModelAndView();
mav.
set
ViewName(
"user/form"
);
mav.addObject(
"user"
,
user
);
return mav;
}
|
修改了form.jsp中表单的value中为“${user.属性}”
value值都默认是requestScope.value
<
form
action
=
"save"
method
=
"get"
>
<
label
for
=
""
>
用户名:
<
input
type
=
"text"
name
=
"username"
value
=
"
${user.username}
"
/></
label
>
<
label
for
=
""
>
密码:
<
input
type
=
"text"
name
=
"password"
value
=
"
${user.password}
"
/></
label
>
<
label
for
=
""
>
年龄:
<
input
type
=
"text"
name
=
"age"
value
=
"
${user.age}
"
/></
label
>
<
label
for
=
""
>
邮箱:
<
input
type
=
"text"
name
=
"email"
value
=
"
${user.email}
"
/></
label
>
<
label
for
=
""
>
省份:
<
input
type
=
"text"
name
=
"address.province"
value
=
"
${user.address.province}
"
/></
label
>
<
label
for
=
""
>
城市:
<
input
type
=
"text"
name
=
"address.city"
value
=
"
${user.address.city}
"
/</
label
>
<
button
>
提交
</
button
>
</
form
>
|
3、使用MAP的参数传到前台页面
利用java中的map,自动将要传递的页面的数据注入到map参数中
@RequestMapping(
"/edit1"
)
public String edit1(Map
<String,Object>
map) {
User
user
= new User();
user
.
set
Username(
"路咨询1"
);
user
.
set
Password(
"山东1"
);
user
.
set
Age(
18
);
user
.
set
Email(
"e1e21@qq.com"
);
Address address = new Address();
address.
set
Province(
"山东1"
);
address.
set
City(
"青岛1"
);
user
.
set
Address(address);
map.put(
"user"
,
user
);
return
"user/form"
;
}
|
4、SpringMVC自带的Model
/**
* springmvc自带的model
* @param model
* @return
*/
@RequestMapping(
"/edit2"
)
public String edit2(Model model) {
User
user
= new User();
user
.
set
Username(
"路咨询1"
);
user
.
set
Password(
"山东1"
);
user
.
set
Age(
18
);
user
.
set
Email(
"e1e21@qq.com"
);
Address address = new Address();
address.
set
Province(
"山东1"
);
address.
set
City(
"青岛1"
);
user
.
set
Address(address);
model.addAttribute(
"user"
,
user
);
return
"user/form"
;
}
|
5.将数据模型传入到页面的session中
controller:
/*
* //
将模型放入
requestScope
中的同时,放入到
session
中。
*
局限性缺点:每传一次值
user
都会往
session
里放一次,耦合性太高。
* types={
数据类型
.class}
将基本类型数据放入
session
中,前台
${sessionScope}
取出
*/
@Controller
@RequestMapping
(
"/user"
)
@SessionAttributes
(value={
"user"
},types={String.
class
})
model
.addAttribute(
"user"
,
user
);
model
.addAttribute(
"strvalue"
,
"
路咨询
"
);
return
"user/form"
;
|
jsp:
${sessionScope.strvalue}
|
6、@ModelAttribute
@ModelAttribute可以在方法上使用,也可以在方法中的参数中使用,关于在这两个不同的地方使用时是有很大的差别的:
- 在方法上使用时, SpringMVC在调用所有的请求处理器(被@RequestMapping注解的方法)前会执行被这个注解标识的所有方法;
- 在方法的参数上使用时
一、方法上使用@ModelAttribute
使用在方法上的目的就是用来添加模型数据,由于被@ModelAttribute注解的方法要在所有被@RequestMapping注解的方法调用前调用,所以可以将该被该注解标识的方法看成是请求拦截器,在所有请求处理器之前执行,一个Controller类中可以有多个被@ModelAttribute注解的方法,由于作为拦截器,所以它接收的参数类型和被@RequestMapping注解的方法的参数类型相同,即亦可以使用像@RequestParam和@PathVariable等注解。另外,在方法上使用该注解时有两种方式:
- 方法没有返回值:当没有返回值时,我们就需要向该注解标识的方法中传递一个Model或者Map类型的参数来作为存储模型数据的容器,其实这里的容器类型可以使用在上一篇中说到的Map的对应的子类型也是可以的,实例如下:
@ModelAttribute
public
void
getGlobalInfo(Model model) {
model.addAttribute(
"area"
,
"China"
);
}
也可以写成这样:
@ModelAttribute
public
void
getGlobalInfo(Map<String, Object> map) {
map.put(
"area"
,
"China"
);
}
这样该Controller类中所有的@RequestMapping注解标识方法的返回的视图中都可以通过EL表达式获取这个模型数据;
- 方法有返回值:当有返回值时,模型数据是被存储到SpringMVC为我们创建的容器中,实例如下:
@ModelAttribute
public
Person getPerson(){
Person person =
new
Person();
person.setName(
"lmy86263"
);
person.setAge(
24
);
return
person;
}
Person是一个POJO类,如下:
public
class
Person
implements
Serializable{
private
static
final
long
serialVersionUID = 2158697392661485138L;
private
String name;
private
Integer age;
<span style=
"white-space:pre"
> </span>
// setter getter
}
在这里就是将Person对象存储到SpringMVC为我们创建的隐式容器中,属性的名称是”person“,至于这个属性名是怎么来的?不过不加指定,默认的属性名是非限定类型名称的第一个字母小写后作为属性名,这里就是将Person首字母小写作为属性名。如果不想使用默认的则
可以使用@ModelAttribute注解中的value属性来指定属性名
,比如使用@ModelAttribute("p"),这是在前台页面只能使用${p.name}而不能使用${person.name}。
还有一个疑问,网上一直没人写过,我在这里试一下,上面可以看到返回的诗句都是POJO类型,如果要是普通类型的数据是什么样的?尤其是普通类型使用默认参数名时是怎么样的?真的是String类型参数,属性名就是"string"?如下:
@ModelAttribute
public
Integer getString(){
// String msg = "string type";
// return msg;
Integer number =
12345
;
return
number;
}
经过测试,果然是这样,即使是String或者其基本类型的包装类也是安装上述所说的方式进行命名的,这里要注意的是不要使用基本类型,比如int,double等当返回值,这会导致抛出javax.el.ELException: The identifier [int] is not a valid Java identifier as required by section 1.19 of the EL specification这种异常,是EL表达式不能解析这种类型。
@ModelAttribute还可以应用到多个Controller类中,通过建立一个被@ControllerAdvice注解
(这个注解很有用,在进行异常处理时还会用到这个注解)的类,在该类中建立一个被@ModelAttribute的方法,这时在该方法中填入的模型数据可以在多个被声明的Controller类中使用,如果@ControllerAdvice没有指定特定的Controller,那么该方法会应用到所有的Controller中,可以看下面的链接。
更进一步,@ModelAttribute注解还可以使用在@RequestMapping注解标识的方法中,这个时候
该请求处理器的返回值就不是一个视图名,而是被认为是一个模型数据
。但是我觉得这样使用不太好,所以尽量不要这样使用。
二、参数上使用@ModelAttribute
在方法参数上使用@ModelAttribute是为了从模型中获取数据来传递到该参数上。如果模型中没有该对应的属性名,那么该类型的参数首先会实例化然后在加入到模型中,关于该类型的实例来自哪里是一个比较复杂的问题,如果有兴趣可以参考SpringMVC的文档。;如果发现有对应的属性名,那么参数的字段就会被该模型值填充,就是所谓的数据绑定。其实在从模型中取数据之前,将该注解使用在@RequestMapping方法参数上可以获取表单或者json数据,当表单或者ajax传递过来值时首先获取这部分的值,如果对应的对象的字段不存在才会去模型中查找对应的数据,好乱啊,看下面的实例:
有一个@ModelAttribute方法如下:
@ModelAttribute
public
User getPerson(){
User user =
new
User();
user.setName(
"lmy"
);
user.setAge(
20
);
Address address =
new
Address();
address.setCity(
"ts"
);
address.setProvince(
"hb"
);
user.setAddress(address);
System.out.println(
"here user "
+ user);
return
user;
}
此处的User和上一篇中的User相同不再指出。
@RequestMapping方法如下:
@RequestMapping
(
"/testModelAttributeParam"
)
public
String testModelAttributeParam(
@ModelAttribute
(
"user"
) User user){
System.out.println(user);
return
"view"
;
}
前台页面如下,没有传递city:
<html>
<body>
<form
action
=
"testModelAttributeParam"
method
=
"post"
>
<input
type
=
"text"
name
=
"name"
>
name
</input>
<input
type
=
"text"
name
=
"age"
>
age
</input>
<input
type
=
"text"
name
=
"address.province"
>
province
</input>
<!-- <input type="text" name="address.city">city</input> -->
<input
type
=
"submit"
value
=
"submit"
/>
</form>
</body>
</html>
后台显示结果如下:
可以看出只有在前台没有传递city数据时,才会到模型中查找对
应User中的city数据填充到@RequestMapping方法的参数中。