Spring in Practice

Willie Wheeler's Spring blog

Annotation-based MVC in Spring 2.5

| Comments

Spring 2.5 introduces annotation-based configuration for MVC controllers. In this short article I’ll describe at a high level what you need to do to migrate your Spring 2.0 app over to Spring 2.5, at least as far as MVC is concerned. For information on migrating the other tiers, please see my article Annotation-based autowiring in Spring 2.5.

First make sure you drop spring-webmvc.jar onto your classpath. The DispatcherServlet is no longer part of spring.jar; it’s in a separate module now.

Any given controller class can be set up in one of two ways. (And you can use both approaches in a single app.) Either the controller can handle a single action or else it can handle multiple actions. Usually a form “action”, which really includes initially serving up the form and then accepting submissions of that form, would be handled with the first sort of controller, and non-form actions can be combined into a single controller, with actions being represented by methods.

Here’s an extremely basic multi-action controller that handles three separate actions (mapped to methods). The actions don’t do anything at all other than serve up the requested page.

package demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
public class SimpleController {
    public void indexHandler() { }
    public void aboutHandler() { }
    public void adminHandler() { }

Even though this is just about the simplest possible controller, there are still a few important points to highlight, especially if you’re coming from earlier versions of Spring. First you will note that the controller is a POJO. It does not extend AbstractController or any of the other controller classes that you would have extended with Spring 2.0 or earlier. Second, notice the annotations. I’ve marked the controller itself with a @Controller annotation and the individual methods with @RequestMapping annotations. (I mentioned above that you can also map a controller to a single action; in that case you would attach the @RequestMapping annotation to the controller class itself. I’m not doing that here though.) Note also that I’m doing the URL mapping with the annotation. Pretty cool to have this option. Finally, though you can’t tell from the controller, I’m using the request URL to specify the logical view name. Unless you specify otherwise, the DispatcherServlet will automatically assume that /index.html maps to the logical name “index”, that /admin.html maps to the logical name “admin”, etc. (Internally, it creates an instance of DefaultRequestToViewNameTranslator, though you don’t see this unless you want to.) This is an example of Spring’s movement toward the convention-over-configuration philosophy.

Now you need to make sure your application context config file is set up. Here’s what I have:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="demo"/>
    <bean id="viewResolver"
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>

The <component-scan> thing runs through your classes to find controllers and their annotation-based configuration. It knows which classes are controllers, as you may have guessed, because you used the @Controller annotation to label the controllers. Spring also supports @Repository for DAO layers, @Service for service layers, and @Component as a general stereotype over @Controller, @Repository and @Service.) The view resolver is just like it was with Spring 2.0.

Those are the basics. Of course there’s a lot more you’re going to want to do; for example, you’ll want to pass in request parameters, process requests, return model objects, etc. But hopefully you’ll find it useful to have a minimalistic example that gets you off the ground. Good luck!

Post migrated from my Wheeler Software site.