?? dispatcherportlet.java
字號:
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.portlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.UnavailableException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.core.JdkVersion;
import org.springframework.core.OrderComparator;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.portlet.context.PortletRequestAttributes;
import org.springframework.web.portlet.multipart.MultipartActionRequest;
import org.springframework.web.portlet.multipart.PortletMultipartResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewRendererServlet;
import org.springframework.web.servlet.ViewResolver;
/**
* Central dispatcher for use within the Portlet MVC framework, e.g. for web UI
* controllers. Dispatches to registered handlers for processing a portlet request.
*
* <p>This portlet is very flexible: It can be used with just about any workflow,
* with the installation of the appropriate adapter classes. It offers the
* following functionality that distinguishes it from other request-driven
* portlet MVC frameworks:
*
* <ul>
* <li>It is based around a JavaBeans configuration mechanism.
*
* <li>It can use any {@link HandlerMapping} implementation - pre-built or provided
* as part of an application - to control the routing of requests to handler objects.
* Default is a {@link org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping}
* on Java 5+; there is no default on Java 1.4. HandlerMapping objects can be defined as
* beans in the portlet's application context, implementing the HandlerMapping interface,
* overriding the default HandlerMapping if present. HandlerMappings can be given any
* bean name (they are tested by type).
*
* <li>It can use any {@link HandlerAdapter}; this allows for using any handler interface.
* The default adapter is {@link org.springframework.web.portlet.mvc.SimpleControllerHandlerAdapter}
* for Spring's {@link org.springframework.web.portlet.mvc.Controller} interface.
* When running in a Java 5+ environment, a default
* {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter}
* will be registered as well. HandlerAdapter objects can be added as beans in the
* application context, overriding the default HandlerAdapter. Like HandlerMappings,
* HandlerAdapters can be given any bean name (they are tested by type).
*
* <li>The dispatcher's exception resolution strategy can be specified via a
* {@link HandlerExceptionResolver}, for example mapping certain exceptions to
* error pages. Default is none. Additional HandlerExceptionResolvers can be added
* through the application context. HandlerExceptionResolver can be given any
* bean name (they are tested by type).
*
* <li>Its view resolution strategy can be specified via a {@link ViewResolver}
* implementation, resolving symbolic view names into View objects. Default is
* {@link org.springframework.web.servlet.view.InternalResourceViewResolver}.
* ViewResolver objects can be added as beans in the application context,
* overriding the default ViewResolver. ViewResolvers can be given any bean name
* (they are tested by type).
*
* <li>The dispatcher's strategy for resolving multipart requests is determined by a
* {@link org.springframework.web.portlet.multipart.PortletMultipartResolver} implementation.
* An implementations for Jakarta Commons FileUpload is included:
* {@link org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver}.
* The MultipartResolver bean name is "portletMultipartResolver"; default is none.
* </ul>
*
* <p><b>NOTE: The <code>@RequestMapping</code> annotation will only be processed
* if a corresponding <code>HandlerMapping</code> (for type level annotations)
* and/or <code>HandlerAdapter</code> (for method level annotations)
* is present in the dispatcher.</b> This is the case by default.
* However, if you are defining custom <code>HandlerMappings</code> or
* <code>HandlerAdapters</code>, then you need to make sure that a
* corresponding custom <code>DefaultAnnotationHandlerMapping</code>
* and/or <code>AnnotationMethodHandlerAdapter</code> is defined as well
* - provided that you intend to use <code>@RequestMapping</code>.
*
* <p><b>A web application can define any number of DispatcherPortlets.</b>
* Each portlet will operate in its own namespace, loading its own application
* context with mappings, handlers, etc. Only the root application context
* as loaded by {@link org.springframework.web.context.ContextLoaderListener},
* if any, will be shared.
*
* <p>Thanks to Rainer Schmitz and Nick Lothian for their suggestions!
*
* @author William G. Thompson, Jr.
* @author John A. Lewis
* @author Juergen Hoeller
* @since 2.0
* @see org.springframework.web.portlet.mvc.Controller
* @see org.springframework.web.servlet.ViewRendererServlet
* @see org.springframework.web.context.ContextLoaderListener
*/
public class DispatcherPortlet extends FrameworkPortlet {
/**
* Well-known name for the PortletMultipartResolver object in the bean factory for this namespace.
*/
public static final String MULTIPART_RESOLVER_BEAN_NAME = "portletMultipartResolver";
/**
* Well-known name for the HandlerMapping object in the bean factory for this namespace.
* Only used when "detectAllHandlerMappings" is turned off.
* @see #setDetectAllViewResolvers
*/
public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
/**
* Well-known name for the HandlerAdapter object in the bean factory for this namespace.
* Only used when "detectAllHandlerAdapters" is turned off.
* @see #setDetectAllHandlerAdapters
*/
public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
/**
* Well-known name for the HandlerExceptionResolver object in the bean factory for this
* namespace. Only used when "detectAllHandlerExceptionResolvers" is turned off.
* @see #setDetectAllViewResolvers
*/
public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";
/**
* Well-known name for the ViewResolver object in the bean factory for this namespace.
*/
public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
/**
* Default URL to ViewRendererServlet. This bridge servlet is used to convert
* portlet render requests to servlet requests in order to leverage the view support
* in the <code>org.springframework.web.view</code> package.
*/
public static final String DEFAULT_VIEW_RENDERER_URL = "/WEB-INF/servlet/view";
/**
* Request attribute to hold the currently chosen HandlerExecutionChain.
* Only used for internal optimizations.
*/
public static final String HANDLER_EXECUTION_CHAIN_ATTRIBUTE =
DispatcherPortlet.class.getName() + ".HANDLER";
/**
* Unlike the Servlet version of this class, we have to deal with the
* two-phase nature of the portlet request. To do this, we need to pass
* forward any exception that occurs during the action phase, so that
* it can be displayed in the render phase. The only direct way to pass
* things forward and preserve them for each render request is through
* render parameters, but these are limited to String objects and we need
* to pass the Exception itself. The only other way to do this is in the
* session. The bad thing about using the session is that we have no way
* of knowing when we are done re-rendering the request and so we don't
* know when we can remove the objects from the session. So we will end
* up polluting the session with an old exception when we finally leave
* the render phase of one request and move on to something else.
*/
public static final String ACTION_EXCEPTION_SESSION_ATTRIBUTE =
DispatcherPortlet.class.getName() + ".ACTION_EXCEPTION";
/**
* This render parameter is used to indicate forward to the render phase
* that an exception occurred during the action phase.
*/
public static final String ACTION_EXCEPTION_RENDER_PARAMETER = "actionException";
/**
* Log category to use when no mapped handler is found for a request.
*/
public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.portlet.PageNotFound";
/**
* Name of the class path resource (relative to the DispatcherPortlet class)
* that defines DispatcherPortet's default strategy names.
*/
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherPortlet.properties";
/**
* Additional logger to use when no mapped handler is found for a request.
*/
protected static final Log pageNotFoundLogger = LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY);
private static final Properties defaultStrategies;
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherPortlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'DispatcherPortlet.properties': " + ex.getMessage());
}
}
/** Detect all HandlerMappings or just expect "handlerMapping" bean? */
private boolean detectAllHandlerMappings = true;
/** Detect all HandlerAdapters or just expect "handlerAdapter" bean? */
private boolean detectAllHandlerAdapters = true;
/** Detect all HandlerExceptionResolvers or just expect "handlerExceptionResolver" bean? */
private boolean detectAllHandlerExceptionResolvers = true;
/** Detect all ViewResolvers or just expect "viewResolver" bean? */
private boolean detectAllViewResolvers = true;
/** URL that points to the ViewRendererServlet */
private String viewRendererUrl = DEFAULT_VIEW_RENDERER_URL;
/** Expose LocaleContext and RequestAttributes as inheritable for child threads? */
private boolean threadContextInheritable = false;
/** MultipartResolver used by this portlet */
private PortletMultipartResolver multipartResolver;
/** List of HandlerMappings used by this portlet */
private List handlerMappings;
/** List of HandlerAdapters used by this portlet */
private List handlerAdapters;
/** List of HandlerExceptionResolvers used by this portlet */
private List handlerExceptionResolvers;
/** List of ViewResolvers used by this portlet */
private List viewResolvers;
/**
* Set whether to detect all HandlerMapping beans in this portlet's context.
* Else, just a single bean with name "handlerMapping" will be expected.
* <p>Default is true. Turn this off if you want this portlet to use a
* single HandlerMapping, despite multiple HandlerMapping beans being
* defined in the context.
*/
public void setDetectAllHandlerMappings(boolean detectAllHandlerMappings) {
this.detectAllHandlerMappings = detectAllHandlerMappings;
}
/**
* Set whether to detect all HandlerAdapter beans in this portlet's context.
* Else, just a single bean with name "handlerAdapter" will be expected.
* <p>Default is "true". Turn this off if you want this portlet to use a
* single HandlerAdapter, despite multiple HandlerAdapter beans being
* defined in the context.
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -