All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping Maven / Gradle / Ivy

There is a newer version: 5.3.34
Show newest version
/*
 * Copyright 2002-2007 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.servlet.mvc.support;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import org.springframework.web.servlet.mvc.throwaway.ThrowawayController;

/**
 * Implementation of {@link HandlerMapping} that follows a simple convention for
 * generating URL path mappings from the class names of registered
 * {@link org.springframework.web.servlet.mvc.Controller} and
 * {@link org.springframework.web.servlet.mvc.throwaway.ThrowawayController} beans.
 *
 * 

For simple {@link org.springframework.web.servlet.mvc.Controller} implementations * (those that handle a single request type), the convention is to take the * {@link ClassUtils#getShortName short name} of the Class, * remove the 'Controller' suffix if it exists and return the remaining text, lowercased, * as the mapping, with a leading /. For example: *

    *
  • WelcomeController -> /welcome*
  • *
  • HomeController -> /home*
  • *
* *

For {@link MultiActionController MultiActionControllers} then a similar mapping is registered, * except that all sub-paths are registed using the trailing wildcard pattern /*. * For example: *

    *
  • WelcomeController -> /welcome/*
  • *
  • CatalogController -> /catalog/*
  • *
* *

For {@link MultiActionController} it is often useful to use * this mapping strategy in conjunction with the * {@link org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver}. * * @author Rob Harrop * @author Juergen Hoeller * @since 2.0 * @see org.springframework.web.servlet.mvc.Controller * @see org.springframework.web.servlet.mvc.throwaway.ThrowawayController * @see org.springframework.web.servlet.mvc.multiaction.MultiActionController */ public class ControllerClassNameHandlerMapping extends AbstractUrlHandlerMapping implements HandlerMapping { /** * Common suffix at the end of controller implementation classes. * Removed when generating the URL path. */ private static final String CONTROLLER_SUFFIX = "Controller"; private Set excludedPackages = Collections.singleton("org.springframework.web.servlet.mvc"); private Set excludedClasses = Collections.EMPTY_SET; /** * Specify Java packages that should be excluded from this mapping. * Any classes in such a package (or any of its subpackages) will be * ignored by this HandlerMapping. *

Default is to exclude the entire "org.springframework.web.servlet.mvc" * package, including its subpackages, since none of Spring's out-of-the-box * Controller implementations is a reasonable candidate for this mapping strategy. * Such controllers are typically handled by a separate HandlerMapping, * e.g. a {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping}, * alongside this ControllerClassNameHandlerMapping for application controllers. */ public void setExcludedPackages(String[] excludedPackages) { this.excludedPackages = (excludedPackages != null ? new HashSet(Arrays.asList(excludedPackages)) : Collections.EMPTY_SET); } /** * Specify controller classes that should be excluded from this mapping. * Any such classes will simply be ignored by this HandlerMapping. */ public void setExcludedClasses(Class[] excludedClasses) { this.excludedClasses = (excludedClasses != null ? new HashSet(Arrays.asList(excludedClasses)) : Collections.EMPTY_SET); } /** * Calls the {@link #detectControllers()} method in addition to the * superclass's initialization. */ protected void initApplicationContext() { super.initApplicationContext(); detectControllers(); } /** * Detect all the {@link org.springframework.web.servlet.mvc.Controller} and * {@link org.springframework.web.servlet.mvc.throwaway.ThrowawayController} * beans registered in the {@link org.springframework.context.ApplicationContext} * and register a URL path mapping for each one based on rules defined here. * @throws BeansException if the controllers couldn't be obtained or registered * @see #generatePathMapping(Class) */ protected void detectControllers() throws BeansException { registerControllers(Controller.class); registerControllers(ThrowawayController.class); } /** * Register all controllers of the given type, searching the current * DispatcherServlet's ApplicationContext for matching beans. * @param controllerType the type of controller to search for * @throws BeansException if the controllers couldn't be obtained or registered */ protected void registerControllers(Class controllerType) throws BeansException { String[] beanNames = getApplicationContext().getBeanNamesForType(controllerType); for (int i = 0; i < beanNames.length; i++) { String beanName = beanNames[i]; Class beanClass = getApplicationContext().getType(beanName); if (isEligibleForMapping(beanName, beanClass)) { registerController(beanName, beanClass); } } } /** * Determine whether the specified controller is excluded from this mapping. * @param beanName the name of the controller bean * @param beanClass the concrete class of the controller bean * @return whether the specified class is excluded * @see #setExcludedPackages * @see #setExcludedClasses */ protected boolean isEligibleForMapping(String beanName, Class beanClass) { if (beanClass == null) { if (logger.isDebugEnabled()) { logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " + "because its bean type could not be determined"); } return false; } if (this.excludedClasses.contains(beanClass)) { if (logger.isDebugEnabled()) { logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " + "because its bean class is explicitly excluded: " + beanClass.getName()); } return false; } String beanClassName = beanClass.getName(); for (Iterator it = this.excludedPackages.iterator(); it.hasNext();) { String packageName = (String) it.next(); if (beanClassName.startsWith(packageName)) { if (logger.isDebugEnabled()) { logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " + "because its bean class is defined in an excluded package: " + beanClass.getName()); } return false; } } return true; } /** * Register the controller with the given name, as defined * in the current application context. * @param beanName the name of the controller bean * @param beanClass the concrete class of the controller bean * @throws BeansException if the controller couldn't be registered * @throws IllegalStateException if there is a conflicting handler registered * @see #getApplicationContext() */ protected void registerController(String beanName, Class beanClass) throws BeansException, IllegalStateException { String urlPath = generatePathMapping(beanClass); if (logger.isDebugEnabled()) { logger.debug("Registering Controller '" + beanName + "' as handler for URL path [" + urlPath + "]"); } registerHandler(urlPath, beanName); } /** * Generate the actual URL path for the given controller class. *

Subclasses may choose to customize the paths that are generated * by overriding this method. * @param beanClass the controller bean class to generate a mapping for * @return the URL path mapping for the given controller */ protected String generatePathMapping(Class beanClass) { StringBuffer pathMapping = new StringBuffer("/"); String className = ClassUtils.getShortName(beanClass.getName()); String path = (className.endsWith(CONTROLLER_SUFFIX) ? className.substring(0, className.indexOf(CONTROLLER_SUFFIX)) : className); pathMapping.append(path.toLowerCase()); if (MultiActionController.class.isAssignableFrom(beanClass)) { pathMapping.append("/*"); } else { pathMapping.append("*"); } return pathMapping.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy