Spring MVC - Controller

Initialize Spring Controller using Autowired (Optional)

Spring MVC Controller is automatically deployed using @Controller annotation, use Spring @Autowired to initialize the controller

@Autowired
public MyController(SomeModel somemodel, SomeService someservice) {
    this.model = somemodel;
    this.service = someservice;
}
  • SomeModel and SomeService are injected to the constructors by the Spring Framework with the @Autowired annotation
    Spring bean configuration
    <bean id="someModel" class="com.innotrekker.model.SomeModel">

Spring MVC Request Mapping with Annotation

Request mapping maps an URL address to a Controller's method

  • Spring MVC DispatcherServlet servlet use the controller annotation @RequestMapping to determine what controller and what method to call to handle the request

Using @RequestMapping on a method

@Controller
public class MyController {

    @RequestMapping(value="/op", method = RequestMethod.GET)
    public ModelAndView someMethod(...) {...}
  • method = RequestMethod.GET handles HTTP Get request
  • value = "/op" define the URL pattern
    http://domain.com/my_app_context/op

Using @RequestMapping on a class & methods

// Prefix any request in this controller with /op
@Controller
@RequestMapping("/op")
public class MyController {

    // Handling "/op"  
    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView op1(...) {...}

    // Handling "/op/subop1"
    @RequestMapping(value="/subop1", method = RequestMethod.GET)
    public ModelAndView op1(...) {...}

    // Handling "/op/subop2"
    @RequestMapping(value="/subop2", method = RequestMethod.GET)
    public ModelAndView op2(...) {...}

    ...
}
  • Prefix any request in this controller with /op
    @RequestMapping("/op")
    public class MyController {
  • Handling "/op/subop1"
    @RequestMapping(value="/subop1", method = RequestMethod.GET)
    public ModelAndView op1(...) {...}

Request Mapping Parameters

@RequestMapping takes multiple parameter(s) to narrow down the HTTP request it handles

@RequestMapping(value="/find", method=RequestMethod.GET)
    public ModelAndView op2(...) {...}

@RequestMapping Parameters

Parameter Example Description
value="/to/path" value="/find" Match a URL path pattern
method=RequestMethod.Get/Post method=RequestMethod.Get Handle specific type of HTTP request only
params="someParamName=someValue" params="member=premium" Process request with a specific parameter/value pair
headers="param=value" headers="content-type=text/*" Process request with a specific header value

Restful URL Mapping

Spring provides a mechanism to map a Restful URL pattern to parameters of a controller's method

@RequestMapping(value="/find/{dept}/employee/{emp}/{date}", method = RequestMethod.GET)
public void getSalary(@PathVariable int dept, 
         @PathVariable String emp, @PathVariable Date date) {...}

For URL

/find/345/employee/john/01012010
  • @RequestMapping value="/find/{dept}/employee/{emp}/{date}"
    • assign dept to 345 with the @PathVariable annotation
    • and emp to 'john'

Spring Controller Method Parameters

A controller's method allows any number of pre-defined parameter in any order

@RequestMapping("/op1")
public ModelAndView op1()

@RequestMapping("/find")
public ModelAndView find(@PathVariable int id, HttpServletRequest req, ... )

@RequestMapping("/op2")
public ModelAndView op2(@RequstParam("product") int id, ExternalContext context)

Assign the HTTP request parameter product to the method parameter id

@RequstParam("product") int id
Spring Controller Built-in Parameters Description
@RequestParam("product") int id Map to a HTTP request parameter
@PathVariable String name Map to a part of the Restful URL
@CookieValue("cookie_name") String value Map to a HTTP cookie
@RequestHeader("content") String ctype Map to a HTTP header
ServletRequest/HttpServletRequest req Map to a Servlet request
ServletResponse/HttpServletResponse rep Map to a Servlet response
HttpSession sess Map to a HTTP session
java.util.Locale Map to the Locale object
java.io.InputStream/java.io.Reader Get the Input reader
java.io.OutputStream/java.io.Writer Get the Output writer
ExternalContext context Get the application context
org.springframework.validation.Errors Validation error
org.springframework.validation.BindingResult Date binding result
org.springframework.web.bind.support.SessionStatus Use to expire session data marked by @SessionAttributes
  • Pass the Spring model object that is accessible by the view
    • A controller can set value to the model object which later access by the view
      public void find(Map<String, Object> model) {
          model.put("user", user);              // Pass data to the view
          model.put("address", address);
      }
  • Pass the HTTP request body RequestBody to the controller's method
    public void handle(@RequestBody String body, Writer writer) throws IOException {
      writer.write(body);
    }

Spring Controller Return Object & View Name Resolution

A Controller method can return different object types. Spring MVC uses the returned object to determine the logical view name to render the page

Example below return a ModelAndView object with the view name set inside the object

@RequestMapping("/find )
    public ModelAndView find() {
       ModelAndView mav = new ModelAndView();
       mav.setViewName("home");
       return mav;    
    }

Resolving the view name from the return type of a controller method

Return type View Name Used in Resolving the View
ModelAndView The view name is set by setViewName: mav.setViewName("product")
String The name of the view
View View's value (toString)
A Model object
return new Products(1245);
The view name will be the classname of the return object (product)
Product[], ArrayList<Product>, Hashset<Product> Append the classname with "List": productList
void The view name can be set inside a controller method
public void find(ExternalContext context) {
     context.selectView("products");
}
A specific string:
"redirect:/products"
"forward:/products"
Redirect or forward to another URL "/products"

Output Result to a Request Body Directly

Write out HTML data directly inside a controller method

@RequestMapping("/ajaxHello")
@ResponseBody
public String hello()  {
  return "Hello";
}

Spring MVC Exception Handler

Exception Handler intercepts an exception and forward to a different view

Global handler

Create a Global custom exceptional handler, define a Java Class implementing HandlerExceptionResolver

package com.innotrekker.springweb.controller.exception;

import ...

public class NPEExceptionHandler implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object arg2, Exception ex) {
	// Handling Null pointer exception
	if (! (ex instanceof NullPointerException)) {
  	    return null;
	}
	// Rendering the "error" view to handle the exception
	ModelAndView mav = new ModelAndView("error");
	return mav;
    }

}

Add bean configuration in webmvc-config.xml

