- Spring MVC Cookbook
- Alex Bretet
- 2218字
- 2021-07-16 13:03:19
Configuring a controller with simple URL mapping
This recipe introduces the Spring MVC controller with its simplest implementation.
Getting ready
We will discover later on, and especially in Chapter 3, Working with Java Persistence and Entities, that Spring MVC is a great tool to build a REST API. Here, we will focus on how to create a controller that prints some content in the response.
Starting with this recipe, we will be using GIT to follow each iteration that has been made to develop the cloudstreetmarket
application. After the initial setup, you will appreciate how smoothly you can upgrade.
How to do it...
This recipe comes with two initial sections for installing and configuring GIT.
Downloading and installing GIT
- To download GIT, go to the GIT download page at https://git-scm.com/download. Select the right product corresponding to your environment (Mac OS X, Windows, Linux, or Solaris).
- To install GIT for Linux and Solaris, execute the suggested installation commands using the system's native package manager.
For Mac OS X, double-click on the downloaded dmg
file to extract the package on your hard drive. Navigate to the extracted directory and double-click on the pkg
file. Select all the default options, one step after an other, up to the Successful Installation screen. Close the screen.
For Windows, execute the downloaded program and follow the default options for every step up to these screens:
- Adjusting your PATH environment: Select the Use Git from the Windows Command Prompt option
- Choosing the SSH executable: Select the Use OpenSSH option
- Configuring the line endings conversions: Select the Checkout Windows-style and commit Unix-style line endings options
- Configuring the terminal emulator to use Git Bash: Select Use Windows' default console window
- Configuring experimental performance tweaks: Don't tick the Enable file system caching checkbox
Let the installation finish and click on the Finish button.
For verification, open your terminal and enter the following command:
git –version
This command should display the installed version. The presented installation guidelines were associated with GIT 2.6.3
.
Configuring GIT in Eclipse
- We will first initialize the local repository from the terminal. Go to your workspace location:
cd <home-directory>/workspace
.Replace
<home-directory>
with your own home path. - Enter the following command to create a local Git repository at this location:
git init
- Enter the following command:
git remote add origin https://github.com/alex-bretet/cloudstreetmarket.com
- Then, enter the
git fetch
command. - Select both your parent projects and right-click on one of them. Go to Team | Add to index:
- From the top-right panel, click on the Git perspective:
Add this perspective with the
button if you don't have it yet.
- From the left hierarchy (the Git perspective), select Add an existing local Git repository.
- A contextual window opens. Target the location of the local Git repository we just created (it should be the current workspace directory).
- A new repository should now appear in Git perspective.
- As shown in the following screenshot, right-click and select Checkout to see the latest version of the branch origin/v1.x.x.
- When prompted, Checkout as New Local Branch:
- The actual workspace should now be synchronized with the branch v1.x.x. This branch reflects the state of the environment at the end of Chapter 1, Setup Routine for an Enterprise Spring Application.
- Right-click on zipcloud-parent to execute Run as | Maven clean and Run as | Maven install. Then, do the same operation on
cloudstreetmarket-parent
. You will observeBUILD SUCCESS
each time. - Finally, right-click on one project and go to Maven | Update Project. Select all the projects of the workspace and click on OK.
- If you still have a red warning in one of your projects (as shown in the previous screenshot), you will probably have to reattach a target runtime environment to cloudstreetmarket-api and cloustreetmarket-webapp (as per Chapter 1 , Setup Routine for an Enterprise Spring Application, 2nd recipe, 7th step).
- From the terminal, go to the local GIT repository:
cd <home-directory>/workspace
- Enter the following command:
git pull origin v2.2.1
- Reiterate steps 13 and 14. (Be prepared to repeat these two steps every time after pulling new changes.)
- In the cloudstreetmarket-webapp module, a new package is now present:
edu.zipcloud.cloudstreetmarket.portal.controllers.
- Inside this package, an
InfoTagController
class has been created:@Controller @RequestMapping("/info") public class InfoTagController { @RequestMapping("/helloHandler") @ResponseBody public String helloController(){ return "hello"; } }
- Make sure the two
wars
are deployed in the Tomcat server. Start the Tomcat server and access thehttp://localhost:8080/portal/info/helloHandler
URL with your browser.Note
You should see a simple hello displayed as HTML content.
- In the
cloudstreetmarket-webapp/src/main/webapp/WEB-INF/dispatcher-context.xml
file, the following bean definition is added:<bean id="webAppVersion" class="java.lang.String"> <constructor-arg value="1.0.0"/> </bean>
- The following method and members in the
InfoTagController
class are also added:@Autowired private WebApplicationContext webAppContext; private final static LocalDateTime startDateTime = LocalDateTime.now(); private final static DateTimeFormatter DT_FORMATTER = DateTimeFormatter.ofPattern("EEE, d MMM yyyy h:mm a"); @RequestMapping("/server") @ResponseBody public String infoTagServer(){ return new StringJoiner("<br>") .add("-------------------------------------") .add(" Server: "+ webAppContext.getServletContext().getServerInfo()) .add(" Start date: "+ startDateTime.format(DT_FORMATTER)) .add(" Version: " + webAppContext.getBean("webAppVersion")) .add("--------------------------------------") .toString(); }
- Now, access the
http://localhost:8080/portal/info/server
URL with your browser.Note
You should see the following content rendered as an HTML document:
-------------------------------------------------- Server: Apache Tomcat/8.0.14 Start date: Sun, 16 Nov 2014 12:10 AM Version: 1.0.0 ---------------------------------------------------
How it works...
We are going to draft an overview of Spring MVC as a Framework. We will then review how a Controller is configured from the DispatcherServlet
, the controller-level annotations, and from the method-handler signatures.
Spring MVC overview
Spring MVC implements two common design patterns: the front controller design pattern and the MVC design pattern.
Front controller
A system designed as a Front controller exposes a single entry point for all incoming requests. In Java Web environments, this entry point is usually a servlet—a unique servlet that dispatches and delegates to other components.
Note
In the case of Spring MVC, this unique servlet is the DispatcherServlet
.
Servlets are standards in the Java web. They are associated to predefined URL paths and are registered in deployment descriptors (the web.xml
files). Parsing deployment descriptors, the servlet-container (such as Apache Tomcat) identifies the declared servlets and their URL mapping. At runtime, the servlet-container intercepts every HTTP client request and creates a new Thread for each one of them. Those Threads will call the matching relevant servlets with Java-converted request and response objects.
MVC design pattern
The MVC design pattern is more of an architectural style. It describes the application as a whole. It encourages a clear separation of concerns between three different layers that the request thread has to pass through: the Model, the View, and the Controller—the Controller, the Model, and then the View to be accurate.

