Save This Page
Home » spring-framework-2.5.6-with-dependencies » org.springframework » web » servlet » [javadoc | source]
    1   /*
    2    * Copyright 2002-2008 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.servlet;
   18   
   19   import java.io.IOException;
   20   import java.security.Principal;
   21   
   22   import javax.servlet.ServletException;
   23   import javax.servlet.http.HttpServletRequest;
   24   import javax.servlet.http.HttpServletResponse;
   25   
   26   import org.springframework.beans.BeanUtils;
   27   import org.springframework.beans.BeansException;
   28   import org.springframework.context.ApplicationContext;
   29   import org.springframework.context.ApplicationContextException;
   30   import org.springframework.context.ApplicationEvent;
   31   import org.springframework.context.ApplicationListener;
   32   import org.springframework.context.ConfigurableApplicationContext;
   33   import org.springframework.context.event.ContextRefreshedEvent;
   34   import org.springframework.context.event.SourceFilteringListener;
   35   import org.springframework.web.context.ConfigurableWebApplicationContext;
   36   import org.springframework.web.context.WebApplicationContext;
   37   import org.springframework.web.context.support.ServletRequestHandledEvent;
   38   import org.springframework.web.context.support.WebApplicationContextUtils;
   39   import org.springframework.web.context.support.XmlWebApplicationContext;
   40   import org.springframework.web.util.NestedServletException;
   41   import org.springframework.web.util.WebUtils;
   42   
   43   /**
   44    * Base servlet for Spring's web framework. Provides integration with
   45    * a Spring application context, in a JavaBean-based overall solution.
   46    *
   47    * <p>This class offers the following functionality:
   48    * <ul>
   49    * <li>Manages a {@link org.springframework.web.context.WebApplicationContext}
   50    * instance per servlet. The servlet's configuration is determined by beans
   51    * in the servlet's namespace.
   52    * <li>Publishes events on request processing, whether or not a request is
   53    * successfully handled.
   54    * </ul>
   55    *
   56    * <p>Subclasses must implement {@link #doService} to handle requests. Because this extends
   57    * {@link HttpServletBean} rather than HttpServlet directly, bean properties are
   58    * automatically mapped onto it. Subclasses can override {@link #initFrameworkServlet()}
   59    * for custom initialization.
   60    *
   61    * <p>Detects a "contextClass" parameter at the servlet init-param level,
   62    * falling back to the default context class,
   63    * {@link org.springframework.web.context.support.XmlWebApplicationContext},
   64    * if not found. Note that, with the default FrameworkServlet,
   65    * a custom context class needs to implement the
   66    * {@link org.springframework.web.context.ConfigurableWebApplicationContext} SPI.
   67    *
   68    * <p>Passes a "contextConfigLocation" servlet init-param to the context instance,
   69    * parsing it into potentially multiple file paths which can be separated by any
   70    * number of commas and spaces, like "test-servlet.xml, myServlet.xml".
   71    * If not explicitly specified, the context implementation is supposed to build a
   72    * default location from the namespace of the servlet.
   73    *
   74    * <p>Note: In case of multiple config locations, later bean definitions will
   75    * override ones defined in earlier loaded files, at least when using Spring's
   76    * default ApplicationContext implementation. This can be leveraged to
   77    * deliberately override certain bean definitions via an extra XML file.
   78    *
   79    * <p>The default namespace is "'servlet-name'-servlet", e.g. "test-servlet" for a
   80    * servlet-name "test" (leading to a "/WEB-INF/test-servlet.xml" default location
   81    * with XmlWebApplicationContext). The namespace can also be set explicitly via
   82    * the "namespace" servlet init-param.
   83    *
   84    * @author Rod Johnson
   85    * @author Juergen Hoeller
   86    * @author Sam Brannen
   87    * @see #doService
   88    * @see #setContextClass
   89    * @see #setContextConfigLocation
   90    * @see #setNamespace
   91    */
   92   public abstract class FrameworkServlet extends HttpServletBean implements ApplicationListener {
   93   
   94   	/**
   95   	 * Suffix for WebApplicationContext namespaces. If a servlet of this class is
   96   	 * given the name "test" in a context, the namespace used by the servlet will
   97   	 * resolve to "test-servlet".
   98   	 */
   99   	public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
  100   
  101   	/**
  102   	 * Default context class for FrameworkServlet.
  103   	 * @see org.springframework.web.context.support.XmlWebApplicationContext
  104   	 */
  105   	public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
  106   
  107   	/**
  108   	 * Prefix for the ServletContext attribute for the WebApplicationContext.
  109   	 * The completion is the servlet name.
  110   	 */
  111   	public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";
  112   
  113   
  114   	/** ServletContext attribute to find the WebApplicationContext in */
  115   	private String contextAttribute;
  116   
  117   	/** WebApplicationContext implementation class to create */
  118   	private Class contextClass = DEFAULT_CONTEXT_CLASS;
  119   
  120   	/** Namespace for this servlet */
  121   	private String namespace;
  122   
  123   	/** Explicit context config location */
  124   	private String contextConfigLocation;
  125   
  126   	/** Should we publish the context as a ServletContext attribute? */
  127   	private boolean publishContext = true;
  128   
  129   	/** Should we publish a ServletRequestHandledEvent at the end of each request? */
  130   	private boolean publishEvents = true;
  131   
  132   	/** Should we dispatch an HTTP OPTIONS request to {@link #doService}? */
  133   	private boolean dispatchOptionsRequest = false;
  134   
  135   	/** Should we dispatch an HTTP TRACE request to {@link #doService}? */
  136   	private boolean dispatchTraceRequest = false;
  137   
  138   	/** WebApplicationContext for this servlet */
  139   	private WebApplicationContext webApplicationContext;
  140   
  141   	/** Flag used to detect whether onRefresh has already been called */
  142   	private boolean refreshEventReceived = false;
  143   
  144   
  145   	/**
  146   	 * Set the name of the ServletContext attribute which should be used to retrieve the
  147   	 * {@link WebApplicationContext} that this servlet is supposed to use.
  148   	 */
  149   	public void setContextAttribute(String contextAttribute) {
  150   		this.contextAttribute = contextAttribute;
  151   	}
  152   
  153   	/**
  154   	 * Return the name of the ServletContext attribute which should be used to retrieve the
  155   	 * {@link WebApplicationContext} that this servlet is supposed to use.
  156   	 */
  157   	public String getContextAttribute() {
  158   		return this.contextAttribute;
  159   	}
  160   
  161   	/**
  162   	 * Set a custom context class. This class must be of type
  163   	 * {@link org.springframework.web.context.WebApplicationContext}.
  164   	 * <p>When using the default FrameworkServlet implementation,
  165   	 * the context class must also implement the
  166   	 * {@link org.springframework.web.context.ConfigurableWebApplicationContext}
  167   	 * interface.
  168   	 * @see #createWebApplicationContext
  169   	 */
  170   	public void setContextClass(Class contextClass) {
  171   		this.contextClass = contextClass;
  172   	}
  173   
  174   	/**
  175   	 * Return the custom context class.
  176   	 */
  177   	public Class getContextClass() {
  178   		return this.contextClass;
  179   	}
  180   
  181   	/**
  182   	 * Set a custom namespace for this servlet,
  183   	 * to be used for building a default context config location.
  184   	 */
  185   	public void setNamespace(String namespace) {
  186   		this.namespace = namespace;
  187   	}
  188   
  189   	/**
  190   	 * Return the namespace for this servlet, falling back to default scheme if
  191   	 * no custom namespace was set: e.g. "test-servlet" for a servlet named "test".
  192   	 */
  193   	public String getNamespace() {
  194   		return (this.namespace != null ? this.namespace : getServletName() + DEFAULT_NAMESPACE_SUFFIX);
  195   	}
  196   
  197   	/**
  198   	 * Set the context config location explicitly, instead of relying on the default
  199   	 * location built from the namespace. This location string can consist of
  200   	 * multiple locations separated by any number of commas and spaces.
  201   	 */
  202   	public void setContextConfigLocation(String contextConfigLocation) {
  203   		this.contextConfigLocation = contextConfigLocation;
  204   	}
  205   
  206   	/**
  207   	 * Return the explicit context config location, if any.
  208   	 */
  209   	public String getContextConfigLocation() {
  210   		return this.contextConfigLocation;
  211   	}
  212   
  213   	/**
  214   	 * Set whether to publish this servlet's context as a ServletContext attribute,
  215   	 * available to all objects in the web container. Default is "true".
  216   	 * <p>This is especially handy during testing, although it is debatable whether
  217   	 * it's good practice to let other application objects access the context this way.
  218   	 */
  219   	public void setPublishContext(boolean publishContext) {
  220   		this.publishContext = publishContext;
  221   	}
  222   
  223   	/**
  224   	 * Set whether this servlet should publish a ServletRequestHandledEvent at the end
  225   	 * of each request. Default is "true"; can be turned off for a slight performance
  226   	 * improvement, provided that no ApplicationListeners rely on such events.
  227   	 * @see org.springframework.web.context.support.ServletRequestHandledEvent
  228   	 */
  229   	public void setPublishEvents(boolean publishEvents) {
  230   		this.publishEvents = publishEvents;
  231   	}
  232   
  233   	/**
  234   	 * Set whether this servlet should dispatch an HTTP OPTIONS request to
  235   	 * the {@link #doService} method.
  236   	 * <p>Default is "false", applying {@link javax.servlet.http.HttpServlet}'s
  237   	 * default behavior (i.e. enumerating all standard HTTP request methods
  238   	 * as a response to the OPTIONS request).
  239   	 * <p>Turn this flag on if you prefer OPTIONS requests to go through the
  240   	 * regular dispatching chain, just like other HTTP requests. This usually
  241   	 * means that your controllers will receive those requests; make sure
  242   	 * that those endpoints are actually able to handle an OPTIONS request.
  243   	 * <p>Note that HttpServlet's default OPTIONS processing will be applied
  244   	 * in any case. Your controllers are simply available to override the
  245   	 * default headers and optionally generate a response body.
  246   	 */
  247   	public void setDispatchOptionsRequest(boolean dispatchOptionsRequest) {
  248   		this.dispatchOptionsRequest = dispatchOptionsRequest;
  249   	}
  250   
  251   	/**
  252   	 * Set whether this servlet should dispatch an HTTP TRACE request to
  253   	 * the {@link #doService} method.
  254   	 * <p>Default is "false", applying {@link javax.servlet.http.HttpServlet}'s
  255   	 * default behavior (i.e. reflecting the message received back to the client).
  256   	 * <p>Turn this flag on if you prefer TRACE requests to go through the
  257   	 * regular dispatching chain, just like other HTTP requests. This usually
  258   	 * means that your controllers will receive those requests; make sure
  259   	 * that those endpoints are actually able to handle a TRACE request.
  260   	 * <p>Note that HttpServlet's default TRACE processing will be applied
  261   	 * in any case. Your controllers are simply available to override the
  262   	 * default headers and the default body, calling <code>response.reset()</code>
  263   	 * if necessary.
  264   	 */
  265   	public void setDispatchTraceRequest(boolean dispatchTraceRequest) {
  266   		this.dispatchTraceRequest = dispatchTraceRequest;
  267   	}
  268   
  269   
  270   	/**
  271   	 * Overridden method of {@link HttpServletBean}, invoked after any bean properties
  272   	 * have been set. Creates this servlet's WebApplicationContext.
  273   	 */
  274   	protected final void initServletBean() throws ServletException, BeansException {
  275   		getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
  276   		if (this.logger.isInfoEnabled()) {
  277   			this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
  278   		}
  279   		long startTime = System.currentTimeMillis();
  280   
  281   		try {
  282   			this.webApplicationContext = initWebApplicationContext();
  283   			initFrameworkServlet();
  284   		}
  285   		catch (ServletException ex) {
  286   			this.logger.error("Context initialization failed", ex);
  287   			throw ex;
  288   		}
  289   		catch (BeansException ex) {
  290   			this.logger.error("Context initialization failed", ex);
  291   			throw ex;
  292   		}
  293   
  294   		if (this.logger.isInfoEnabled()) {
  295   			long elapsedTime = System.currentTimeMillis() - startTime;
  296   			this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
  297   					elapsedTime + " ms");
  298   		}
  299   	}
  300   
  301   	/**
  302   	 * Initialize and publish the WebApplicationContext for this servlet.
  303   	 * <p>Delegates to {@link #createWebApplicationContext} for actual creation
  304   	 * of the context. Can be overridden in subclasses.
  305   	 * @return the WebApplicationContext instance
  306   	 * @throws BeansException if the context couldn't be initialized
  307   	 * @see #setContextClass
  308   	 * @see #setContextConfigLocation
  309   	 */
  310   	protected WebApplicationContext initWebApplicationContext() throws BeansException {
  311   		WebApplicationContext wac = findWebApplicationContext();
  312   		if (wac == null) {
  313   			// No fixed context defined for this servlet - create a local one.
  314   			WebApplicationContext parent =
  315   					WebApplicationContextUtils.getWebApplicationContext(getServletContext());
  316   			wac = createWebApplicationContext(parent);
  317   		}
  318   
  319   		if (!this.refreshEventReceived) {
  320   			// Apparently not a ConfigurableApplicationContext with refresh support:
  321   			// triggering initial onRefresh manually here.
  322   			onRefresh(wac);
  323   		}
  324   
  325   		if (this.publishContext) {
  326   			// Publish the context as a servlet context attribute.
  327   			String attrName = getServletContextAttributeName();
  328   			getServletContext().setAttribute(attrName, wac);
  329   			if (this.logger.isDebugEnabled()) {
  330   				this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
  331   						"' as ServletContext attribute with name [" + attrName + "]");
  332   			}
  333   		}
  334   
  335   		return wac;
  336   	}
  337   
  338   	/**
  339   	 * Retrieve a <code>WebApplicationContext</code> from the <code>ServletContext</code>
  340   	 * attribute with the {@link #setContextAttribute configured name}. The
  341   	 * <code>WebApplicationContext</code> must have already been loaded and stored in the
  342   	 * <code>ServletContext</code> before this servlet gets initialized (or invoked).
  343   	 * <p>Subclasses may override this method to provide a different
  344   	 * <code>WebApplicationContext</code> retrieval strategy.
  345   	 * @return the WebApplicationContext for this servlet, or <code>null</code> if not found
  346   	 * @see #getContextAttribute()
  347   	 */
  348   	protected WebApplicationContext findWebApplicationContext() {
  349   		String attrName = getContextAttribute();
  350   		if (attrName == null) {
  351   			return null;
  352   		}
  353   		WebApplicationContext wac =
  354   				WebApplicationContextUtils.getWebApplicationContext(getServletContext(), attrName);
  355   		if (wac == null) {
  356   			throw new IllegalStateException("No WebApplicationContext found: initializer not registered?");
  357   		}
  358   		return wac;
  359   	}
  360   
  361   	/**
  362   	 * Instantiate the WebApplicationContext for this servlet, either a default
  363   	 * {@link org.springframework.web.context.support.XmlWebApplicationContext}
  364   	 * or a {@link #setContextClass custom context class}, if set.
  365   	 * <p>This implementation expects custom contexts to implement the
  366   	 * {@link org.springframework.web.context.ConfigurableWebApplicationContext}
  367   	 * interface. Can be overridden in subclasses.
  368   	 * <p>Do not forget to register this servlet instance as application listener on the
  369   	 * created context (for triggering its {@link #onRefresh callback}, and to call
  370   	 * {@link org.springframework.context.ConfigurableApplicationContext#refresh()}
  371   	 * before returning the context instance.
  372   	 * @param parent the parent ApplicationContext to use, or <code>null</code> if none
  373   	 * @return the WebApplicationContext for this servlet
  374   	 * @throws BeansException if the context couldn't be initialized
  375   	 * @see org.springframework.web.context.support.XmlWebApplicationContext
  376   	 */
  377   	protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
  378   			throws BeansException {
  379   
  380   		if (this.logger.isDebugEnabled()) {
  381   			this.logger.debug("Servlet with name '" + getServletName() +
  382   					"' will try to create custom WebApplicationContext context of class '" +
  383   					getContextClass().getName() + "'" + ", using parent context [" + parent + "]");
  384   		}
  385   		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(getContextClass())) {
  386   			throw new ApplicationContextException(
  387   					"Fatal initialization error in servlet with name '" + getServletName() +
  388   					"': custom WebApplicationContext class [" + getContextClass().getName() +
  389   					"] is not of type ConfigurableWebApplicationContext");
  390   		}
  391   
  392   		ConfigurableWebApplicationContext wac =
  393   				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(getContextClass());
  394   		wac.setParent(parent);
  395   		wac.setServletContext(getServletContext());
  396   		wac.setServletConfig(getServletConfig());
  397   		wac.setNamespace(getNamespace());
  398   		wac.setConfigLocation(getContextConfigLocation());
  399   		wac.addApplicationListener(new SourceFilteringListener(wac, this));
  400   
  401   		postProcessWebApplicationContext(wac);
  402   		wac.refresh();
  403   
  404   		return wac;
  405   	}
  406   
  407   	/**
  408   	 * Post-process the given WebApplicationContext before it is refreshed
  409   	 * and activated as context for this servlet.
  410   	 * <p>The default implementation is empty. <code>refresh()</code> will
  411   	 * be called automatically after this method returns.
  412   	 * @param wac the configured WebApplicationContext (not refreshed yet)
  413   	 * @see #createWebApplicationContext
  414   	 * @see ConfigurableWebApplicationContext#refresh()
  415   	 */
  416   	protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
  417   	}
  418   
  419   	/**
  420   	 * Return the ServletContext attribute name for this servlet's WebApplicationContext.
  421   	 * <p>The default implementation returns
  422   	 * <code>SERVLET_CONTEXT_PREFIX + servlet name</code>.
  423   	 * @see #SERVLET_CONTEXT_PREFIX
  424   	 * @see #getServletName
  425   	 */
  426   	public String getServletContextAttributeName() {
  427   		return SERVLET_CONTEXT_PREFIX + getServletName();
  428   	}
  429   
  430   	/**
  431   	 * Return this servlet's WebApplicationContext.
  432   	 */
  433   	public final WebApplicationContext getWebApplicationContext() {
  434   		return this.webApplicationContext;
  435   	}
  436   
  437   
  438   	/**
  439   	 * This method will be invoked after any bean properties have been set and
  440   	 * the WebApplicationContext has been loaded. The default implementation is empty;
  441   	 * subclasses may override this method to perform any initialization they require.
  442   	 * @throws ServletException in case of an initialization exception
  443   	 * @throws BeansException if thrown by ApplicationContext methods
  444   	 */
  445   	protected void initFrameworkServlet() throws ServletException, BeansException {
  446   	}
  447   
  448   	/**
  449   	 * Refresh this servlet's application context, as well as the
  450   	 * dependent state of the servlet.
  451   	 * @throws BeansException in case of errors
  452   	 * @see #getWebApplicationContext()
  453   	 * @see org.springframework.context.ConfigurableApplicationContext#refresh()
  454   	 */
  455   	public void refresh() throws BeansException {
  456   		WebApplicationContext wac = getWebApplicationContext();
  457   		if (!(wac instanceof ConfigurableApplicationContext)) {
  458   			throw new IllegalStateException("WebApplicationContext does not support refresh: " + wac);
  459   		}
  460   		((ConfigurableApplicationContext) wac).refresh();
  461   	}
  462   
  463   	/**
  464   	 * ApplicationListener endpoint that receives events from this servlet's
  465   	 * WebApplicationContext.
  466   	 * <p>The default implementation calls {@link #onRefresh} in case of a
  467   	 * {@link org.springframework.context.event.ContextRefreshedEvent},
  468   	 * triggering a refresh of this servlet's context-dependent state.
  469   	 * @param event the incoming ApplicationContext event
  470   	 */
  471   	public void onApplicationEvent(ApplicationEvent event) {
  472   		if (event instanceof ContextRefreshedEvent) {
  473   			this.refreshEventReceived = true;
  474   			onRefresh(((ContextRefreshedEvent) event).getApplicationContext());
  475   		}
  476   	}
  477   
  478   	/**
  479   	 * Template method which can be overridden to add servlet-specific refresh work.
  480   	 * Called after successful context refresh.
  481   	 * <p>This implementation is empty.
  482   	 * @param context the current WebApplicationContext
  483   	 * @throws BeansException in case of errors
  484   	 * @see #refresh()
  485   	 */
  486   	protected void onRefresh(ApplicationContext context) throws BeansException {
  487   		// For subclasses: do nothing by default.
  488   	}
  489   
  490   
  491   	/**
  492   	 * Delegate GET requests to processRequest/doService.
  493   	 * <p>Will also be invoked by HttpServlet's default implementation of <code>doHead</code>,
  494   	 * with a <code>NoBodyResponse</code> that just captures the content length.
  495   	 * @see #doService
  496   	 * @see #doHead
  497   	 */
  498   	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
  499   	    throws ServletException, IOException {
  500   
  501   		processRequest(request, response);
  502   	}
  503   
  504   	/**
  505   	 * Delegate POST requests to {@link #processRequest}.
  506   	 * @see #doService
  507   	 */
  508   	protected final void doPost(HttpServletRequest request, HttpServletResponse response)
  509   	    throws ServletException, IOException {
  510   
  511   		processRequest(request, response);
  512   	}
  513   
  514   	/**
  515   	 * Delegate PUT requests to {@link #processRequest}.
  516   	 * @see #doService
  517   	 */
  518   	protected final void doPut(HttpServletRequest request, HttpServletResponse response)
  519   	    throws ServletException, IOException {
  520   
  521   		processRequest(request, response);
  522   	}
  523   
  524   	/**
  525   	 * Delegate DELETE requests to {@link #processRequest}.
  526   	 * @see #doService
  527   	 */
  528   	protected final void doDelete(HttpServletRequest request, HttpServletResponse response)
  529   	    throws ServletException, IOException {
  530   
  531   		processRequest(request, response);
  532   	}
  533   
  534   	/**
  535   	 * Delegate OPTIONS requests to {@link #processRequest}, if desired.
  536   	 * <p>Applies HttpServlet's standard OPTIONS processing first.
  537   	 * @see #doService
  538   	 */
  539   	protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  540   		super.doOptions(request, response);
  541   		if (this.dispatchOptionsRequest) {
  542   			processRequest(request, response);
  543   		}
  544   	}
  545   
  546   	/**
  547   	 * Delegate TRACE requests to {@link #processRequest}, if desired.
  548   	 * <p>Applies HttpServlet's standard TRACE processing first.
  549   	 * @see #doService
  550   	 */
  551   	protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  552   		super.doTrace(request, response);
  553   		if (this.dispatchTraceRequest) {
  554   			processRequest(request, response);
  555   		}
  556   	}
  557   
  558   
  559   	/**
  560   	 * Process this request, publishing an event regardless of the outcome.
  561   	 * <p>The actual event handling is performed by the abstract
  562   	 * {@link #doService} template method.
  563   	 */
  564   	protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
  565   			throws ServletException, IOException {
  566   
  567   		long startTime = System.currentTimeMillis();
  568   		Throwable failureCause = null;
  569   
  570   		try {
  571   			doService(request, response);
  572   		}
  573   		catch (ServletException ex) {
  574   			failureCause = ex;
  575   			throw ex;
  576   		}
  577   		catch (IOException ex) {
  578   			failureCause = ex;
  579   			throw ex;
  580   		}
  581   		catch (Throwable ex) {
  582   			failureCause = ex;
  583   			throw new NestedServletException("Request processing failed", ex);
  584   		}
  585   
  586   		finally {
  587   			if (failureCause != null) {
  588   				this.logger.debug("Could not complete request", failureCause);
  589   			}
  590   			else {
  591   				this.logger.debug("Successfully completed request");
  592   			}
  593   			if (this.publishEvents) {
  594   				// Whether or not we succeeded, publish an event.
  595   				long processingTime = System.currentTimeMillis() - startTime;
  596   				this.webApplicationContext.publishEvent(
  597   						new ServletRequestHandledEvent(this,
  598   								request.getRequestURI(), request.getRemoteAddr(),
  599   								request.getMethod(), getServletConfig().getServletName(),
  600   								WebUtils.getSessionId(request), getUsernameForRequest(request),
  601   								processingTime, failureCause));
  602   			}
  603   		}
  604   	}
  605   
  606   	/**
  607   	 * Determine the username for the given request.
  608   	 * <p>The default implementation takes the name of the UserPrincipal, if any.
  609   	 * Can be overridden in subclasses.
  610   	 * @param request current HTTP request
  611   	 * @return the username, or <code>null</code> if none found
  612   	 * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
  613   	 */
  614   	protected String getUsernameForRequest(HttpServletRequest request) {
  615   		Principal userPrincipal = request.getUserPrincipal();
  616   		return (userPrincipal != null ? userPrincipal.getName() : null);
  617   	}
  618   
  619   	/**
  620   	 * Subclasses must implement this method to do the work of request handling,
  621   	 * receiving a centralized callback for GET, POST, PUT and DELETE.
  622   	 * <p>The contract is essentially the same as that for the commonly overridden
  623   	 * <code>doGet</code> or <code>doPost</code> methods of HttpServlet.
  624   	 * <p>This class intercepts calls to ensure that exception handling and
  625   	 * event publication takes place.
  626   	 * @param request current HTTP request
  627   	 * @param response current HTTP response
  628   	 * @throws Exception in case of any kind of processing failure
  629   	 * @see javax.servlet.http.HttpServlet#doGet
  630   	 * @see javax.servlet.http.HttpServlet#doPost
  631   	 */
  632   	protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
  633   	    throws Exception;
  634   
  635   
  636   	/**
  637   	 * Close the WebApplicationContext of this servlet.
  638   	 * @see org.springframework.context.ConfigurableApplicationContext#close()
  639   	 */
  640   	public void destroy() {
  641   		getServletContext().log("Destroying Spring FrameworkServlet '" + getServletName() + "'");
  642   		if (this.webApplicationContext instanceof ConfigurableApplicationContext) {
  643   			((ConfigurableApplicationContext) this.webApplicationContext).close();
  644   		}
  645   	}
  646   
  647   }

Save This Page
Home » spring-framework-2.5.6-with-dependencies » org.springframework » web » servlet » [javadoc | source]