痴情的高山 · 三角进攻造就了乔丹科比,为何安东尼不行?禅师 ...· 4 月前 · |
豁达的可乐 · 商务部等5部门关于进一步做好二手车出口工作的通知· 7 月前 · |
爽快的绿豆 · 7-摊牌 - 谁是那个他 - 包子漫画· 1 年前 · |
忐忑的铁板烧 · 央视摄影师庆幸未撞坏博尔特 ...· 1 年前 · |
欢乐的莲藕 · 8家出售不记名手机空号、死号网站被关停-新华网· 1 年前 · |
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
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
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
Section 9.6.1, “Understanding AOP proxies”
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 need not 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, Velocity
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, a
Velocity template model.
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, Struts, 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 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 and theme resolution, support for JSPs with or without Spring tag library, support for JSTL, support for Velocity without the need for extra bridges, and so
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 Appendix G, spring.tld
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 Appendix H, spring-form.tld
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
Section 5.5.4, “Request, session, and global session scopes”
Non-Spring MVC implementations are preferable for some projects. Many teams expect to leverage their existing investment in skills and tools. A large body of knowledge and experience exist for the Struts framework. If you can abide Struts' architectural flaws, it can be a viable choice for the web layer; the same applies to WebWork and other web MVC frameworks.
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
ServletContext
attribute (or Spring's
respective helper method) from within a Struts or WebWork action. 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 Struts or WebWork 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.
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.
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
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:
<web-app> <servlet> <servlet-name>example</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>example</servlet-name> <url-pattern>/example/*</url-pattern> </servlet-mapping> </web-app>
In the preceding example, all requests starting with
/example
will be handled by the
DispatcherServlet
instance named
example
.
In a Servlet 3.0+ environment, you also have the
option of configuring the Servlet container programmatically. Below is the code
based equivalent of the above
web.xml
example:
public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet()); registration.setLoadOnStartup(1); registration.addMapping("/example/*");
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 interace namedAbstractDispatcherServletInitializer
makes it even easier to register theDispatcherServlet
by simply specifying its servlet mapping. See Code-based Servlet container initialization for more details.The above is only the first step in setting up Spring Web MVC. You now need to configure the various beans used by the Spring Web MVC framework (over and above the
DispatcherServlet
itself).As detailed in Section 5.14, “Additional Capabilities of the
ApplicationContext
”,ApplicationContext
instances in Spring can be scoped. In the Web MVC framework, eachDispatcherServlet
has its ownWebApplicationContext
, which inherits all the beans already defined in the rootWebApplicationContext
. 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.Upon initialization of a
DispatcherServlet
, Spring MVC looks for a file named[servlet-name]-servlet.xml
in theWEB-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 theweb.xml
file):<web-app> <servlet> <servlet-name>golfing</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>golfing</servlet-name> <url-pattern>/golfing/*</url-pattern> </servlet-mapping> </web-app>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).The
WebApplicationContext
is an extension of the plainApplicationContext
that has some extra features necessary for web applications. It differs from a normalApplicationContext
in that it is capable of resolving themes (see Section 17.9, “Using themes”), and that it knows which Servlet it is associated with (by having a link to theServletContext
). TheWebApplicationContext
is bound in theServletContext
, and by using static methods on theRequestContextUtils
class you can always look up theWebApplicationContext
if you need access to it.The Spring
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 theWebApplicationContext
. However, you don't need to do that initially since Spring MVC maintains a list of default beans to use if you don't configure any. More on that in the next section. First see the table below listing the special bean types theDispatcherServlet
relies on.Table 17.1. Special bean types in the
WebApplicationContext
Bean type Explanation HandlerMapping Maps incoming requests to handlers and a list of pre- and post-processors (handler interceptors) based on some criteria the details of which vary by HandlerMapping
implementation. The most popular implementation supports annotated controllers but other implementations exists as well.HandlerAdapter Helps the DispatcherServlet
to invoke a handler mapped to a request regardless of the handler is actually invoked. For example, invoking an annotated controller requires resolving various annotations. Thus the main purpose of aHandlerAdapter
is to shield theDispatcherServlet
from such details.HandlerExceptionResolver Maps exceptions to views also allowing for more complex exception handling code. ViewResolver Resolves logical String-based view names to actual View
types.LocaleResolver Resolves the locale a client is using, in order to be able to offer internationalized views ThemeResolver Resolves themes your web application can use, for example, to offer personalized layouts MultipartResolver Parses multi-part requests for example to support processing file uploads from HTML forms. FlashMapManager Stores and retrieves the "input" and the "output" FlashMap
that can be used to pass attributes from one request to another, usually across a redirect.As mentioned in the previous section for each special bean the
DispatcherServlet
maintains a list of implementations to use by default. This information is kept in the fileDispatcherServlet.properties
in the packageorg.springframework.web.servlet
.All special beans have some reasonable defaults of their own. Sooner or later though you'll need to customize one or more of the properties these beans provide. For example it's quite common to configure an
InternalResourceViewResolver
settings itsprefix
property to the parent location of view files.Regardless of the details, the important concept to understand here is that once you configure a special bean such as an
InternalResourceViewResolver
in yourWebApplicationContext
, you effectively override the list of default implementations that would have been used otherwise for that special bean type. For example if you configure anInternalResourceViewResolver
, the default list ofViewResolver
implementations is ignored.In Section 17.15, “Configuring Spring MVC” you'll learn about other options for configuring Spring MVC including MVC Java config and the MVC XML namespace both of which provide a simple starting point and assume little knowledge of how Spring MVC works. Regardless of how you choose to configure your application, the concepts explained in this section are fundamental should be of help to you.
After you set up a
DispatcherServlet
, and a request comes in for that specificDispatcherServlet
, theDispatcherServlet
starts processing the request as follows:The
WebApplicationContext
is searched for and bound in the request as an attribute that the controller and other elements in the process can use. It is bound by default under the keyDispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE
.The locale resolver is bound to the request to enable elements in the process to resolve the locale to use when processing the request (rendering the view, preparing data, and so on). If you do not need locale resolving, you do not need it.
The theme resolver is bound to the request to let elements such as views determine which theme to use. If you do not use themes, you can ignore it.
If you specify a multipart file resolver, the request is inspected for multiparts; if multiparts are found, the request is wrapped in a
MultipartHttpServletRequest
for further processing by other elements in the process. See Section 17.10, “Spring's multipart (file upload) support” for further information about multipart handling.An appropriate handler is searched for. If a handler is found, the execution chain associated with the handler (preprocessors, postprocessors, and controllers) is executed in order to prepare a model or rendering.
If a model is returned, the view is rendered. If no model is returned, (may be due to a preprocessor or postprocessor intercepting the request, perhaps for security reasons), no view is rendered, because the request could already have been fulfilled.
Handler exception resolvers that are declared in the
WebApplicationContext
pick up exceptions that are thrown during processing of the request. Using these exception resolvers allows you to define custom behaviors to address exceptions.The Spring
DispatcherServlet
also supports the return of the last-modification-date, as specified by the Servlet API. The process of determining the last modification date for a specific request is straightforward: theDispatcherServlet
looks up an appropriate handler mapping and tests whether the handler that is found implements theLastModified
interface. If so, the value of thelong getLastModified(request)
method of theLastModified
interface is returned to the client.You can customize individual
DispatcherServlet
instances by adding Servlet initialization parameters (init-param
elements) to the Servlet declaration in theweb.xml
file. See the following table for the list of supported parameters.
Parameter Explanation contextClass
Class that implements WebApplicationContext
, which instantiates the context used by this Servlet. By default, theXmlWebApplicationContext
is used.contextConfigLocation
String that is passed to the context instance (specified by contextClass
) to indicate where context(s) can be found. The string consists potentially of multiple strings (using a comma as a delimiter) to support multiple contexts. In case of multiple context locations with beans that are defined twice, the latest location takes precedence.namespace
Namespace of the WebApplicationContext
. Defaults to[servlet-name]-servlet
.Controllers provide access to the application behavior that you typically define through a service interface. Controllers interpret user input and transform it into a model that is represented to the user by the view. Spring implements a controller in a very abstract way, which enables you to create a wide variety of controllers.
Spring 2.5 introduced an annotation-based programming model for MVC controllers that uses annotations such as
@RequestMapping
,@RequestParam
,@ModelAttribute
, and so on. This annotation support is available for both Servlet MVC and Portlet MVC. Controllers implemented in this style do not have to extend specific base classes or implement specific interfaces. Furthermore, they do not usually have direct dependencies on Servlet or Portlet APIs, although you can easily configure access to Servlet or Portlet facilities.Available in the samples repository, a number of web applications leverage the annotation support described in this section including MvcShowcase, MvcAjax, MvcBasic, PetClinic, PetCare, and others.
@RequestMapping("/helloWorld") public String helloWorld(Model model) { model.addAttribute("message", "Hello World!"); return "helloWorld";As you can see, the
@Controller
and@RequestMapping
annotations allow flexible method names and signatures. In this particular example the method accepts aModel
and returns a view name as aString
, but various other method parameters and return values can be used as explained later in this section.@Controller
and@RequestMapping
and a number of other annotations form the basis for the Spring MVC implementation. This section documents these annotations and how they are most commonly used in a Servlet environment.The
@Controller
annotation indicates that a particular class serves the role of a controller. Spring does not require you to extend any controller base class or reference the Servlet API. However, you can still reference Servlet-specific features if you need to.The
@Controller
annotation acts as a stereotype for the annotated class, indicating its role. The dispatcher scans such annotated classes for mapped methods and detects@RequestMapping
annotations (see the next section).You can define annotated controller beans explicitly, using a standard Spring bean definition in the dispatcher's context. However, the
@Controller
stereotype also allows for autodetection, aligned with Spring general support for detecting component classes in the classpath and auto-registering bean definitions for them.To enable autodetection of such annotated controllers, you add component scanning to your configuration. Use the spring-context schema as shown in the following XML snippet:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.springframework.samples.petclinic.web"/> <!-- ... --> </beans>You use the
@RequestMapping
annotation to map URLs such as/appointments
onto an entire class or a particular handler method. Typically the class-level annotation maps a specific request path (or path pattern) onto a form controller, with additional method-level annotations narrowing the primary mapping for a specific HTTP method request method ("GET", "POST", etc.) or an HTTP request parameter condition.The following example from the Petcare sample shows a controller in a Spring MVC application that uses this annotation:
@Controller @RequestMapping("/appointments") public class AppointmentsController { private final AppointmentBook appointmentBook; @Autowired public AppointmentsController(AppointmentBook appointmentBook) { this.appointmentBook = appointmentBook; @RequestMapping(method = RequestMethod.GET) public Map<String, Appointment> get() { return appointmentBook.getAppointmentsForToday(); @RequestMapping(value="/{day}", method = RequestMethod.GET) public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) { return appointmentBook.getAppointmentsForDay(day); @RequestMapping(value="/new", method = RequestMethod.GET) public AppointmentForm getNewForm() { return new AppointmentForm(); @RequestMapping(method = RequestMethod.POST) public String add(@Valid AppointmentForm appointment, BindingResult result) { if (result.hasErrors()) { return "appointments/new"; appointmentBook.addAppointment(appointment); return "redirect:/appointments";In the example, the
@RequestMapping
is used in a number of places. The first usage is on the type (class) level, which indicates that all handling methods on this controller are relative to the/appointments
path. Theget()
method has a further@RequestMapping
refinement: it only accepts GET requests, meaning that an HTTP GET for/appointments
invokes this method. Thepost()
has a similar refinement, and thegetNewForm()
combines the definition of HTTP method and path into one, so that GET requests forappointments/new
are handled by that method.The
getForDay()
method shows another usage of@RequestMapping
: URI templates. (See the next section ).A
@RequestMapping
on the class level is not required. Without it, all paths are simply absolute, and not relative. The following example from the PetClinic sample application shows a multi-action controller using@RequestMapping
:@Controller public class ClinicController { private final Clinic clinic; @Autowired public ClinicController(Clinic clinic) { this.clinic = clinic; @RequestMapping("/") public void welcomeHandler() { @RequestMapping("/vets") public ModelMap vetsHandler() { return new ModelMap(this.clinic.getVets());
豁达的可乐 · 商务部等5部门关于进一步做好二手车出口工作的通知 7 月前 |
爽快的绿豆 · 7-摊牌 - 谁是那个他 - 包子漫画 1 年前 |
欢乐的莲藕 · 8家出售不记名手机空号、死号网站被关停-新华网 1 年前 |