diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 2061a7e371..e4545909dc 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -29,7 +29,7 @@ This reference document provides the following sections: * <> -* <> +* <> * <> diff --git a/src/docs/asciidoc/web.adoc b/src/docs/asciidoc/web.adoc index 4567b7254f..600256dcd0 100644 --- a/src/docs/asciidoc/web.adoc +++ b/src/docs/asciidoc/web.adoc @@ -11,7 +11,7 @@ or on a reactive stack (Reactive Streams API + non-blocking runtime). The first few chapters cover the Servlet-based <> web framework including <>, <>, and <> support. Subsequent chapters cover the <> reactive web framework -including its <> functional programming model. +including its <>. include::web/web-mvc.adoc[leveloffset=+1] diff --git a/src/docs/asciidoc/web/web-integration.adoc b/src/docs/asciidoc/web/web-integration.adoc index 1e91c26870..277278a8e0 100644 --- a/src/docs/asciidoc/web/web-integration.adoc +++ b/src/docs/asciidoc/web/web-integration.adoc @@ -6,24 +6,6 @@ [[intro]] == Introduction -.Spring Web Flow -**** -Spring Web Flow (SWF) aims to be the best solution for the management of web application -page flow. - -SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and -Portlet environments. If you have a business process (or processes) that would benefit -from a conversational model as opposed to a purely request model, then SWF may be the -solution. - -SWF allows you to capture logical page flows as self-contained modules that are reusable -in different situations, and as such is ideal for building web application modules that -guide the user through controlled navigations that drive business processes. - -For more information about SWF, consult the -http://projects.spring.io/spring-webflow/[Spring Web Flow website]. -**** - This chapter details Spring's integration with third party web frameworks, such as http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF]. diff --git a/src/docs/asciidoc/web/web-mvc.adoc b/src/docs/asciidoc/web/web-mvc.adoc index e7a8a4923b..f47d4da35e 100644 --- a/src/docs/asciidoc/web/web-mvc.adoc +++ b/src/docs/asciidoc/web/web-mvc.adoc @@ -3,336 +3,198 @@ :doc-spring-security: {doc-root}/spring-security/site/docs/current/reference [[mvc-introduction]] -== Introduction to Spring Web MVC framework -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, time zone and theme resolution as well as support for -uploading files. The default handler is based on the `@Controller` and `@RequestMapping` -annotations, offering a wide range of flexible handling methods. With the introduction -of Spring 3.0, the `@Controller` mechanism also allows you to create RESTful Web sites -and applications, through the `@PathVariable` annotation and other features. - -**** -"Open for extension..." -A key design principle in Spring Web MVC and in Spring in general is the "__Open for -extension, closed for modification__" principle. - -Some methods in the core classes of Spring Web MVC are marked `final`. As a developer -you cannot override these methods to supply your own behavior. This has not been done -arbitrarily, but specifically with this principle in mind. - -For an explanation of this principle, refer to __Expert Spring Web MVC and Web Flow__ by -Seth Ladd and others; specifically see the section "A Look At Design," on page 117 of -the first edition. Alternatively, see - -* https://www.cs.duke.edu/courses/fall07/cps108/papers/ocp.pdf[Bob Martin, The Open-Closed - Principle (PDF)] - -You cannot add advice to final methods when you use Spring MVC. For example, you cannot -add advice to the `AbstractController.setSynchronizeOnSession()` method. Refer to -<> -for more information on AOP proxies and why you cannot add advice to final methods. -**** - -In Spring Web MVC you can use any object as a command or form-backing object; you do not -need to implement a framework-specific interface or base class. Spring's data binding is -highly flexible: for example, it treats type mismatches as validation errors that can be -evaluated by the application, not as system errors. Thus you do not need to duplicate your -business objects' properties as simple, untyped strings in your form objects simply to -handle invalid submissions, or to convert the Strings properly. Instead, it is often -preferable to bind directly to your business objects. - -Spring's view resolution is extremely flexible. 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. 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. The model -(the M in MVC) is a `Map` interface, which allows for the complete abstraction of the -view technology. You can integrate directly with template based rendering technologies -such as JSP 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 or a FreeMarker template model. - - - -[[mvc-features]] -=== Features of Spring Web MVC - -.Spring Web Flow -**** -Spring Web Flow (SWF) aims to be the best solution for the management of web application -page flow. - -SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and -Portlet environments. If you have a business process (or processes) that would benefit -from a conversational model as opposed to a purely request model, then SWF may be the -solution. - -SWF allows you to capture logical page flows as self-contained modules that are reusable -in different situations, and as such is ideal for building web application modules that -guide the user through controlled navigations that drive business processes. - -For more information about SWF, consult the -http://projects.spring.io/spring-webflow/[Spring Web Flow website]. -**** - -Spring's web module includes many unique web support features: - -* __Clear separation of roles__. Each role -- controller, validator, command object, - form object, model object, `DispatcherServlet`, handler mapping, view resolver, and so - on -- can be fulfilled by a specialized object. -* __Powerful and straightforward configuration of both framework and application classes - as JavaBeans__. This configuration capability includes easy referencing across - contexts, such as from web controllers to business objects and validators. -* __Adaptability, non-intrusiveness, and flexibility.__ Define any controller method - signature you need, possibly using one of the parameter annotations (such as - @RequestParam, @RequestHeader, @PathVariable, and more) for a given scenario. -* __Reusable business code, no need for duplication__. Use existing business objects - as command or form objects instead of mirroring them to extend a particular framework - base class. -* __Customizable binding and validation__. Type mismatches as application-level - validation errors that keep the offending value, localized date and number binding, - and so on instead of String-only form objects with manual parsing and conversion to - business objects. -* __Customizable handler mapping and view resolution__. Handler mapping and view - resolution strategies range from simple URL-based configuration, to sophisticated, - purpose-built resolution strategies. Spring is more flexible than web MVC frameworks - that mandate a particular technique. -* __Flexible model transfer__. Model transfer with a name/value `Map` supports easy - integration with any view technology. -* __Customizable locale, time zone and theme resolution, support for JSPs with or without - Spring tag library, support for JSTL, support for FreeMarker without the need for extra - bridges, and so on.__ -* __A simple yet powerful JSP tag library known as the Spring tag library that provides - support for features such as data binding and themes__. The custom tags allow for - maximum flexibility in terms of markup code. For information on the tag library - descriptor, see the appendix entitled <> -* __A JSP form tag library, introduced in Spring 2.0, that makes writing forms in JSP - pages much easier.__ For information on the tag library descriptor, see the appendix - entitled <> -* __Beans whose lifecycle is scoped to the current HTTP request or HTTP `Session`.__ - This is not a specific feature of Spring MVC itself, but rather of the - `WebApplicationContext` container(s) that Spring MVC uses. These bean scopes are - described in <> - - - -[[mvc-introduction-pluggability]] -=== Pluggability of other MVC implementations -Non-Spring MVC implementations are preferable for some projects. Many teams expect to -leverage their existing investment in skills and tools, for example with JSF. - -If you do not want to use Spring's Web MVC, but intend to leverage other solutions that -Spring offers, you can integrate the web MVC framework of your choice with Spring -easily. Simply start up a Spring root application context through its -`ContextLoaderListener`, and access it through its `ServletContext` attribute (or -Spring's respective helper method) from within any action object. No "plug-ins" -are involved, so no dedicated integration is necessary. From the web layer's point of -view, you simply use Spring as a library, with the root application context instance as -the entry point. - -Your registered beans and Spring's services can be at your fingertips even without -Spring's Web MVC. Spring does not compete with other web frameworks in this scenario. -It simply addresses the many areas that the pure web MVC frameworks do not, from bean -configuration to data access and transaction handling. So you can enrich your -application with a Spring middle tier and/or data access tier, even if you just want -to use, for example, the transaction abstraction with JDBC or Hibernate. +== Introduction to Spring Web MVC +Spring Web MVC is the Servlet-based, web framework included in the Spring Framework. +Its name is based on the name of the module, "spring-webmvc", but most people call +it simply Spring MVC. +The Spring Framework also includes the reactive, <> +web framework that runs on on Servlet containers via Servlet 3.1 non-blocking I/O +as well as on other non-blocking runtimes such as Netty and Undertow. [[mvc-servlet]] == The DispatcherServlet -Spring's web MVC framework is, like many other web MVC frameworks, request-driven, -designed around a central Servlet 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 you to use every other feature that Spring -has. +Spring MVC, like many other web frameworks, is designed around the front controller +pattern with a central `Servlet`, the `DispatcherServlet`, dispatching incoming +requests to registered handlers for processing requests, providing convenient mapping +and exception handling facilities. -The request processing workflow of the Spring Web MVC `DispatcherServlet` is illustrated -in the following diagram. The pattern-savvy reader will recognize that the -`DispatcherServlet` is an expression of the "Front Controller" design pattern (this is a -pattern that Spring Web MVC shares with many other leading web frameworks). +The `DispatcherServlet` provides the shared algorithm for processing requests while +actual work is performed by configurable, delegate components. This model is very +flexible and it can be used with just about any workflow, with the installation of the +appropriate delegate components +(see <>). -.The request processing workflow in Spring Web MVC (high level) -image::images/mvc.png[] +The `DispatcherServlet` uses Spring configuration to discover the delegate components +it needs to perform handler mapping, view resolution, and much more. As an actual +`Servlet` it needs to be declared and mapped according to the Servlet specification. +This can be done through code configuration or in`web.xml`. -The `DispatcherServlet` is an actual `Servlet` (it inherits from the `HttpServlet` base -class), and as such is declared in your web application. You need to map requests that -you want the `DispatcherServlet` to handle, by using a URL mapping. Here is a standard -Java EE Servlet configuration in a Servlet 3.0+ environment: +Below is an example of code-based configuration where `WebApplicationInitializer` is an +interface provided by Spring MVC that ensures this Java-based configuration is +auto-detected by the Servlet container (see +<> for more details): [source,java,indent=0] [subs="verbatim,quotes"] ---- - public class MyWebApplicationInitializer implements WebApplicationInitializer { +public class MyWebApplicationInitializer implements WebApplicationInitializer { - @Override - public void onStartup(ServletContext container) { - ServletRegistration.Dynamic registration = container.addServlet("example", new DispatcherServlet()); - registration.setLoadOnStartup(1); - registration.addMapping("/example/*"); - } + @Override + public void onStartup(ServletContext servletCxt) { - } + // Load Spring web application configuration + AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext(); + cxt.register(AppConfig.class); + cxt.refresh(); + + // Create DispatcherServlet + DispatcherServlet servlet = new DispatcherServlet(cxt); + + // Register and map the Servlet + ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet); + registration.setLoadOnStartup(1); + registration.addMapping("/app/*"); + } + +} ---- -In the preceding example, all requests starting with `/example` will be handled by the -`DispatcherServlet` instance named `example`. +In addition to using the ServletContext API directly as shown above, you can also extend +the convenient base class `AbstractAnnotationConfigDispatcherServletInitializer` and +override specific methods to customize it (an example is shown later under +<>). -`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. An abstract base class implementation of this interface named -`AbstractAnnotationConfigDispatcherServletInitializer` makes it even easier to register the -`DispatcherServlet` by simply specifying its servlet mapping and listing configuration -classes - it's even the recommended way to set up your Spring MVC application. -See <> for more details. - -The `DispatcherServlet` is an actual `Servlet` (it inherits from the `HttpServlet` base -class), and as such is declared in the `web.xml` of your web application. You need to -map requests that you want the `DispatcherServlet` to handle, by using a URL mapping in -the same `web.xml` file. This is standard Java EE Servlet configuration; the following -example shows such a `DispatcherServlet` declaration and mapping: - -Below is the `web.xml` equivalent of the above code based example: +Below is the `web.xml` equivalent of the above code-based example: [source,xml,indent=0] [subs="verbatim,quotes"] ---- - - - example - org.springframework.web.servlet.DispatcherServlet - 1 - + - - example - /example/* - + + org.springframework.web.context.ContextLoaderListener + - + + contextConfigLocation + /WEB-INF/app-context.xml + + + + app + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + + + 1 + + + + app + /app/* + + + ---- -As detailed in <>, -`ApplicationContext` instances in Spring can be scoped. -In the Web MVC framework, each `DispatcherServlet` has its own `WebApplicationContext`, -which inherits all the beans already defined in the root `WebApplicationContext`. -The root `WebApplicationContext` should contain all the -infrastructure beans that should be shared between your other contexts and Servlet -instances. These inherited beans can be overridden in the servlet-specific -scope, and you can define new scope-specific beans local to a given Servlet instance. +[[mvc-servlet-context-hierarchy]] +=== WebApplicationContext Hierarchy + +For many applications, a single `WebApplicationContext` is simple and sufficient. +It is also possible to set up a context hierarchy where one root `WebApplicationContext` +is shared across multiple `DispatcherServlet` (or other `Servlet`) instances each with +its own `WebApplicationContext` configuration +(see <> +for more details). + +The root `WebApplicationContext` contains infrastructure beans (e.g. data repositories, +business services) that need to be shared across multiple Servlet instances. These beans +are effectively inherited and can be overridden (re-declared) in the Servlet-specific +context, which also contains beans local to the given `Servlet`. -.Typical context hierarchy in Spring Web MVC image::images/mvc-context-hierarchy.png[] -Upon initialization of a `DispatcherServlet`, Spring MVC looks for a file named -__[servlet-name]-servlet.xml__ in the `WEB-INF` directory of your web application and -creates the beans defined there, overriding the definitions of any beans defined with -the same name in the global scope. - -Consider the following `DispatcherServlet` Servlet configuration (in the `web.xml` file): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - **golfing** - org.springframework.web.servlet.DispatcherServlet - 1 - - - **golfing** - /golfing/* - - ----- - -With the above Servlet configuration in place, you will need to have a file called -`/WEB-INF/golfing-servlet.xml` in your application; this file will contain all of your -Spring Web MVC-specific components (beans). You can change the exact location of this -configuration file through a Servlet initialization parameter (see below for details). - -It is also possible to have just one root context for single DispatcherServlet scenarios. - -.Single root context in Spring Web MVC -image::images/mvc-root-context.png[] - -This can be configured by setting an empty contextConfigLocation servlet init parameter, -as shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - contextConfigLocation - /WEB-INF/root-context.xml - - - dispatcher - org.springframework.web.servlet.DispatcherServlet - - contextConfigLocation - - - 1 - - - dispatcher - /* - - - org.springframework.web.context.ContextLoaderListener - - ----- - - -The `WebApplicationContext` is an extension of the plain `ApplicationContext` that has +[NOTE] +==== +`WebApplicationContext` is an extension of the plain `ApplicationContext` that has some extra features necessary for web applications. It differs from a normal `ApplicationContext` in that it is capable of resolving themes (see <>), and that it knows which Servlet it is associated with (by having -a link to the `ServletContext`). The `WebApplicationContext` is bound in the -`ServletContext`, and by using static methods on the `RequestContextUtils` class you can +a link to the `ServletContext`). `WebApplicationContext` is bound to the +`ServletContext` and by using static methods on the `RequestContextUtils` class you can always look up the `WebApplicationContext` if you need access to it. +==== -Note that we can achieve the same with java-based configurations: +Below is an example of configuration that sets up a `WebApplicationContext` hierarchy: [source,java,indent=0] [subs="verbatim,quotes"] ---- - public class GolfingWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { + public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { - @Override - protected Class[] getRootConfigClasses() { - // GolfingAppConfig defines beans that would be in root-context.xml - return new Class[] { GolfingAppConfig.class }; - } + @Override + protected Class[] getRootConfigClasses() { + return new Class[] { RootConfig.class }; + } - @Override - protected Class[] getServletConfigClasses() { - // GolfingWebConfig defines beans that would be in golfing-servlet.xml - return new Class[] { GolfingWebConfig.class }; - } + @Override + protected Class[] getServletConfigClasses() { + return new Class[] { App1Config.class }; + } - @Override - protected String[] getServletMappings() { - return new String[] { "/golfing/*" }; - } - - } + @Override + protected String[] getServletMappings() { + return new String[] { "/app1/*" }; + } + } ---- +Below is the `web.xml` equivalent: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + org.springframework.web.context.ContextLoaderListener + + + + contextConfigLocation + /WEB-INF/root-context.xml + + + + app1 + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + /WEB-INF/app1-context.xml + + 1 + + + + app1 + /app1/* + + + +---- + + + [[mvc-servlet-special-bean-types]] === Special Bean Types In the WebApplicationContext -The Spring `DispatcherServlet` uses special beans to process requests and render the +The `DispatcherServlet` uses special beans to process requests and render the appropriate views. These beans are part of Spring MVC. You can choose which special beans to use by simply configuring one or more of them in the `WebApplicationContext`. However, you don't need to do that initially since Spring MVC maintains a list of