When a client request is intercepted by the servlet-container, it is routed to the DispatcherServlet
. The DispatcherServlet
sends the request to one Controller (one controller method-handler), which has a configuration matching the request state (if a match is found).
The Controller orchestrates the business logic, the model generation and ultimately chooses a View for the model and the response. In this perspective, the model represents a populated data structure handled by the controller and given to the view for visualization purposes.
But the three components (Model, View, and Controller) can also be visualized at a Macro scale as independent static layers. Each of these components is a layer and a placeholder for every inpidual constituent, part of the category. The Controller layer contains all the registered controllers as well as the Web Interceptors and converters; the Model generation layer (and Business logic layer) contains the business services and data access components. The View layer encloses the templates (JSPs for example) and other web client-side components.
Spring MVC flow
The Spring MVC flow can be represented with the following diagram:

We previously mentioned that Spring MVC implements a front controller pattern. The entry point is the DispatcherServlet
. This DispatcherServlet
relies on a HandlerMapping
implementation. With different strategies and specificities, the HandlerMapping
resolves a Controller method-handler for the request.
Once the DispatcherServlet
has a Controller method-handler, it dispatches the request to it. The method-handler returns a View name (or directly the View itself) and also the populated model object to the DispatcherServlet
.
With a View name, the DispatcherServlet
asks a ViewResolver
implementation to find and select a View.
With the request, a View, and a Model, the DispatcherServlet
has everything to build the client response. The view is processed with all these elements and the response is finally returned to the servlet-container.
DispatcherServlet – the Spring MVC entrypoint
As explained, the DispatcherServlet
is quite a central piece in Spring MVC. It intercepts the client requests that target predefined URL paths for the application. It maps them to handlers that belong to business logic operators (Controllers, Interceptors, Filters, and so on). It also provides a set of tools, available as beans for solving recurring web development issues and techniques such as serving a centralized and modular View layer, handling internationalisation, themes, handing exceptions, and so on.
Before everything, the DispatcherServlet
is a servlet and is defined as such in the web.xml
file with a servlet configuration and its servlet-mapping. The code is as follows:
<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>
In our application, in the cloudstreetmarket-webapp, the DispatcherServlet
is named spring and covers the full context-path of the application: /*
.
We have already seen that each DispatcherServlet
has a restricted-scope WebApplicationContext
that inherits the beans from the root ApplicationContext
.
By default, for the WebApplicationContext
, Spring MVC looks in the /WEB-INF
directory for a configuration file named {servletName}-servlet.xml
. We have, however, overridden this default name and location through the initialization parameter contextConfigLocation
:
<servlet> <servlet-name>spring</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcher-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
Still in the web.xml
, you can see that the root application context (classpath*:/META-INF/spring/*-config.xml
) starts with the ContextLoaderListener
:
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
Annotation-defined controllers
Spring MVC controllers are the place where client requests really start to be processed by the business-specific code. Since Spring 2.5, we have been able to use annotations on controllers so we don't have to explicitly declare them as beans in configuration. This makes their implementation much easier to extend and understand.
@Controller
A @Controller
annotation tags a class as a Web controller. It remains a Spring Stereotype for presentation layers. The main purpose of defining a Spring Stereotype is to make a target type or method discoverable during the Spring classpath scanning which is activated by package with the following command:
<context:component-scan base-package="edu.zipcloud.cloudstreetmarket.portal"/>
There is not much custom logic related to this annotation. We could run a Controller with other Stereotype annotations (@Component
or @Service
) if we don't bother making the application a cleaner place.
@RequestMapping
The @RequestMapping
annotations define handlers onto Controller classes and/or onto controller methods. These annotations are looked-up among stereotyped classes by the DispatcherServlet
. The main idea behind the @RequestMapping
annotations is to define a primary path mapping on the class-level and to narrow HTTP request methods, headers, parameters, and media-types on the methods.
To implement this narrowing, the @RequestMapping
annotation accepts comma-separated parameters within parentheses.
Consider the following example:
@RequestMapping(value="/server", method=RequestMethod.GET)
Available parameters for @RequestMapping
are summarized in the following table:
All these parameters can be used both at the type and method level. When used at the type level, all method-level parameters inherit the parent-level narrowing.
Controller method-handler signatures
Several constituents make a Controller method-handler. Here's another example of such a handler with Spring MVC:
@RequestMapping(value="/index") public ModelAndView getRequestExample(ServletRequest request){ ModelAndView mav = new ModelAndView(); mav.setViewName("index"); mav.addObject("variable1", new ArrayList<String>()); return mav; }
We have just talked about how to use the @RequestMapping
annotation. With regard to the method signature, this annotation can only be placed before the return-type.
Supported method arguments types
Declaring specific types of arguments for handler methods can get Spring to automatically inject in them references to external objects. Objects related to the request lifecycle, the session, or to the application configuration. With the benefit of being scoped for the method, those argument types are presented in the following table:
Supported annotations for method arguments
A set of native annotations for method-handler arguments has been designed. They must be seen as handles that configure the web behavior of controller methods in regard to incoming requests or the response yet to be built.
They identify abstractions for handy Spring MVC functions such as request parameter binding, URI path variable binding, injection-to-argument of request payloads, HTML form-parameter binding, and so on.
These annotations have to be placed just before the method argument to be populated:
@RequestMapping(value="/index") public ModelAndView getRequestExample(@RequestParam("exP1") String exP1){ ModelAndView mav = new ModelAndView(); mav.setViewName("index"); mav.addObject("exP1", exP1); return mav; }
Supported return Types
Spring MVC, with different possible controller method return Types, allows us to specify either the response sent back to the client or the necessary configuration for targeting or populating with variables an intermediate View layer. Depending upon what we want to do or the actual application state, we have the choice among the following:
There's more...
In the InfoTagController.infoTagServer()
method-handler, we have used the @ResponseBody
annotation before the return Type. This annotation has been borrowed from the REST-specific tools. When you don't need to process a View, the @ResponseBody
directive will use the registered Spring converters to marshal the returned object into the expected format (XML, JSON, and so on). It will then write the marshalled content to the Response body (as the Response payload).
In the case of a String object with no more configurations, it is printed out as such in the Response body. We could have used the ResponseEntity<String>
return Type to achieve the same goal.
- Vue.js設(shè)計(jì)與實(shí)現(xiàn)
- 軟件項(xiàng)目估算
- Mobile Application Development:JavaScript Frameworks
- Python快樂編程:人工智能深度學(xué)習(xí)基礎(chǔ)
- Java EE 6 企業(yè)級(jí)應(yīng)用開發(fā)教程
- Java應(yīng)用開發(fā)與實(shí)踐
- 趣學(xué)Python算法100例
- R語(yǔ)言游戲數(shù)據(jù)分析與挖掘
- 名師講壇:Java微服務(wù)架構(gòu)實(shí)戰(zhàn)(SpringBoot+SpringCloud+Docker+RabbitMQ)
- 學(xué)Python也可以這么有趣
- R Data Analysis Cookbook(Second Edition)
- Visual C++開發(fā)入行真功夫
- Node學(xué)習(xí)指南(第2版)
- Django Design Patterns and Best Practices
- QlikView Unlocked