Spring MVC

What is Spring MVC ?

The Spring Web model-view-controller (MVC) framework is designed around a DispatcherServlet that dispatches requests to handlers, with configurable handler mappings, view resolution, locale and theme resolution as well as support for uploading files.

Which annotations do help the default handler to handle methods ?

The default handler is based on the @Controller and @RequestMapping annotations, offering a wide range of flexible handling methods.

What does a controller do ?

A Controller is typically responsible for preparing a model Map with data and selecting a view name but it can also write directly to the response stream and complete the request.

How is a view name resolved ?

View name resolution is highly configurable through file extension or Accept header content type negotiation, through bean names, a properties file, or even a custom ViewResolver implementation.

What does a model do ?

The model (the M in MVC) is a Map interface, which allows for the complete abstraction of the view technology.  We can integrate directly with template based rendering technologies such as JSP, Velocity and Freemarker, or directly generate XML, JSON, Atom, and many other types of content. The model Map is simply transformed into an appropriate format, such as JSP request attributes, a Velocity template model.

What is DispatcherServlet ?

The DispatcherServlet is an expression of the “Front Controller” design pattern. Spring’s web MVC framework is, like many other web MVC frameworks, request-driven, designed around a central Servlet(DispatcherServlet) that dispatches requests to controllers and offers other functionality that facilitates the development of web applications. Spring’s DispatcherServlet however, does more than just that. It is completely integrated with the Spring IoC container and as such allows us to use every other feature that Spring has.

Where do we need to declare the DispatcherServlet ?

The DispatcherServlet is declared in the web.xml of our web application.

How do we declare the DispatcherServlet in web.xml ?

