@EnableWebMvc 注解注入【DelegatingWebMvcConfiguration.class】类,把RequestMappingHandlerAdapter,RequestMappingHandlerMapping等自动加载到spring容器中。不需要再xml文件中配置映射。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
使用 @EnableWebMvc 注解下面图的内容就不需要在xml配置。
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
需要在实现类中配置上面xml内容。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@Configuration
@EnableWebMvc
public class WebMvcConfig {
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resourceViewResolver = new InternalResourceViewResolver();
resourceViewResolver.setViewClass(JstlView.class);
resourceViewResolver.setPrefix("/WEB-INF/jsp/");
resourceViewResolver.setSuffix(".jsp");
return resourceViewResolver;
}
}
下面是DEBUG实现DispatcherServlet源码分析图片:
1.首先会进入 doService()方法。
2. 然后再 doService() 方法中调用doDispatch()方法。
3.在doDispatch()方法中,调用getHandler() 方法。可以看到 【RequestMappingHandlerMapping】类被加载进来了。
4. 然后再向下执行getHandlerInternal(request);方法,getHandlerInternal()方法中执行addMatchingMappings()遍历所有映射路径,返回请求的类名字。
5. 请求的地址被返回到doDispatch()方法。
7.然后进入getHandlerAdapter()方法,【RequestMappingHanderAdater】类也被加载进来了。然后找到对应的适配器。
8.在handle()向下执行就进入Controller方法,然后返回对应地址。
9. 下面就会进去视图全名称,然后调用对应的视图。
然后就会找到对应的视图返回。
看完之后有很多疑问。
比如:在源码中 handlerAdapters的值在哪设定的?
initHandlerAdapters()中方法中加载。initHandlerAdapters()中方法handlerAdapters 赋值是通过spring上下文进行加载。 handlerMappings的值也同样在initHandlerMappings方法中加载。
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
}
}
}