Can i return two models in ModelAndView in Spring MVC
Suppose i have following code if i have one model
MyBean bean = new MyBean();
bean.setName("Mike");
bean.setMessage("Meow!");
return new ModelAndView("welcomePage","model",bean);
But if i have two or three models like
Suppose on my one view i want the mo开发者_如何学Cdel with userdetails , shoppingcart details and history details
how can i use ModelAnd View to return 2-3 models
You can accomplish this a number of ways, but perhaps the easiest way would be to use a map
Map<String, Object> model = new HashMap<String, Object>();
model.put("bean", bean);
model.put("userdetails", userdetails);
//and so on
return new ModelAndView("welcomePage", "model", model);
Then, in your page, you just have to add an extra level when you access it
User's name is ${ model.userdetails.username }
alternatively, you could also change your handler signature to be something like this
public String handleRequest(Model model){
//arbitrary handling code
model.addAttribute("bean", bean);
model.addAttribute("userdetails", userdetails);
//etc
return "welcomePage";
}
When you do it like this, you don't actually have to return the model because Spring holds on to the reference before you receive it and can then access it afterwards. I personally find this method a little better because it makes unit testing easier. All you have to do is check the string return value and use a Spring mock model (or your own mock object that implements the Model
interface).
Edit To address the comments:
This source gives some examples and discusses some of the various supported method signatures. Specifically, check out section 15.3.2.3 for a discussion of the parameters that can be passed to handler methods.
Basically, Spring uses the @RequestMapping
annotations to determine which methods should be called based on a given request. Spring is then able to examine the method signature and generate the appropriate parameters before calling the method. In the case where you return a ModelAndView
object, the Model
is created when the constructor is called based on the parameters you provide. If you don't provide any model objects, then an empty model is created. However, when you specify that you should receive the model as a parameter to your handler method, Spring creates an instance of a Model
object for you and passes it to your method. Spring holds on to a reference to that model and, when your method returns, passes that model along to the web view (for example a JSP parser).
It really is effectively the same as returning a ModelAndView
object except it makes unit testing a lot easier and frankly, IMO makes for a cleaner and more elegant implementation.
Note: Keep in mind that a Model
is really just a special Map
object (hence why Spring supports using a Model
or Map
interchangeably in the method signatures). There are a few additional methods and it also supports implicit attribute naming. For instance, if you were to simply pass an object without giving it a name, the Model
object will figure out what to name the object based on object type, etc. However, if you always provide a "key" for the object you add to the model, it behaves exactly the same as a Map
.
Yes, you can return arbitrary number of model attributes by placing them into Map
:
Map<String, Object> model = new HashMap<String, Object>();
model.put("model", bean);
model.put("userdetails", ...);
model.put("shoppingcart", ...);
return new ModelAndView("welcomePage", model);
Note the terminology - model is a map, it consists of model attributes (individual objects), new ModelAndView("welcomePage","model",bean)
is a convenience constructor for creating a model with a single attribute.
There are good examples given. Just to add to the mix, I'm really becoming a fan of the annotations based methodology of doing this. I like it because it provides a very clean way of implementing. Here is an example...
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@Scope("prototype")
@RequestMapping("/testing")
public class TestController {
@Autowired
TestFactory factory;
@RequestMapping(value = "/test1", method = RequestMethod.POST)
public void test1(String something, String something2, Model model) {
List<Map<String, String>> results =
factory.getSomethingCool(something1, something2);
model.addAttribute("something1", something1);
model.addAttribute("something2", something2);
model.addAttribute("results", results);
}
@RequestMapping(value = "/test2", method = RequestMethod.POST)
public void test1(String something1, String something2, Model model) {
List<String> results =
factory.getSomethingElseCool(something1, something2);
model.addAttribute("something1", something1);
model.addAttribute("something2", something2);
model.addAttribute("results", results);
}
}
精彩评论