org.springframework.web.portlet.mvc.annotation
public class: DefaultAnnotationHandlerMapping [javadoc |
source]
java.lang.Object
org.springframework.context.support.ApplicationObjectSupport
org.springframework.web.portlet.handler.AbstractHandlerMapping
org.springframework.web.portlet.handler.AbstractMapBasedHandlerMapping
org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping
All Implemented Interfaces:
HandlerMapping, Ordered, ApplicationContextAware
Implementation of the
org.springframework.web.portlet.HandlerMapping
interface that maps handlers based on portlet modes expressed through the
RequestMapping annotation at the type or method level.
Registered by default in org.springframework.web.portlet.DispatcherPortlet
on Java 5+. NOTE: If you define custom HandlerMapping beans in your
DispatcherPortlet context, you need to add a DefaultAnnotationHandlerMapping bean
explicitly, since custom HandlerMapping beans replace the default mapping strategies.
Defining a DefaultAnnotationHandlerMapping also allows for registering custom
interceptors:
<bean class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
...
</property>
</bean>
Annotated controllers are usually marked with the
Controller stereotype
at the type level. This is not strictly necessary when
RequestMapping is
applied at the type level (since such a handler usually implements the
org.springframework.web.portlet.mvc.Controller interface). However,
Controller is required for detecting
RequestMapping annotations
at the method level.
NOTE: Method-level mappings are only allowed to narrow the mapping
expressed at the class level (if any). Portlet modes need to uniquely map onto
specific handler beans, with any given portlet mode only allowed to be mapped
onto one specific handler bean (not spread across multiple handler beans).
It is strongly recommended to co-locate related handler methods into the same bean.
The AnnotationMethodHandlerAdapter is responsible for processing
annotated handler methods, as mapped by this HandlerMapping. For
RequestMapping at the type level, specific HandlerAdapters such as
org.springframework.web.portlet.mvc.SimpleControllerHandlerAdapter apply.
| Methods from org.springframework.web.portlet.handler.AbstractHandlerMapping: |
|---|
|
adaptInterceptor, extendInterceptors, getAdaptedInterceptors, getDefaultHandler, getHandler, getHandlerExecutionChain, getHandlerInternal, getOrder, initApplicationContext, initInterceptors, setApplyWebRequestInterceptorsToRenderPhaseOnly, setDefaultHandler, setInterceptors, setOrder |
| Method from org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping Detail: |
protected boolean detectHandlerMethods(Class handlerType,
String beanName,
RequestMapping typeMapping) {
final Set< Boolean > handlersRegistered = new HashSet< Boolean >(1);
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() {
public void doWith(Method method) {
RequestMapping mapping = method.getAnnotation(RequestMapping.class);
if (mapping != null) {
String[] modeKeys = mapping.value();
if (modeKeys.length == 0) {
if (typeMapping != null) {
modeKeys = typeMapping.value();
}
else {
throw new IllegalStateException(
"No portlet mode mappings specified - neither at type nor method level");
}
}
String[] params = mapping.params();
if (typeMapping != null) {
PortletAnnotationMappingUtils.validateModeMapping(modeKeys, typeMapping.value());
params = StringUtils.mergeStringArrays(typeMapping.params(), params);
}
ParameterMappingPredicate predicate = new ParameterMappingPredicate(params);
for (String modeKey : modeKeys) {
registerHandler(new PortletMode(modeKey), beanName, predicate);
handlersRegistered.add(Boolean.TRUE);
}
}
}
});
return !handlersRegistered.isEmpty();
}
Derive portlet mode mappings from the handler's method-level mappings. |
protected void detectHandlers() throws BeansException {
ApplicationContext context = getApplicationContext();
String[] beanNames = context.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
Class< ? > handlerType = context.getType(beanName);
ListableBeanFactory bf = (context instanceof ConfigurableApplicationContext ?
((ConfigurableApplicationContext) context).getBeanFactory() : context);
GenericBeanFactoryAccessor bfa = new GenericBeanFactoryAccessor(bf);
RequestMapping mapping = bfa.findAnnotationOnBean(beanName, RequestMapping.class);
if (mapping != null) {
String[] modeKeys = mapping.value();
String[] params = mapping.params();
boolean registerHandlerType = true;
if (modeKeys.length == 0 || params.length == 0) {
registerHandlerType = !detectHandlerMethods(handlerType, beanName, mapping);
}
if (registerHandlerType) {
ParameterMappingPredicate predicate = new ParameterMappingPredicate(params);
for (String modeKey : modeKeys) {
registerHandler(new PortletMode(modeKey), beanName, predicate);
}
}
}
else if (AnnotationUtils.findAnnotation(handlerType, Controller.class) != null) {
detectHandlerMethods(handlerType, beanName, mapping);
}
}
}
Register all handlers specified in the Portlet mode map for the corresponding modes. |
protected Object getLookupKey(PortletRequest request) throws Exception {
return request.getPortletMode();
}
Uses the current PortletMode as lookup key. |
public void initApplicationContext() throws BeansException {
super.initApplicationContext();
detectHandlers();
}
Calls the registerHandlers method in addition
to the superclass's initialization. |