001/* 002 * Copyright 2002-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.portlet; 018 019import javax.portlet.ActionRequest; 020import javax.portlet.ActionResponse; 021import javax.portlet.EventRequest; 022import javax.portlet.EventResponse; 023import javax.portlet.RenderRequest; 024import javax.portlet.RenderResponse; 025import javax.portlet.ResourceRequest; 026import javax.portlet.ResourceResponse; 027 028/** 029 * Workflow interface that allows for customized handler execution chains. 030 * Applications can register any number of existing or custom interceptors 031 * for certain groups of handlers, to add common pre-processing behavior 032 * without needing to modify each handler implementation. 033 * 034 * <p>A {@code HandlerInterceptor} gets called before the appropriate 035 * {@link HandlerAdapter} triggers the 036 * execution of the handler itself. This mechanism can be used for a large 037 * field of preprocessing aspects, e.g. for authorization checks, 038 * or common handler behavior like locale or theme changes. Its main purpose 039 * is to permit the factoring out of otherwise repetitive handler code. 040 * 041 * <p>Typically an interceptor chain is defined per 042 * {@link HandlerMapping} bean, sharing its 043 * granularity. To be able to apply a certain interceptor chain to a group of 044 * handlers, one needs to map the desired handlers via one 045 * {@code HandlerMapping} bean. The interceptors themselves are defined as 046 * beans in the application context, referenced by the mapping bean definition 047 * via its 048 * {@link org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors "interceptors"} 049 * property (in XML: a <list> of <ref> elements). 050 * 051 * <p>A {@code HandlerInterceptor} is basically similar to a Servlet 052 * {@link javax.servlet.Filter}, but in contrast to the latter it allows 053 * custom pre-processing with the option to prohibit the execution of the handler 054 * itself, and custom post-processing. {@code Filters} are more powerful; 055 * for example they allow for exchanging the request and response objects that 056 * are handed down the chain. Note that a filter gets configured in 057 * {@code web.xml}, a {@code HandlerInterceptor} in the application context. 058 * 059 * <p>As a basic guideline, fine-grained handler-related pre-processing tasks are 060 * candidates for {@code HandlerInterceptor} implementations, especially 061 * factored-out common handler code and authorization checks. On the other hand, 062 * a {@code Filter} is well-suited for request content and view content 063 * handling, like multipart forms and GZIP compression. This typically shows when 064 * one needs to map the filter to certain content types (e.g. images), or to all 065 * requests. 066 * 067 * <p>Be aware that filters cannot be applied to portlet requests (they 068 * only operate on servlet requests), so for portlet requests interceptors are 069 * essential. 070 * 071 * <p>If we assume a "sunny day" request cycle (i.e. a request where nothing goes wrong 072 * and all is well), the workflow of a {@code HandlerInterceptor} will be as 073 * follows: 074 * 075 * <p><b>Action Request:</b><p> 076 * <ol> 077 * <li>{@code DispatcherPortlet} maps the action request to a particular handler and 078 * assembles a handler execution chain consisting of the handler that is to be invoked 079 * and all of the {@code HandlerInterceptor} instances that apply to the request.</li> 080 * <li>{@link HandlerInterceptor#preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) preHandleAction(..)} 081 * is called; if the invocation of this method returns {@code true} then this workflow continues.</li> 082 * <li>The target handler handles the action request (via 083 * {@link HandlerAdapter#handleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) HandlerAdapter.handleAction(..)}).</li> 084 * <li>{@link HandlerInterceptor#afterActionCompletion(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object, Exception) afterActionCompletion(..)} 085 * is called.</li> 086 * </ol> 087 * 088 * <p><b>Render Request:</b><p> 089 * <ol> 090 * <li>{@code DispatcherPortlet} maps the render request to a particular handler and 091 * assembles a handler execution chain consisting of the handler that is to be invoked 092 * and all of the {@code HandlerInterceptor} instances that apply to the request.</li> 093 * <li>{@link HandlerInterceptor#preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) preHandleRender(..)} 094 * is called; if the invocation of this method returns {@code true} then this workflow continues.</li> 095 * <li>The target handler handles the render request (via 096 * {@link HandlerAdapter#handleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) HandlerAdapter.handleRender(..)}).</li> 097 * <li>{@link HandlerInterceptor#postHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, ModelAndView) postHandleRender(..)} 098 * is called.</li> 099 * <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 */ 113public 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}