<web-app>
    <!-- Declare DispatcherServlet -->
    <servlet>
        <servlet-name>dispServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- load when application starts up -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- URL mapping -->
    <servlet-mapping>
        <servlet-name>dispServlet</servlet-name>
        <url-pattern>/dispServlet/*</url-pattern>
    </servlet-mapping>
</web-app>

How do we declare DispatcherServlet programmatically ?

In a Servlet 3.0+ environment, we also have the option of configuring the Servlet container programmatically. Below is the code based equivalent of the above web.xml example:

public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) {
        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/dispServlet/*");
    }
}

WebApplicationInitializer is an interface provided by Spring MVC that ensures your code-based configuration is detected and automatically used to initialize any Servlet 3 container.

List down all special beans used in DispatcherServlet ?

The Spring DispatcherServlet uses special beans to process requests and render the appropriate views. These beans are part of Spring MVC. We can choose which special beans to use by simply configuring one or more of them in the WebApplicationContext. However, we don’t need to do that initially since Spring MVC maintains a list of default beans to use if we don’t configure any.

HandlerMapping    :  Maps incoming requests to handlers and a list of pre- and post-processors (handler interceptors) based on some criteria the details of which vary by HandlerMapping implementation. The most popular implementation supports annotated controllers but other implementations exists as well.
HandlerAdapter    :  Helps the DispatcherServlet to invoke a handler mapped to a request regardless of the handler is actually invoked. For example, invoking an annotated controller requires resolving various annotations. Thus the main purpose of a HandlerAdapter is to shield the DispatcherServlet from such details.
HandlerExceptionResolver  :   Maps exceptions to views also allowing for more complex exception handling code.
ViewResolver  :  Resolves logical String-based view names to actual View types.
LocaleResolver  :  Resolves the locale a client is using, in order to be able to offer internationalized views
ThemeResolver  :  Resolves themes your web application can use, for example, to offer personalized layouts
MultipartResolver  :  Parses multi-part requests for example to support processing file uploads from HTML forms.
FlashMapManager  :  Stores and retrieves the “input” and the “output” FlashMap that can be used to pass attributes from one request to another, usually across a redirect.

How does the DispatcherServlet process requests ?

After setting up a DispatcherServlet, and a request comes in for that specific DispatcherServlet, the DispatcherServlet starts processing the request as follows:

The WebApplicationContext is searched for and bound in the request as an attribute that the controller and other elements in the process can use. It is bound by default under the key DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE.

The locale resolver is bound to the request to enable elements in the process to resolve the locale to use when processing the request (rendering the view, preparing data, and so on). If we do not need locale resolving, we do not need it.

The theme resolver is bound to the request to let elements such as views determine which theme to use. If we do not use themes, we can ignore it.

If we specify a multipart file resolver, the request is inspected for multiparts; if multiparts are found, the request is wrapped in a MultipartHttpServletRequest for further processing by other elements in the process.

An appropriate handler is searched for. If a handler is found, the execution chain associated with the handler (preprocessors, postprocessors, and controllers) is executed in order to prepare a model or rendering.

If a model is returned, the view is rendered. If no model is returned, (may be due to a preprocessor or postprocessor intercepting the request, perhaps for security reasons), no view is rendered, because the request could already have been fulfilled.

Handler exception resolvers that are declared in the WebApplicationContext pick up exceptions that are thrown during processing of the request. Using these exception resolvers allows we to define custom behaviors to address exceptions.

List down DispatcherServlet’s initialization parameters ?

contextClass  :  Class that implements WebApplicationContext, which instantiates the context used by this Servlet. By default, the XmlWebApplicationContext is used.

contextConfigLocation  :  String that is passed to the context instance (specified by contextClass) to indicate where context(s) can be found. The string consists potentially of multiple strings (using a comma as a delimiter) to support multiple contexts. In case of multiple context locations with beans that are defined twice, the latest location takes precedence.

namespace  :  Namespace of the WebApplicationContext. Defaults to [servlet-name]-servlet.

What is the use of WebMvcTest annotation in Spring MVC applications?

WebMvcTest annotation is used for unit testing Spring MVC Applications in cases where the test objective is to just focus on Spring MVC Components. In the snapshot shown above, we want to launch only the ToTestController. All other controllers and mappings will not be launched when this unit test is executed.

For Example: @WebMvcTest(value = ToTestController.class, secure = False)

What’s the difference between @Component, @Controller, @Repository & @Service annotations in Spring?

@Component is used to indicate that a class is a component. These classes are used for auto-detection and configured as bean when annotation based configurations are used.

@Controller is a specific type of component, used in MVC applications and mostly used with RequestMapping annotation.

@Repository annotation is used to indicate that a component is used as repository and a mechanism to store/retrieve/search data. We can apply this annotation with DAO pattern implementation classes.

@Service is used to indicate that a class is a Service. Usually, the business facade classes that provide some services are annotated with this.

You can use any of the above annotations for a class for auto-detection but different types are provided so that you can easily distinguish the purpose of the annotated classes.

What does the InternalResourceViewResolver do?

In Spring MVC, InternalResourceViewResolver is used to resolve “internal resource view” (in simple, it’s final output, jsp or htmp page) based on a predefined URL pattern. In additional, it allow you to add some predefined prefix or suffix to the view name (prefix + view name + suffix), and generate the final view page URL.

What’s internal resource views?

In Spring MVC or any web application, for good practice, it’s always recommended to put the entire views or JSP files under “WEB-INF” folder, to protect it from direct access via manual entered URL. Those views under “WEB-INF” folder are named as internal resource views, as it’s only accessible by the servlet or Spring’s controllers class.

How to autodetect annotated controller ?

To enable autodetection of such annotated controllers, we need to add component scanning to our configuration.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="org.springframework.samples.petclinic.web"/>
    <!-- ... -->
</beans>

What does @RequestMapping annotation do ?

We use the @RequestMapping annotation to map URLs such as /reports onto an entire class or a particular handler method. Typically the class-level annotation maps a specific request path (or path pattern) onto a form controller, with additional method-level annotations narrowing the primary mapping for a specific HTTP method request method (“GET”, “POST”, etc.) or an HTTP request parameter condition.

What is URI Template ?

URI templates can be used for convenient access to selected parts of a URL in a @RequestMapping method. A URI Template is a URI-like string, containing one or more variable names. When we substitute values for these variables, the template becomes a URI.

For example, the URI Template http://www.example.com/hello/{msg} contains the variable ‘msg’. Assigning the value ‘Welcome’ to the variable yields http://www.example.com/hello/Welcome

What is @PathVariable annotation ?

In Spring MVC we can use the @PathVariable annotation on a method argument to bind it to the value of a URI template variable:

@RequestMapping(value = "helloWorld/{msg}")
public String helloWorld(@PathVariable String msg, Model model) {
    model.addAttribute("today", new Date());
    model.addAttribute("msg", msg);
    return "hello";
}

To process the @PathVariable annotation, Spring MVC needs to find the matching URI template variable by name. We can specify it in the annotation:

@RequestMapping(value = "helloWorld/{msg}")
public String helloWorld(@PathVariable("msg") String theMsg, Model model) {
    //...
}

Or if the URI template variable name matches the method argument name we can omit that detail. As long as your code is not compiled without debugging information, Spring MVC will match the method argument name to the URI template variable name:

@RequestMapping(value = "helloWorld/{msg}")
public String helloWorld(@PathVariable String msg, Model model) {
    //...
}

How to use URI Template with regular expression ?

Sometimes you need more precision in defining URI template variables. The @RequestMapping annotation supports the use of regular expressions in URI template variables. The syntax is {varName:regex} where the first part defines the variable name and the second – the regular expression.

For example:

@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
    public void handle(@PathVariable String version, @PathVariable String extension) {
        // ...
    }
}

How does @RequestMapping annotation support path pattern ?

In addition to URI templates, the @RequestMapping annotation also supports Ant-style path patterns (for example, /reports/*.do). A combination of URI templates and Ant-style globs is also supported (for example, /reports/*/pdfs/{pdfId}).

