官术网_书友最值得收藏!

  • 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
  1. 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).
  2. 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
  1. 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.

  2. Enter the following command to create a local Git repository at this location:
    git init
    
  3. Enter the following command:
    git remote add origin https://github.com/alex-bretet/cloudstreetmarket.com
    
  4. Then, enter the git fetch command.
  5. Select both your parent projects and right-click on one of them. Go to Team | Add to index:
  6. From the top-right panel, click on the Git perspective:

    Add this perspective with the Configuring GIT in Eclipse button if you don't have it yet.

  7. From the left hierarchy (the Git perspective), select Add an existing local Git repository.
  8. A contextual window opens. Target the location of the local Git repository we just created (it should be the current workspace directory).
  9. A new repository should now appear in Git perspective.
  10. As shown in the following screenshot, right-click and select Checkout to see the latest version of the branch origin/v1.x.x.
  11. When prompted, Checkout as New Local Branch:
  12. 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.
  13. 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 observe BUILD SUCCESS each time.
  14. Finally, right-click on one project and go to Maven | Update Project. Select all the projects of the workspace and click on OK.
  15. 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).
  16. From the terminal, go to the local GIT repository:
     cd <home-directory>/workspace 
    
  17. Enter the following command:
     git pull origin v2.2.1
    
  18. Reiterate steps 13 and 14. (Be prepared to repeat these two steps every time after pulling new changes.)
  19. In the cloudstreetmarket-webapp module, a new package is now present:
     edu.zipcloud.cloudstreetmarket.portal.controllers.
    
  20. Inside this package, an InfoTagController class has been created:
    @Controller
    @RequestMapping("/info")
    public class InfoTagController {
      @RequestMapping("/helloHandler")
      @ResponseBody
      public String helloController(){
        return "hello";
      }
    }
  21. Make sure the two wars are deployed in the Tomcat server. Start the Tomcat server and access the http://localhost:8080/portal/info/helloHandler URL with your browser.
    Note

    You should see a simple hello displayed as HTML content.

  22. 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>
  23. 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();
    }
  24. 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.

主站蜘蛛池模板: 徐州市| 平安县| 桦川县| 磐石市| 沙坪坝区| 泰来县| 乐山市| 密云县| 咸宁市| 呈贡县| 永嘉县| 杂多县| 苏州市| 恩平市| 裕民县| 大英县| 稷山县| 秭归县| 麟游县| 耿马| 藁城市| 涞水县| 固安县| 怀安县| 英超| 莎车县| 永济市| 莎车县| 晴隆县| 威海市| 云龙县| 阳新县| 淮安市| 屯门区| 上思县| 无锡市| 改则县| 莒南县| 土默特右旗| 南郑县| 台州市|