天天看点

Spring MVC 之@ModelAttribute使用

在Spring MVC里,@ModelAttribute通常使用在Controller方法的参数注解中,用于解释model entity;但同时,也可以放在方法注解里。

如果把@ModelAttribute放在方法的注解上时,代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法。下面介绍@ModelAttribute常用的三种方式。

1、@ModelAttribute注释一个方法的参数:

1)从model中获取数据

@Controller  
    public class HelloWorldController {  
  
        @ModelAttribute("user")  
        public User addAccount() {  
           return new User("jz","123");  
        }  
  
        @RequestMapping(value = "/helloWorld")  
        public String helloWorld(@ModelAttribute("user") User user) {  
           user.setUserName("jizhou");  
           return "helloWorld";  
        }  
    }      

在这个例子里,请求/helloWorld后执行helloWorld方法之前,会先执行addAccount方法。有因为,@ModelAttribute("user") User user注释方法参数,

所以参数user的值来源于addAccount()方法中的model属性。  此时如果方法体没有标注@SessionAttributes("user"),那么scope为request,如果标注了,那么scope为session。

2)从Form表单或URL参数中获取(实际上,不做此注释也能拿到user对象) 

@Controller  
    public class HelloWorldController {  
  
        @RequestMapping(value = "/helloWorld")  
        public String helloWorld(@ModelAttribute User user) {  
           return "helloWorld";  
        }  
    }      

2、

@ModelAttribute注释在方法上,当做方法拦截器使用:

如果把@ModelAttribute放在方法的注解上时,代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法。我们可以把这个@ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行@ModelAttribute方法。比如权限验证。

@Controller
@RequestMapping(value="test")
public class PassportController {

    @ModelAttribute
    public void preRun() {
        System.out.println("Test Pre-Run");
    }
    
    @RequestMapping(method=RequestMethod.GET)
    public String index() {
        return "login/index";
    }
    
    @RequestMapping(value="login", method=RequestMethod.POST)
    public ModelAndView login(@ModelAttribute @Valid Account account, BindingResult result)
        :
        :
    }

    
}      

在调用所有方法之前,都会先执行preRun()方法。

3、@ModelAttribute放在方法上,做为Model输出到View时使用:

1)@ModelAttribute注释void返回值的方法

@Controller  
public class HelloModelController {  
      
    @ModelAttribute   
    public void populateModel(@RequestParam String abc, Model model) {    
       model.addAttribute("attributeName", abc);    
    }    
  
    @RequestMapping(value = "/helloWorld")    
    public String helloWorld() {    
       return "helloWorld.jsp";    
    }    
  
}      

在这个代码中,访问控制器方法helloWorld时,会首先调用populateModel方法,将页面参数abc(/helloWorld.ht?abc=text)放到model的attributeName属性中,在视图中可以直接访问。

jsp中使用:

<%@ page language="java" contentType="text/html; charset=utf-8"  
    pageEncoding="utf-8"%>  
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>  
<html>  
<head>  
</head>  
<body>  
<c:out value="${attributeName}"></c:out>  
</body>  
</html>      

2)@ModelAttribute注释返回具体类的方法

@Controller  
public class Hello2ModelController {  
      
    @ModelAttribute   
    public User populateModel() {    
       User user=new User();  
       user.setAccount("ray");  
       return user;  
    }    
    @RequestMapping(value = "/helloWorld2")    
    public String helloWorld() {    
       return "helloWorld.jsp";    
    }    
}      

当用户请求 http://localhost:8080/test/helloWorld2时,首先访问populateModel方法,返回User对象

,model属性的名称没有指定,它由返回类型隐含表示,如这个方法返回User类型,那么这个model属性的名称是user。 

这个例子中model属性名称有返回对象类型隐含表示,model属性对象就是方法的返回值。它无须要特定的参数。

jsp中访问:

<c:out value="${user.account}"></c:out>      

3)也可以指定属性名字:

@Controller  
public class Hello2ModelController {  
      
    @ModelAttribute(value="myUser")  
    public User populateModel() {    
       User user=new User();  
       user.setAccount("ray");  
       return user;  
    }    
    @RequestMapping(value = "/helloWorld2")    
    public String helloWorld(Model map) {    
       return "helloWorld.jsp";    
    }    
}      

jsp中使用:

<c:out value="${myUser.account}"></c:out>      

4)合并对象:

@Controller  
public class Hello2ModelController {  
      
    @ModelAttribute  
    public User populateModel() {    
       User user=new User();  
       user.setAccount("ray");  
       return user;  
    }    
      
    @RequestMapping(value = "/helloWorld2")    
    public String helloWorld(User user) {  
        user.setName("老王");  
       return "helloWorld.jsp";    
    }    
}      

合并对象也可以指定名字:

@Controller  
public class Hello2ModelController {  
      
    @ModelAttribute("myUser")  
    public User populateModel() {    
       User user=new User();  
       user.setAccount("ray");  
       return user;  
    }    
      
    @RequestMapping(value = "/helloWorld2")    
    public String helloWorld(@ModelAttribute("myUser") User user) {  
        user.setName("老王");  
       return "helloWorld.jsp";    
    }    
}      

在jsp中访问:

<c:out value="${myUser.name}"></c:out>  
<c:out value="${myUser.account}"></c:out>