  • Spring will automatically register it as a Spring MVC exception handler
    <bean id="npe" class="com.innotrekker.springweb.controller.exception.NPEExceptionHandler" />

Define a Specific Exception handler for a Controller

Add a @ExceptionHandler annotation to handle a specific exception thrown by a controller

@Controller
public class MyController {

  ...

  @ExceptionHandler(NullPointerException.class)
  public String handleException(NullPointerException ex, HttpServletRequest request) {
    return "error";
  }
}
  • Define a exceptional handler to handle the null pointer exception thrown by this controller

Pass Spring Model Data to a View

Spring MVC controller put data object in ModelAndView to be rendered by a view

public ModelAndView helloHandler() {

        ModelAndView mav = new ModelAndView();

        // Use the view named "home" to display the data
        mav.setViewName("home");
        // Add a model object to be displayed by the view
        mav.addObject("message", "welcome to spring mvc");

        return mav;
    }

To access the model data in a JSP view

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

...
<c:out value="${message}"/>
...

Bulit-in Spring MVC Request Mapper

Spring supports other out of the box request mapper to map a URL to a controller without the annotation

Match a URL pattern to a controller

<bean id="flowMappings" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <value>
            /ordering/order=orderingFlowHandler
        </value>
    </property>
    <property name="order" value="0"/>
</bean>
  • If a request can be mapped to different controller by different mapper, a mapper with lower "order" value will take a higher preference
    <property name="order" value="0"/>

Convention Based Request Mapper

Spring supplies some out of the box convention based request mapper

  • Use the URL path name as the name of the controller
    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
        <property name="order" value="2"/>
    </bean>

    URL path

    /item/*

    will map to the controller ItemController

  • Use the URL path name as the name of the view
    <bean id="viewMappings" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="defaultHandler">
            <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
        </property>
        <property name="order" value="3"/>
    </bean>

    Path

    /order

    will map to the view order