SpringWeb Mvc从手动到自动装配
解决Spring Web Mvc 自动装配,要解决两大问题
- DispatcherServlet 注册到Servlet 容器,可以通过WebApplicationInitializer、AbstractAnnotationConfigDispatcherServletInitializer两种方式来做
- Spring Web Mvc 关键组件装配并关联到DispatcherServlet上去
Spring Web Mvc 关键组件
Bean 类型 | 说明 |
---|---|
HandlerMapping | 将请求映射到handler 并将一些拦截器添加到Handler上 ,其中两种主要 HandlerMapping 实现, RequestMappingHandlerMapping 支持标注 @RequestMapping 的方法, SimpleUrlHandlerMapping 维护精确的URI路径与处理器的映射 |
HandlerAdapter | 帮助 DispatcherServlet 调用请求处理器(Handler),无需关注其中实际的调用细节 |
HandlerExceptionResolver | 根据不同的策略处理异常,比如到某一个错误的html或者其他 |
ViewResolver | 视图渲染器,从处理器(Handler)返回字符类型的逻辑视图名称解析出实际的 View 对象,该对象将渲染后的内容输出到HTTP 响应中。 |
LocaleResolver, LocaleContextResolver | 解决国际化、本地化 |
ThemeResolver | 主题渲染器 |
传统方式配置
1、配置web.xml
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app1-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping>
</web-app>
2、配置Spring Mvc --定义RequestMappingHandlerMapping、RequestMappingHandlerAdapter、InternalResourceViewResolver等
<!-- 对模型视图名称的解析,在根目录下找对应的jsp文件 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- springmvc 注解驱动 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" >
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html; charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<bean
class="org.springframework.http.converter.json.GsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html; charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
基于Spring 注解方式
- 配置Spring Mvc
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
// <!--<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>-->
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截中...");
return true;
}
});
}
}
- 配置web.xml(DispatcherServlet注册)
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { MyWebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
@ComponentScan(basePackages = "com.github.bearboy80.web")
public class MyWebConfig{
}
spring boot 自动装配关键类
- WebMvcAutoConfiguration
主要是实现mvc 核心组件配置,比如requestMappingHandlerAdapter、RequestMappingHandlerAdapter等 - DispatcherServletAutoConfiguration
主要实现DispatcherServlet配置和注册到Servlet容器
关键代码:实现DispatcherServlet注册到Servlet容器,关于原理可以参考SpringBoot 装配Filter、Servlet源码分析
@Configuration(proxyBeanMethods = false)
@Conditional(DispatcherServletRegistrationCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
@Import(DispatcherServletConfiguration.class)
protected static class DispatcherServletRegistrationConfiguration {
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
webMvcProperties.getServlet().getPath());
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
multipartConfig.ifAvailable(registration::setMultipartConfig);
return registration;
}
}