Social Media

Spring MVC

Spring MVC is one of the most commonly used Spring Modules. At its core is the DispatcherServlet.

The DispatcherServlet offers a range of features including –

  • Separation of roles between controller, validator, command object, form object, model object, DispatcherServlet, handler mapping, view resolver
  • Use of POJO’s
  • Customisable binding and Validation
  • Model Map allows different front end solutions to be used

The DispatcherServlet binds to WebApplicationContext, and special beans –

  • DispatcherServlet
  • WebApplicationContext – Bound to request as attribute for controller. Default key – DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE
  • Controllers
  • Handler Mappings – Examples include URL matching
  • Locale Resolvers – Map to locale
  • Theme Resolver – Resolve themes for personalized layouts
  • View Resolvers – Map view names to views
  • Multipart Resolver – File Uploads
  • Handler Exception Resolvers – Handle exceptions

DispatcherServlet Configuration

[sourcecode lang=”xml”]

    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
[/sourcecode]

By default this will look for a configuration under /WEB-INF/spring-servlet.xml

You can also use ContextLoaderListener to load multiple configuration files

[sourcecode lang=”xml”] <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
[/sourcecode]

Allows you to specify multiple xml files –

[sourcecode lang=”xml”] <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
     /WEB-INF/applicationContext*.xml
     classpath:someother-context.xml
  </param-value>
</context-param>
[/sourcecode]

Configuration

Like all Spring configurations you have the option of either –

  • XML Config
  • Annotation Driven Context

Im not going to cover the XML configuration beyond configuration of annotation driven context, as its covered very well in the Spring documentation.

Preconfiguration

The servlet configuration above will serve all requests. The starting point is to separate requests for resources from spring MVC configurations –

[sourcecode lang=”xml”]     <mvc:resources mapping="/assets/**" location="classpath:/META-INF/resources/webjars/"/>
    <mvc:resources mapping="/css/**"    location="/css/"/>
    <mvc:resources mapping="/img/**"    location="/img/"/>
    <mvc:resources mapping="/js/**"     location="/js/"/>
[/sourcecode]

We’re using DefaultAnnotationHandlerMapping. This needs to be configured by –

[sourcecode lang=”xml”] <context:component-scan base-package="com.glenware.parkrunpb" />
<mvc:annotation-driven/>
[/sourcecode]

Other options are BeanNameUrlHandlerMapping, ControllerBeanNameHandlerMapping, ControllerClassNameHandlerMapping and SimpleUrlHandlerMapping

Finally we configure the ViewResolver –

[sourcecode lang=”xml”]     <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
[/sourcecode]

This will serve JSTL pages of the pattern –

prefix/<controllerRequest>.suffix –> /WEB-INF/jsp/<controllerRequest>.jsp

Other options for ViewResolvers include BeanNameViewResolver, TilesViewResolver and ContentNegotiatingViewResolver

Finally we should configure the messages –

[sourcecode lang=”xml”]

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>

[/sourcecode]

Configuration of Controllers

The most basic controller is

[sourcecode lang=”java”] package com.glenware.parkrunpb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class AboutController {

    @RequestMapping("/about")
    public String about() {
        return "about";s
    }

}
[/sourcecode]

Lets break this down –

1. @Controller – This annotation instructs the Spring container that the object is a Controller

2. @RequestMapping – Signifies the use of DefaultAnnotationHandlerMapping. In this instance it will serve requests for /about

The @RequestMapping can also be used at class level – eg

[sourcecode lang=”java”]

@Controller
@RequestMapping("api")
public class JSONController

[/sourcecode]

3. Finally we see the about method which simply forwards to “about”. This is combined with the ViewResolver –

prefix/<controllerRequest>.suffix –> /WEB-INF/jsp/about.jsp

Forms

Any real app would involve some transfer of data from the server.

An example form would be of the structure –

[sourcecode lang=”html”]

<form:form method="post" action="addAdmin.html" commandName="prCourse" role="form" class="form-horizontal">

<form:errors path="*" cssClass="errorblock" element="div" />

<div class="form-group">
<label class="col-sm-2 control-label" for="prName">Course Name</label>
<div class="col-sm-4">
<form:input type="text" path="prName" class="form-control" />
</div>
</div>

