天天看點

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>