SpringMVCのDispatcherServiceletのデフォルトポリシー
SpringMVCを使用する場合、HandlerMappingが要求パスとプロセッサ間のマッピングを定義する必要があることを知っています.HandlerAdapterがプロセッサメソッドを呼び出し、ModelAndViewオブジェクトを返す必要があります.ビューを解析するにはViewResolverが必要です.これらはSpringMVCで最も基本的なインタフェースです.通常、SpringMVCのプロファイルで使用するHandlerMapping、HandlerAdapter、ViewResolverを定義する必要があります.注釈ベースのSpringMVC構成も同様です.一般的にSpringMVCプロファイルは次のようになります.
mvcネーミングスペースはSpringが提供する簡単なSpringMVC構成のネーミングスペースであり、
はSpringのbeanコンテナにHandlerMappingインタフェース実装RequestMappingHandlerMappingタイプのbeanとHandlerAdapterインタフェース実装クラスRequestMappingHandlerAdapterタイプのbeanを自動的に登録する.
は、ViewResolverを迅速に定義するために実装され、
は、InternalResourceViewResolverタイプのViewResolverを自動的に定義します.これらの比較基本インタフェースに対して,それらの実装を定義しなくてもSpringMVC内部にはデフォルトの定義が与えられ,これらをポリシーと呼ぶ.SpringMVCは、これらのデフォルトポリシーを
DispatcherServlet.properties
というファイルに定義し、DispatcherServiceletと同じパッケージに定義します.以下は筆者が使用する4.1である.0バージョンのDispatcherServicelet.propertiesファイルの定義.org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
上記の定義から、SpringMVCを使用する場合、HandlerMappingを定義しなくても、SpringMVCのデフォルトではBeanNameUrlHandlerMappingとD e faultAnnotationHandlerMappingが定義されていることがわかります.HandlerAdapterとViewResolverも同じです.他にも、DispatcherServiceletを参照してください.propertiesで.デフォルトのポリシーがあなたの要求を満たすことができない場合は、beanコンテナで私たち自身の対応する実装を定義することができます.このとき、私たち自身の実装が適用されます.初期化HandlerMappingを例に、DispatcherServiceletのソースコードを見てみましょう.
/**
* Initialize the HandlerMappings used by this class.
* If no HandlerMapping beans are defined in the BeanFactory for this namespace,
* we default to BeanNameUrlHandlerMapping.
*/
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList(matchingBeans.values());
// We keep HandlerMappings in sorted order.
OrderComparator.sort(this.handlerMappings);
}
}
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}
ソースコードから、SpringMVCは、バインドされたApplicationContextから対応するHandlerMapping定義を取得し、取得しない場合は
getDefaultStrategies(context, HandlerMapping.class)
を呼び出してデフォルトポリシーから取得することがわかります.そのコードは以下の通りです.protected List getDefaultStrategies(ApplicationContext context, Class strategyInterface) {
String key = strategyInterface.getName();
String value = defaultStrategies.getProperty(key);
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List strategies = new ArrayList(classNames.length);
for (String className : classNames) {
try {
Class> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]", ex);
}
catch (LinkageError err) {
throw new BeanInitializationException(
"Error loading DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]: problem with class file or dependent class", err);
}
}
return strategies;
}
else {
return new LinkedList();
}
}
このうちdefaultStrategiesは、対応する
DispatcherServlet.properties
ファイルの内容です.private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
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, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
}
}
(注:SpringMVC 4.1.0に基づいて記載されています)