<div class="form-group">
<label class="col-sm-2 control-label" for="url">Link</label>
<div class="col-sm-4">
<form:input type="text" path="url" class="form-control" />
</div>
</div>

<div class="form-group">
<label class="col-sm-2 control-label" for="averageTime">Average Time(s)</label>
<div class="col-sm-4">
<form:input type="text" path="averageTime" class="form-control" />
</div>
</div>

<div class="form-group">
<label class="col-sm-2 control-label" for="regionId">Course</label>
<div class="col-sm-4">
<form:select path="regionId" class="form-control">
<form:options items="${prRegionMap}" />
</form:select>
</div>
</div>

<div class="form-group">
<div class="col-sm-2"></div>
<div>
<input type="submit"
value="<spring:message code="label.addparkrun"/>"
class="btn btn-primary btn-lg" />
</div>
</div>

</form:form>

[/sourcecode]

The key points are –

  • commandName=”prCourse” – This is a reference to the form object being passed
  • action=”addAdmin.html” – This is the Controller action that will process the object
  • <form:errors path=”*” cssClass=”errorblock” element=”div” /> – Prints out errors

The mapping and method for processing this object is –

[sourcecode lang=”java”]

@RequestMapping(value = "/addAdmin", method = RequestMethod.POST)
public String addPRCourse( @Valid @ModelAttribute("prCourse") PRCourse prCourse,
BindingResult result,
Map<String, Object> map ) {

if ( result.hasErrors() ) {
List<PRCourse> prCourseList = parkrunService.listPRCourse();
map.put("prCourseList", prCourseList);

List<PRRegion> prRegionList = parkrunService.listPRRegion();
Map <Integer, String> prRegionMap = new LinkedHashMap<Integer, String> ();
for ( PRRegion prRegion : prRegionList ) {
prRegionMap.put(prRegion.getId(), prRegion.getRegionName());
}
map.put("prRegionMap", prRegionMap);

return "admin";
} else {
prCourse.setPrregion( parkrunService.getPRRegion( prCourse.getRegionId() ) );
parkrunService.addPRCourse(prCourse);
}
return "redirect:/admin";
}
[/sourcecode]

The key points are –

  • @Valid @ModelAttribute(“prCourse”) PRCourse prCourse
  • @ModelAttribute(“prCourse”) – Maps to commandName=”prCourse”
  • @Valid – References JSR303 validation in PRCourse Object
  • Check for errors – result.hasErrors()
  • Map<String, Object> map – Key, Values passed to View layer
  • return “redirect:/admin” – Is a send redirect, other options are forward or direct straight to the jsp

Passing Single Parameters

@RequestParam

A RequestParam represents a link would be of the form –

http://localhost:8080/mysite/requestParamExample?id=123

[sourcecode lang=”java”]

  @RequestMapping(value = "/requestParamExample", method = RequestMethod.GET)
  public String requestParamExample(@RequestParam("id") String id, Model model) {
      …
      return "requestParamExample";
  }

[/sourcecode]

@PathVariable

A RequestParam represents a link would be of the form –

http://localhost:8080/mysite/pathVariableExample/id/123

[sourcecode lang=”java”] @RequestMapping(value = "/pathVariableExample", method = RequestMethod.GET)
public String pathVariableExample(@PathVariable("id") Integer id) {
return "pathVariableExample";
}
[/sourcecode]

File Upload

File Upload is covered here –

http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch16s08.html

JSON

You can also use Spring MVC to serve JSON, when combined with the Jackson libraries and the @ResponseBody annotation –

[sourcecode lang=”java”] @Controller
@RequestMapping("api")
public class JSONController {

@RequestMapping("/listcourses")
@ResponseBody
public List&lt;PRCourse&gt; admin( Map&lt;String, Object&gt; map ) {
map.put("prCourse", new PRCourse());
List&lt;PRCourse&gt; prCourseList = parkrunService.listPRCourse();
return prCourseList;
}

}
[/sourcecode]

References

http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/pt03.html

About the Author Martin Farrell

My name is Martin Farrell. I have almost 20 years Java experience. I specialize inthe Spring Framework and JEE. I’ve consulted to a range of businesses, and have provide Java and Spring mentoring and training. You can learn more at About or on my consultancy website Glendevon Software

follow me on:

Leave a Comment: