Search code examples
javaspringspring-mvcmodel-view-controllertemplate-engine

Spring MVC parent template model component


I'm using Spring MVC 4 and I'm building a site with a template that requires several common components across pages, such as login status, cart status, etc. An example of controller function would be this:

@RequestMapping( path = {"/"}, method=RequestMethod.GET)    
    public ModelAndView index() {
        ModelAndView mav = new ModelAndView("index");
        mav.addObject("listProducts", products );
        mav.addObject("listCategories",  menuCategoriasUtils.obtainCategories());
        return mav;
    }

What would be a good way/pattern to feed these elements that do not belong to the controller we are currently calling so we don't repeat over and over unrelated operations in every method of every controller?

Thanks!


Solution

  • There is a several approaches to show common data in views. One of them is using of @ModelAttributte annotation.

    Lets say, you have user login, that needed to be shown on every page. Also, you have security service, where from you will get security information about current login. You have to create parent class for all controllers, that will add common information.

    public class CommonController{
    
        @Autowired
        private SecurityService securityService;
    
        @ModelAttribute
        public void addSecurityAttributes(Model model){
            User user = securityService.getCurrentUser();
            model.addAttribute("currentLogin", user.getLogin());
    
            //... add other attributes you need to show
        }
    
    }
    

    Note, that you don't need to mark CommonController with @Controller annotation. Because you'll never use it as controller directly. Other controllers have to be inherited from CommonController:

    @Controller
    public class ProductController extends CommonController{
    
        //... controller methods
    }
    

    Now you should do nothing to add currentLogin to model attributes. It will be added to every model automatically. And you can access user login in views:

    ...
    <body>
       <span>Current login: ${currentLogin}</span>
    </body>
    

    More details about usage of @ModelAttribute annotation you can find here in documentation.