What is matrix variable ?

The URI specification defines the possibility of including name-value pairs within path segments. Matrix variables can appear in any path segment, each matrix variable separated with a “;” (semicolon). For example: “/cars;color=red;year=2012”. Multiple values may be either “,” (comma) separated “color=red,green,blue” or the variable name may be repeated “color=red;color=green;color=blue”.

If a URL is expected to contain matrix variables, the request mapping pattern must represent them with a URI template. This ensures the request can be matched correctly regardless of whether matrix variables are present or not and in what order they are provided.

Below is an example of extracting the matrix variable “q”:
// GET /pets/42;q=11;r=22

@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET)
public void findPet(@PathVariable String petId, @MatrixVariable int q) {
  // petId == 42
  // q == 11
}

Since all path segments may contain matrix variables, in some cases you need to be more specific to identify where the variable is expected to be:

// GET /owners/42;q=11/pets/21;q=22

@RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
public void findPet(@MatrixVariable(value="q", pathVar="ownerId") int q1, @MatrixVariable(value="q", pathVar="petId") int q2) {
  // q1 == 11
  // q2 == 22
}

A matrix variable may be defined as optional and a default value specified:
// GET /pets/42

@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET)
public void findPet(@MatrixVariable(required=true, defaultValue="1") int q) {
    // q == 1
}

All matrix variables may be obtained in a Map:
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23

@RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
public void findPet(@MatrixVariable Map<String, String> matrixVars,    @MatrixVariable(pathVar="petId"") Map<String, String> petMatrixVars) {
    // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]
    // petMatrixVars: ["q" : 11, "s" : 23]
}

What is Consumable Media Type ?

We can narrow the primary mapping by specifying a list of consumable media types. The request will be matched only if the Content-Type request header matches the specified media type.

For example:

@Controller
@RequestMapping(value = "/news", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody News news, Model model) {
    //...
}

Consumable media type expressions can also be negated as in !text/plain to match to all requests other than those with Content-Type of text/plain.

The consumes condition is supported on the type and on the method level. Unlike most other conditions, when used at the type level, method-level consumable types override rather than extend type-level consumable types.

What is Producible Media Type ?

We can narrow the primary mapping by specifying a list of producible media types. The request will be matched only if the Accept request header matches one of these values. Furthermore, use of the produces condition ensures the actual content type used to generate the response respects the media types specified in the produces condition. For example:

@Controller
@RequestMapping(value = "/news/{newsId}", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String newsId, Model model) {
    //...
}

Just like with consumes, producible media type expressions can be negated as in !text/plain to match to all requests other than those with an Accept header value of text/plain.

The produces condition is supported on the type and on the method level. Unlike most other conditions, when used at the type level, method-level producible types override rather than extend type-level producible types.

What are Request Parameters and Header Values ?

We can narrow request matching through request parameter conditions such as “myParam”, “!myParam”, or “myParam=myValue”. The first two test for request parameter presence/absence and the third for a specific parameter value. Here is an example with a request parameter value condition:

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
  @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
    // implementation omitted
  }
}

The same can be done to test for request header presence/absence or to match based on a specific request header value:

@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(value = "/pets", method = RequestMethod.GET, headers="myHeader=myValue")
  public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
    // implementation omitted
  }
}

Although we can match to Content-Type and Accept header values using media type wild cards (for example “content-type=text/*” will match to “text/plain” and “text/html”), it is recommended to use the consumes and produces conditions respectively instead.

Text mainly taken from http://docs.spring.io/autorepo/docs/spring/3.2.x/spring-framework-reference/html/mvc.html