Spring MVC Framework: A Comprehensive Overview
6.1 Spring MVC Summary
The Spring MVC framework is designed around a DispatcherServlet, which plays a pivotal role in distributing requests to various processors. This web framework includes a configurable processor (Handler) map, view resolution, localization, theme resolution, and support for uploading files. The processor is an implementation of the Controller interface, which defines the ModelAndView handleRequest(request, response) method.
Processor and Controller
A controller is an implementation of the Controller interface, which defines the ModelAndView handleRequest(request, response) method. You can implement this interface to create your own controller, but Spring provides an easier way of inheritance through abstract controllers such as AbstractController, AbstractCommandController, and SimpleFormController. It is essential to choose an appropriate base class, as the need for a FormController depends on the presence of a form.
View Resolution
Spring’s view resolution is highly flexible. A controller can directly return a view to the response (the return value of the ModelAndView is null). In the general case, a ModelAndView instance consists of a view name and a type of Map model, with a model of some bean-name as key and a bean object (like a command or form, containing other JavaBeans) as value. The view name resolution process is also highly configurable, either via bean names, file properties, or custom ViewResolvers.
Map-Based Model
Map-based models (MVC) are highly abstract and can be integrated with various presentation layer technologies. Any renderer can be integrated directly with Spring, whether it’s JSP, Velocity, or any other rendering technology. The map model can be converted into an appropriate format, such as JSP request attributes or Velocity template models.
Unique Features of Spring Web MVC Framework
- Clear Separation of Roles: Each role can be implemented by a special object, including the controller, validator, command object, form object, model object, Servlet distributor, mapping processor, view resolver, and others.
- Powerful and Straightforward Configuration: The framework and application classes are configured as JavaBeans, supporting other references in the context of a JavaBean, such as references to controllers in web business objects and validators.
- Adapted to be Non-Invasive Controller: You can select the appropriate subclass (simple type, command type, form type, Wizard type, multi-action, or a custom type) according to different application scenarios, instead of inheriting from a single controller.
- Reusable Business Code: You can use existing business objects as command or form objects without repeating their definition of a category of similar ActionForm.
- Customizable Binding and Validation: For example, type mismatches as application-level validation errors that keep the offending value. Another example is localized date and number binding, etc.
- Customizable Handler Mapping and View Resolution: Spring offers from simple URL mapping to complex, dedicated custom policies. In comparison, some MVC frameworks mandate a particular technique, while Spring is more flexible.
- Flexible Model Conversion: In the Spring web framework, a name/value Map can be easily integrated with various techniques to achieve the view.
- Customizable Locale and Theme Analysis: Supports JSP tag library Spring, JSTL support, Velocity (no additional intermediate layer), and others.
- Spring Bean’s Life Cycle: Can be limited to the current HTTP Request or HTTP Session.
6.2 Mapping the Request to the Controller
Many web frameworks are request-driven, designed around a central servlet conductor that dispatches requests to controllers and offers other functionality facilitating the development of web applications. However, Spring’s DispatcherServlet is more than just a request dispatcher, and it is fully integrated with the Spring IoC container, allowing you to use other functions of Spring.
Listing 1: Servlet Configuration
<Servlet>
<Servlet-name>dispatcher</Servlet-name>
<Servlet-class>org.springframework.web.servlet.DispatcherServlet</Servlet-class>
<Init-param>
<Param-name>contextConfigLocation</Param-name>
<Param-value>/WEB-INF/spring-config-mvc.xml</Param-value>
</Init-param>
<Load-on-startup>1</Load-on-startup>
</Servlet>
<Servlet-mapping>
<Servlet-name>dispatcher</Servlet-name>
<Url-pattern>*.do</Url-pattern>
</Servlet-mapping>
Listing 2: InternalResourceViewResolver Configuration
<Bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<Property name="prefix" value="/WEB-INF/jsp/"/>
<Property name="suffix" value=".jsp"/>
</Bean>
Listing 3: SimpleUrlHandlerMapping Configuration
<Bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<Property name="mappings">
<Props>
<Prop key="/helloworld.do">helloworldController</Prop>
</Props>
</Property>
</Bean>
Listing 4: HelloworldController Configuration
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class HelloworldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// Add a value to the HttpServletRequest
request.setAttribute("message", "HelloWorld");
// Return a ModelAndView object by a process viewResolver
// Page jump to /WEB-INF/jsp/helloworld.jsp
return new ModelAndView("helloworld");
}
}
Listing 5: SimpleFormController Configuration
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.mvc.SimpleFormController;
public class HelloworldController extends SimpleFormController {
public HelloworldController() {
// Set the type of form object
this.setCommandClass(User.class);
}
@Override
protected void doSubmitAction(Object command) throws Exception {
// User object will be stored in the database
User user = (User) command;
}
}