【SpringMVC学习笔记】04 处理模型数据

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方法的参数中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值