HandlerExecutionChain and Interceptors


In the previous section you learned about the different handler mappings Spring provides. Handler mappings determine the path of execution for a request a user has issued, for example based on the request URL. When an appropriate mapping is found, the handler mapping returns a so-called HandlerExecutionChain, which instructs the dispatcher servlet on how to progress.

Important 

The HandlerExecutionChain consists of interceptors and exactly one handler (or controller), together providing all you need when it comes to accessing your business logic and other supporting services such as authentication, logging, and filtering.

A HandlerExecutionChain always contains a handler taking care of the request (in other words, executing the actual logic). A handler can be of any type. There are no specific requirements to a handler, as long as it is capable of handling a request and there's an appropriate HandlerAdapter that knows how to use the handler in the HandlerExecutionChain. By default, Spring uses two HandlerAdapters, one for invoking handlers deriving from the Controller interface and one for invoking handlers of type ThrowAwayController. The different types of controllers are covered later in this chapter.

A HandlerExecutionChain might also contain one or more HandlerInterceptors, which are capable of intercepting incoming requests. Interception is especially suited for actions such as logging, security, and auditing. A more in-depth discussion about the concept itself can be found in Chapter 4.

We've already discussed the workflow involved with an incoming request. Let's review the interceptors:

  1. Call to preHandle(HttpServletRequest, HttpServletResponse, Object) on any HandlerInterceptor available in the chain of execution. The Object in this case is the handler from the chain. This call allows to you execute any logic before the actual handler is allowed to do its job. Here you can check whether or not a user is allowed to issue this request, for example (this could be done using a UserRoleAuthorizationInterceptor explained a bit further on). Based on the return value of the call, Spring will decide to proceed with handling the request. When returning false, the dispatcher assumes the interceptor has handled the request itself (for example, when security constraints should prevent a user from issuing the request). In such a case Spring will immediately stop handling the request, which means the remaining interceptors, on which preHandle() hasn't been called, won't be consulted, just as the handler itself won't be consulted. Any interceptor, however, that did successfully return true before this moment will receive an afterCompletion() call.

  2. Retrieve the handler from the HandlerExecutionChain and start looking for a HandlerAdapter. All available HandlerAdapters (registered in the WebApplicationContext or provided by default) will be inspected to see if one of them supports such a handler (usually determined, based on the class of the handler). In all except some complex and maybe rare situations there is no need to worry about the HandlerAdapter, its implementations, and the way they work. Spring's default behavior works just fine.

  3. The next step is the actual execution of the handler. This will execute your actual business logic, or better; after some initial preparation such as data-binding, delegate the request to the middle tier. After the execution of the request has completed, you should prepare a ModelAndView, containing data that a JSP or, for example, a Velocity template needs to render an HTML page or a PDF document.

  4. Next, all interceptors will be called again, using the postHandle(HttpServletRequest, HttpServletResponse, Object, ModelAndView) method. Here you can modify the ModelAndView (maybe add extra attributes to it or maybe even remove things). This is your last chance to execute logic before the view gets rendered.

  5. Next, the view will be resolved and rendered. We will cover view resolving and rendering later in this chapter.

  6. The last step involves calling afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception) on any interceptor available. The object is the handler that took care of the logic involved with this request. If an exception has occurred during the completion of the request, it will be passed in there as well.

WebContentInterceptor

Spring provides some HandlerInterceptors implementing functionality often needed in web applications. One of those is the WebContentInterceptor, providing functionality for easy modification of caching behavior of a web application and useful generic tasks such as limiting the methods (GET, POST, PUT) that are supported by the webapplication. Configuring this interceptor would be done as follows(note that the UserRoleAuthorizationInterceptor will be explained later):

<bean >   <property name="interceptors">     <list>       <ref local="contentInterceptor"/>       <ref local="userRoleAuthorizationInterceptor"/>     </list>   </property> </bean>     <bean      >   <property name="cacheSeconds"><value>30</value></property>   <property name="supportedMethods"><value>GET</value></property> </bean>

The following table shows the properties that are available for the content interceptor.

Property

Description

Default Value

cacheSeconds

The amount of seconds that is specified for content caching headers, if those headers are generated.

-1, which results in no caching headers being generated

supportedMethods

The HTTP methods associated with client requests that the interceptor will permit. If the request method is not allowed, a ServletException will be thrown.

GET and POST

requireSession

A ServletException will be thrown if a request without an associated session is found.

false

useCacheControlHeader

Indicates whether or not to use the HTTP 1.1 Cache-Control directive while generating content caching headers.

true

useExpiresHeader

Indicates whether or not to use the HTTP 1.0 Expires directive while generating content caching headers.

true

UserRoleAuthorizationInterceptor

Spring also features a simple authorization interceptor that checks a user's Principal with a set of roles you specify. Adding the interceptor to your handler mapping is done in the same way as when using the content interceptor. The UserRoleAuthorizationInterceptor features a property called authorizedRoles, which is an array of Strings. The interceptor directly delegates to HttpServletRequest.isUserInRole(String). When the user issuing the request is not in a role mentioned with the configuration of the interceptor, an HttpServletResponse.SC_FORBIDDEN is sent to the client, corresponding to status code 403. Using, for example, the error mappings in the web.xml descriptor, you can direct the user to an appropriate error page. You could also subclass the interceptor and override the handlerNotAuthorized(...) method to perform custom actions.

<bean      >   <property name="authorizedRoles">     <list>       <value>administrator</value>       <value>editor</value>     </list>   </property> </bean>

Important 

The UsersRoleAuthorizationInterceptor can be used in combination with the JAAS features of an application server. Generally, the UserRoleAuthorizationInterceptor suffices in simple situations only: It does not aim to be a powerful general security solution. For more complete security solutions, including advanced features such as single-sign-on, we recommend Acegi Security System for Spring, discussed in Chapter 10.

Other Handler Interceptors Provided by Spring MVC

Other handler interceptors provided by Spring MVC concern persistence and internationalization:

  • OpenSessionInViewInterceptor and OpenPersistenceManagerInViewInterceptor: For use with Hibernate and JDO, respectively. Refer to Chapter 7 for a more in-depth discussion about those.

  • LocaleChangeInterceptor: Use this to change the locale a web application uses on the fly. This specific interceptor will be covered later in the chapter.



Professional Java Development with the Spring Framework
Professional Java Development with the Spring Framework
ISBN: 0764574833
EAN: 2147483647
Year: 2003
Pages: 188

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net