Skip to content

The simple sample of Model-View-Controller design pattern within Spring framework

Notifications You must be signed in to change notification settings

cklimkowski/klmspringmvc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

klmspringmvc

KLM A Model-View-Controller desing pattern with Spring framework

MVC in a few words.... Being concise controllers manipulate data in a model that represents information the user is interested in and pass that model on to the view, which renders the model in a way useful to the user. The point is to separate different application layers ie Model as business logic, Controller as a director of the flow process and View as presentation layer.

Package and class hierarchy looks like this: Hierarchy

To dispatch the client to a different URL I use org.springframework.web.servlet.view.RedirectView.

The HomeController has several request handler methods. First is home(Map), where argument Map<String, Object> model stands for Model.

@Controller
public class HomeController
{
    @RequestMapping("/")
    public View home(Map<String, Object> model)
    {
        model.put("dashboardUrl", "dashboard");
        return new RedirectView("/{dashboardUrl}", true);
    }
...
}

Obviously I could construct the view using the static URL string( new RedirectView("/dashboard", true)), but I would prefer to utilize the replacement template and pull dynamically attributes from the model. Now when we are transfered to /dashboard we serve it with another request handler method.

    @RequestMapping(value = "/dashboard", method = RequestMethod.GET)
    public String dashboard(Map<String, Object> model)
    {
        model.put("text", "This is a model attribute.");
        model.put("date", Instant.now());
        return "home/dashboard";
    }

The dashboard(Map) responds to the /dashboard URL, saves into the model text and date attributes and returns the String name home/dashboard of a view. Then Spring resolves it to WEB-INF/jsp/view/home/dashboard.jsp using JstlView resolver that I configured in ServletContextConfiguration :

    @Bean
    public ViewResolver viewResolver()
    {
        InternalResourceViewResolver resolver =
                new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/WEB-INF/jsp/view/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

So we have two JSP views. ---- View Layer WEB-INF/jsp/view/home/dashboard.jsp

<%--@elvariable id="text" type="java.lang.String"--%>
<%--@elvariable id="date" type="java.time.Instant"--%>
<!DOCTYPE html>
<html>
    <head>
        <title>Dashboard</title>
    </head>
    <body>
        Text: ${text}<br />
        Date: ${date}
    </body>
</html>

It just puts on view two model attributes that are exposed as EL variables for the JSP thanks to Spring JstlView ViewResolver.

#viewing implicitly model attributes To view implicitly model attributes I use org.springframework.web.servlet.RequestToViewNameTranslator configured in ServletContextConfiguration this way:

    @Bean
    public RequestToViewNameTranslator viewNameTranslator()
    {
        return new DefaultRequestToViewNameTranslator();
    }

I utilize deafult option org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

The userHome() method of the HomeController, mapped to the /user/home URL constructs and populates a new User object, returns it, and also adds it to the model with the attribute key currentUser thanks to @ModelAttribute annotation.

    @RequestMapping(value = "/user/home", method = RequestMethod.GET)
    @ModelAttribute("currentUser")
    public User userHome()
    {
        User user = new User();
        user.setUserId(1234987234L);
        user.setUsername("stefan");
        user.setName("Stefan Nowak");
        return user;
    }

Thanks to setting up the view name translation the view name becomes user/home, so I have to have this view in WEB-INF/jsp/view/user/home.jsp, where I can utilize again EL variables with "currentUser" object.

<%--@elvariable id="currentUser" type="klm.pstryk.site.User"--%>
<!DOCTYPE html>
<html>
    <head>
        <title>User Home</title>
    </head>
    <body>
        ID: ${currentUser.userId}<br />
        Username: ${currentUser.username}<br />
        Name: ${currentUser.name}<br />
    </body>
</html>

In the app there is another functionality. I employ content negotiation in Spring that allows to change the content type received back to the client based on a file extension. The configuration resides of course in ServletContextConfiguration.

    @Override
    public void configureContentNegotiation(
            ContentNegotiationConfigurer configurer)
    {
        configurer.favorPathExtension(true).favorParameter(false)
                .parameterName("mediaType").ignoreAcceptHeader(false)
                .useJaf(false).defaultContentType(MediaType.APPLICATION_XML)
                .mediaType("xml", MediaType.APPLICATION_XML)
                .mediaType("json", MediaType.APPLICATION_JSON);
    }

And I use it in the HomeController with @ResponseBody annotation.

    @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET)
    @ResponseBody
    public User getUser(@PathVariable("userId") long userId)
    {
        User user = new User();
        user.setUserId(userId);
        user.setUsername("piotr");
        user.setName("Piotr Wysmial");
        return user;
    }

Thanks to this the mapped views eg user/1 and user/1.json properly render with "xml view" and "json view" as relevant.

About

The simple sample of Model-View-Controller design pattern within Spring framework

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages