1 /* 2 * Copyright 2002-2014 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.web.portlet; 18 19 import javax.portlet.ActionRequest; 20 import javax.portlet.ActionResponse; 21 import javax.portlet.EventRequest; 22 import javax.portlet.EventResponse; 23 import javax.portlet.RenderRequest; 24 import javax.portlet.RenderResponse; 25 import javax.portlet.ResourceRequest; 26 import javax.portlet.ResourceResponse; 27 28 /** 29 * Workflow interface that allows for customized handler execution chains. 30 * Applications can register any number of existing or custom interceptors 31 * for certain groups of handlers, to add common pre-processing behavior 32 * without needing to modify each handler implementation. 33 * 34 * <p>A {@code HandlerInterceptor} gets called before the appropriate 35 * {@link HandlerAdapter} triggers the 36 * execution of the handler itself. This mechanism can be used for a large 37 * field of preprocessing aspects, e.g. for authorization checks, 38 * or common handler behavior like locale or theme changes. Its main purpose 39 * is to permit the factoring out of otherwise repetitive handler code. 40 * 41 * <p>Typically an interceptor chain is defined per 42 * {@link HandlerMapping} bean, sharing its 43 * granularity. To be able to apply a certain interceptor chain to a group of 44 * handlers, one needs to map the desired handlers via one 45 * {@code HandlerMapping} bean. The interceptors themselves are defined as 46 * beans in the application context, referenced by the mapping bean definition 47 * via its 48 * {@link org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors "interceptors"} 49 * property (in XML: a <list> of <ref> elements). 50 * 51 * <p>A {@code HandlerInterceptor} is basically similar to a Servlet 52 * {@link javax.servlet.Filter}, but in contrast to the latter it allows 53 * custom pre-processing with the option to prohibit the execution of the handler 54 * itself, and custom post-processing. {@code Filters} are more powerful; 55 * for example they allow for exchanging the request and response objects that 56 * are handed down the chain. Note that a filter gets configured in 57 * {@code web.xml}, a {@code HandlerInterceptor} in the application context. 58 * 59 * <p>As a basic guideline, fine-grained handler-related pre-processing tasks are 60 * candidates for {@code HandlerInterceptor} implementations, especially 61 * factored-out common handler code and authorization checks. On the other hand, 62 * a {@code Filter} is well-suited for request content and view content 63 * handling, like multipart forms and GZIP compression. This typically shows when 64 * one needs to map the filter to certain content types (e.g. images), or to all 65 * requests. 66 * 67 * <p>Be aware that filters cannot be applied to portlet requests (they 68 * only operate on servlet requests), so for portlet requests interceptors are 69 * essential. 70 * 71 * <p>If we assume a "sunny day" request cycle (i.e. a request where nothing goes wrong 72 * and all is well), the workflow of a {@code HandlerInterceptor} will be as 73 * follows: 74 * 75 * <p><b>Action Request:</b><p> 76 * <ol> 77 * <li>{@code DispatcherPortlet} maps the action request to a particular handler and 78 * assembles a handler execution chain consisting of the handler that is to be invoked 79 * and all of the {@code HandlerInterceptor} instances that apply to the request.</li> 80 * <li>{@link HandlerInterceptor#preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) preHandleAction(..)} 81 * is called; if the invocation of this method returns {@code true} then this workflow continues.</li> 82 * <li>The target handler handles the action request (via 83 * {@link HandlerAdapter#handleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) HandlerAdapter.handleAction(..)}).</li> 84 * <li>{@link HandlerInterceptor#afterActionCompletion(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object, Exception) afterActionCompletion(..)} 85 * is called.</li> 86 * </ol> 87 * 88 * <p><b>Render Request:</b><p> 89 * <ol> 90 * <li>{@code DispatcherPortlet} maps the render request to a particular handler and 91 * assembles a handler execution chain consisting of the handler that is to be invoked 92 * and all of the {@code HandlerInterceptor} instances that apply to the request.</li> 93 * <li>{@link HandlerInterceptor#preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) preHandleRender(..)} 94 * is called; if the invocation of this method returns {@code true} then this workflow continues.</li> 95 * <li>The target handler handles the render request (via 96 * {@link HandlerAdapter#handleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) HandlerAdapter.handleRender(..)}).</li> 97 * <li>{@link HandlerInterceptor#postHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, ModelAndView) postHandleRender(..)} 98 * is called.</li> 99 * <li>If the {@code HandlerAdapter} returned a {@code ModelAndView}, then 100 * {@code DispatcherPortlet} renders the view accordingly. 101 * <li>{@link HandlerInterceptor#afterRenderCompletion(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, Exception) afterRenderCompletion(..)} 102 * is called.</li> 103 * </ol> 104 * 105 * @author Juergen Hoeller 106 * @author John A. Lewis 107 * @since 2.0 108 * @see HandlerExecutionChain#getInterceptors 109 * @see HandlerMapping 110 * @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors 111 * @see HandlerExecutionChain 112 */ 113 public interface HandlerInterceptor { 114 115 /** 116 * Intercept the execution of a handler in the action phase. 117 * <p>Called after a HandlerMapping determines an appropriate handler object 118 * to handle an {@link ActionRequest}, but before said HandlerAdapter actually 119 * invokes the handler. 120 * <p>{@link DispatcherPortlet} processes a handler in an execution chain, 121 * consisting of any number of interceptors, with the handler itself at the end. 122 * With this method, each interceptor can decide to abort the execution chain, 123 * typically throwing an exception or writing a custom response. 124 * @param request current portlet action request 125 * @param response current portlet action response 126 * @param handler chosen handler to execute, for type and/or instance evaluation 127 * @return {@code true} if the execution chain should proceed with the 128 * next interceptor or the handler itself. Else, {@code DispatcherPortlet} 129 * assumes that this interceptor has already dealt with the response itself 130 * @throws Exception in case of errors 131 */ 132 boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) 133 throws Exception; 134 135 /** 136 * Callback after completion of request processing in the action phase, that is, 137 * after rendering the view. Will be called on any outcome of handler execution, 138 * thus allowing for proper resource cleanup. 139 * <p>Note: Will only be called if this interceptor's 140 * {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)} 141 * method has successfully completed and returned {@code true}! 142 * @param request current portlet action request 143 * @param response current portlet action response 144 * @param handler chosen handler to execute, for type and/or instance examination 145 * @param ex exception thrown on handler execution, if any (only included as 146 * additional context information for the case where a handler threw an exception; 147 * request execution may have failed even when this argument is {@code null}) 148 * @throws Exception in case of errors 149 */ 150 void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex) 151 throws Exception; 152 153 /** 154 * Intercept the execution of a handler in the render phase. 155 * <p>Called after a HandlerMapping determines an appropriate handler object 156 * to handle a {@link RenderRequest}, but before said HandlerAdapter actually 157 * invokes the handler. 158 * <p>{@link DispatcherPortlet} processes a handler in an execution chain, 159 * consisting of any number of interceptors, with the handler itself at the end. 160 * With this method, each interceptor can decide to abort the execution chain, 161 * typically throwing an exception or writing a custom response. 162 * @param request current portlet render request 163 * @param response current portlet render response 164 * @param handler chosen handler to execute, for type and/or instance evaluation 165 * @return {@code true} if the execution chain should proceed with the 166 * next interceptor or the handler itself. Else, {@code DispatcherPortlet} 167 * assumes that this interceptor has already dealt with the response itself 168 * @throws Exception in case of errors 169 */ 170 boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler) 171 throws Exception; 172 173 /** 174 * Intercept the execution of a handler in the render phase. 175 * <p>Called after a {@link HandlerAdapter} actually invoked the handler, but 176 * before the {@code DispatcherPortlet} renders the view. Can thus expose 177 * additional model objects to the view via the given {@link ModelAndView}. 178 * <p>{@code DispatcherPortlet} processes a handler in an execution chain, 179 * consisting of any number of interceptors, with the handler itself at the end. 180 * With this method, each interceptor can post-process an execution, getting 181 * applied in inverse order of the execution chain. 182 * @param request current portlet render request 183 * @param response current portlet render response 184 * @param handler chosen handler to execute, for type and/or instance examination 185 * @param modelAndView the {@code ModelAndView} that the handler returned 186 * (can also be {@code null}) 187 * @throws Exception in case of errors 188 */ 189 void postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView) 190 throws Exception; 191 192 /** 193 * Callback after completion of request processing, that is, after rendering 194 * the view. Will be called on any outcome of handler execution, thus allowing 195 * for proper resource cleanup. 196 * <p>Note: Will only be called if this interceptor's 197 * {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)} 198 * method has successfully completed and returned {@code true}! 199 * @param request current portlet render request 200 * @param response current portlet render response 201 * @param handler chosen handler to execute, for type and/or instance examination 202 * @param ex exception thrown on handler execution, if any 203 * @throws Exception in case of errors 204 */ 205 void afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex) 206 throws Exception; 207 208 /** 209 * Intercept the execution of a handler in the render phase. 210 * <p>Called after a HandlerMapping determines an appropriate handler object 211 * to handle a {@link RenderRequest}, but before said HandlerAdapter actually 212 * invokes the handler. 213 * <p>{@link DispatcherPortlet} processes a handler in an execution chain, 214 * consisting of any number of interceptors, with the handler itself at the end. 215 * With this method, each interceptor can decide to abort the execution chain, 216 * typically throwing an exception or writing a custom response. 217 * @param request current portlet render request 218 * @param response current portlet render response 219 * @param handler chosen handler to execute, for type and/or instance evaluation 220 * @return {@code true} if the execution chain should proceed with the 221 * next interceptor or the handler itself. Else, {@code DispatcherPortlet} 222 * assumes that this interceptor has already dealt with the response itself 223 * @throws Exception in case of errors 224 */ 225 boolean preHandleResource(ResourceRequest request, ResourceResponse response, Object handler) 226 throws Exception; 227 228 /** 229 * Intercept the execution of a handler in the render phase. 230 * <p>Called after a {@link HandlerAdapter} actually invoked the handler, but 231 * before the {@code DispatcherPortlet} renders the view. Can thus expose 232 * additional model objects to the view via the given {@link ModelAndView}. 233 * <p>{@code DispatcherPortlet} processes a handler in an execution chain, 234 * consisting of any number of interceptors, with the handler itself at the end. 235 * With this method, each interceptor can post-process an execution, getting 236 * applied in inverse order of the execution chain. 237 * @param request current portlet render request 238 * @param response current portlet render response 239 * @param handler chosen handler to execute, for type and/or instance examination 240 * @param modelAndView the {@code ModelAndView} that the handler returned 241 * (can also be {@code null}) 242 * @throws Exception in case of errors 243 */ 244 void postHandleResource(ResourceRequest request, ResourceResponse response, Object handler, ModelAndView modelAndView) 245 throws Exception; 246 247 /** 248 * Callback after completion of request processing, that is, after rendering 249 * the view. Will be called on any outcome of handler execution, thus allowing 250 * for proper resource cleanup. 251 * <p>Note: Will only be called if this interceptor's 252 * {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)} 253 * method has successfully completed and returned {@code true}! 254 * @param request current portlet render request 255 * @param response current portlet render response 256 * @param handler chosen handler to execute, for type and/or instance examination 257 * @param ex exception thrown on handler execution, if any 258 * @throws Exception in case of errors 259 */ 260 void afterResourceCompletion(ResourceRequest request, ResourceResponse response, Object handler, Exception ex) 261 throws Exception; 262 263 /** 264 * Intercept the execution of a handler in the action phase. 265 * <p>Called after a HandlerMapping determines an appropriate handler object 266 * to handle an {@link ActionRequest}, but before said HandlerAdapter actually 267 * invokes the handler. 268 * <p>{@link DispatcherPortlet} processes a handler in an execution chain, 269 * consisting of any number of interceptors, with the handler itself at the end. 270 * With this method, each interceptor can decide to abort the execution chain, 271 * typically throwing an exception or writing a custom response. 272 * @param request current portlet action request 273 * @param response current portlet action response 274 * @param handler chosen handler to execute, for type and/or instance evaluation 275 * @return {@code true} if the execution chain should proceed with the 276 * next interceptor or the handler itself. Else, {@code DispatcherPortlet} 277 * assumes that this interceptor has already dealt with the response itself 278 * @throws Exception in case of errors 279 */ 280 boolean preHandleEvent(EventRequest request, EventResponse response, Object handler) 281 throws Exception; 282 283 /** 284 * Callback after completion of request processing in the action phase, that is, 285 * after rendering the view. Will be called on any outcome of handler execution, 286 * thus allowing for proper resource cleanup. 287 * <p>Note: Will only be called if this interceptor's 288 * {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)} 289 * method has successfully completed and returned {@code true}! 290 * @param request current portlet action request 291 * @param response current portlet action response 292 * @param handler chosen handler to execute, for type and/or instance examination 293 * @param ex exception thrown on handler execution, if any (only included as 294 * additional context information for the case where a handler threw an exception; 295 * request execution may have failed even when this argument is {@code null}) 296 * @throws Exception in case of errors 297 */ 298 void afterEventCompletion(EventRequest request, EventResponse response, Object handler, Exception ex) 299 throws Exception; 300 301 }