20201201黄春跃
20201201黄春跃
知识点
基于 java 的 springMVC 配置
实现WebApplicationInitializer接口
org.springframework.web.WebApplicationInitializer 接口是在Servlet 3.0+环境中实现,以便
以编程方式配置 ServletContext 。
这个接口的实现将被 SpringServletContainerInitializer 自动检测,它本身将被任何Servlet 3.0容
器自动引导(自动加载)。
运行机制
Servlet 3.0 提供 javax.servlet.ServletContainerInitializer 接口是为了允许在Web应用程序
的启动阶段通知库/运行时( library/runtime ),并响应此请求而对 Servlet 、过滤器和监听器执行任
何所需的程序化注册。
该接口的实现可以用注释 HandlesTypes ,以便(使用它们的 onStartup(java.util.Set
应用程序类的集合。
public interface ServletContainerInitializer {
// c 表示将要加载的应用程序类
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}
SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements
ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses,
ServletContext servletContext)
throws ServletException {
// 存储所有实现了 WebApplicationInitializer 接口的类
List<WebApplicationInitializer> initializers = new LinkedList<>();
// 省略部分代码(判断是否符合要求,符合要求添加到集合中去)
// 循环调用其 onStartup 方法,将委派ServletContext给
WebApplicationInitializer 应用 程序类路径上存在的所有实现
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
Spring的 WebApplicationInitializer 仅包含一种方法:
WebApplicationInitializer.onStartup(ServletContext) 。签名非常类似于
ServletContainerInitializer.onStartup(Set, ServletContext) :简而言之,
SpringServletContainerInitializer 负责实例化和委派 ServletContext 给任何用户定义的
WebApplicationInitializer 的实现类。然后,每个 WebApplicationInitializer 实现类负责进行
初始化 ServletContext 的实际工作。委托的确切过程就是 onStartup 中的代码。
结论:
所以我们可以通过实现 WebApplicationInitializer 接口并实现 onStartup 来初始化
ServletContext ,向 ServletContext 中添加 DispatcherServlet 的映射,并注册我们的配置类。
具体代码
- 创建项目,并导入相关 jar 包(与之前 xml 方式的步骤一致)
- 创建 MyWebApplicationInitializer 实现 WebApplicationInitializer 接口
public class MyWebApplicationInitializer implements
WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws
ServletException {
/*
加载 spring 容器,使用的是注解所以使用
AnnotationConfigWebApplicationContext
如果配置文件是xml 使用 XmlWebApplicationContext
XmlWebApplicationContext appContext = new
XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-
config.xml");
*/
AnnotationConfigWebApplicationContext ac = new
AnnotationConfigWebApplicationContext();
// 注册 spring 配置类 AppConfig
ac.register(AppConfig.class);
ac.refresh();
// 创建 dispathcerServlet 对象
DispatcherServlet dispatcherServlet = new
DispatcherServlet(ac);
// 将 dispathcerServlet 添加到 web容器中
ServletRegistration.Dynamic servlet =
servletContext.addServlet("dispatcherServlet", dispatcherServlet);
// 设置启动就加载 dispathcerServlet
servlet.setLoadOnStartup(1);
// 设置 dispathcerServlet 的映射路径
servlet.addMapping("/");
}
}
上面的代码,等同于 xml 中的如下代码:
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-
class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 给 servlet 传递参数 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- xml配置 -->
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<init-param>
<param-name>contextClass</param-name>
<!-- java 配置 -->
<param-
value>com.itlaobing.springmvc.config.SpringConfig.class</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 所有的请求都由 DispatcherServlet 来处理 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
完成上述操作后,即可进行测试了。
继承AbstractAnnotationConfigDispatcherServletInitializer
org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletIn
itializer 是spring 3.2 后提供的一个 WebApplicationInitializer 的抽象实现。此
WebApplicationInitializer 实现中注册了 DispatcherServlet 并使用基于Java的Spring配置。
getRootConfigClasses() - 用于“根”应用程序上下文(非Web基础结构)配置。
getServletConfigClasses()-用于DispatcherServlet 应用程序上下文(Spring MVC基础结
构)配置。
// 其父类 AbstractDispatcherServletInitializer 的抽象方法
getServletMappings() - 用于指定过滤器DispatcherServlet的映射
AbstractDispatcherServletInitializer
@Override
public void onStartup(ServletContext servletContext) throws
ServletException {
super.onStartup(servletContext);
// 调用 registerDispatcherServlet
registerDispatcherServlet(servletContext);
}
protected void registerDispatcherServlet(ServletContext servletContext) {
// 获取 servletName 如果重写getServletName() 值默认是 dispatcher
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return
empty or null");
/*
创建要提供给的Servlet应用程序上下文DispatcherServlet。
具体实现在
AbstractAnnotationConfigDispatcherServletInitializer.createServletApplicati
onContext()
此实现创建了一个AnnotationConfigWebApplicationContext对象,并为其
提供了由getServletConfigClasses()返回的带注释的类
返回的上下文委托给Spring的
DispatcherServlet.DispatcherServlet(WebApplicationContext)。
因此,它通常包含控制器,视图解析器,语言环境解析器和其他与Web相关的bean
简单的说就是读取 java 配置类
*/
WebApplicationContext servletAppContext =
createServletApplicationContext();
Assert.notNull(servletAppContext,
"createServletApplicationContext() did not return an
application " +
"context for servlet [" + servletName + "]");
// 创建 dispatcherServlet 对象。new
DispatcherServlet(servletAppContext)
FrameworkServlet dispatcherServlet =
createDispatcherServlet(servletAppContext);
dispatcherServlet.setContextInitializers(getServletApplicationContextIniti
alizers());
// 将 dispatcherServlet 添加到 servletContext中
ServletRegistration.Dynamic registration =
servletContext.addServlet(servletName, dispatcherServlet);
Assert.notNull(registration,
"Failed to register servlet with name '" + servletName +
"'." + "Check if there is another servlet registered under
the same name.");
// 设置启动加载
registration.setLoadOnStartup(1);
// 通过 getServletMappings() 获取 dispatcherServlet 的映射路径并添加到
servlet
registration.addMapping(getServletMappings());
registration.setAsyncSupported(isAsyncSupported());
// 通过 getServletFilters() 获取所有的过滤器
Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
// 注册过滤器
registerServletFilter(servletContext, filter);
}
}
customizeRegistration(registration);
}
具体实现
public class MyWebAppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
/**
* 设置 web 根配置的类
* @return
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
/**
* 关于 spring 的配置
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{AppConfig.class};
}
/**
* 设置 dispatcherServlet 的映射路径
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
* 过滤器
* @return
*/
@Override
protected Filter[] getServletFilters() {
return new Filter[]{new MyFileter(), new MyFileter1()
, new HiddenHttpMethodFilter()
, new CharacterEncodingFilter()};
}
}
@Configuration
@ComponentScan("com.itlaobing.spring")
@EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
/**
* 视图解析器
* @return
*/
@Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver resourceViewResolver = new
InternalResourceViewResolver();
resourceViewResolver.setPrefix("/WEB-INF/pages/");
resourceViewResolver.setSuffix(".jsp");
return resourceViewResolver;
}
/**
* 异常处理器
* @return
*/
@Bean
public CustomExceptionResolver exception(){
return new CustomExceptionResolver();
}
/**
* 上传文件
*/
@Bean
public CommonsMultipartResolver multipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(5242880L);
return resolver;
}
/**
* 拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new
HandlerInterceptorDemo1()).addPathPatterns("/**");
registry.addInterceptor(new
HandlerInterceptorDemo2()).addPathPatterns("/**");
}
/*** 静态资源
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/js/**")
.addResourceLocations("/static/js/")
.setCachePeriod(31556926);
registry.addResourceHandler("/static/img/**")
.addResourceLocations("/static/img/");
}
/**
* 消息转换
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>>
converters) {
Jackson2ObjectMapperBuilder builder = new
Jackson2ObjectMapperBuilder()
.indentOutput(true)
.dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
converters.add(new
MappingJackson2HttpMessageConverter(builder.build()));
// converters.add(new FastJsonHttpMessageConverter());
// converters.add(new
MappingJackson2XmlHttpMessageConverter(Jackson2ObjectMapperBuilder.xml().bu
ild()));
}
}
@EnableWebMvc - 将此注释添加到 @Configuration 类中会从中导入Spring MVC配置
WebMvcConfigurationSupport 。要自定义导入的配置,需要实现接口 WebMvcConfigurer 并覆
盖各个方法
WebMvcConfigurer 定义回调方法以自定义通过启用 @EnableWebMvc 的Spring MVC的基于Java的
配置
注意:只有一个 @Configuration 类可以具有 @EnableWebMvc 注释,以导入Spring Web MVC配置。
但是,可以 @Configuration 实现多个类 WebMvcConfigurer 以定制提供的配置。
如果 WebMvcConfigurer 未显示一些需要配置的更高级的设置,请考虑删除 @EnableWebMvc 注释并直
接从 WebMvcConfigurationSupport 继承
@Configuration
public class AppConfig extends WebMvcConfigurationSupport{
// 省略其他代码
}
SSM 整合
- 整合说明:SSM整合可以使用多种方式,咱们会选择XML + 注解的方式
- 整合的思路
- 先搭建整合的环境
- 先把Spring的配置搭建完成
- 再使用Spring整合SpringMVC框架
- 最后使用Spring整合MyBatis框架
创建数据库和表结构
create database `ssm` charset 'utf8';
use `ssm`;
create table account(
id int primary key auto_increment,
name varchar(100),
money double(7,2)
);
创建 Maven 工程
设置项目的打包方式
创建子模块:
ssm_domain jar
ssm_dao jar
ssm_service jar
ssm_web war
web依赖于service,service依赖于dao,dao依赖于domain
运行的时候,只用把web项目加入到tomcat即可运行
在ssm_parent的pom.xml文件中引入坐标依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itlaobing</groupId>
<artifactId>ssm_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>ssm_domain</module>
<module>ssm_service</module>
<module>ssm_dao</module>
<module>ssm_web</module>
</modules>
<packaging>pom</packaging>
<name>Maven</name>
<!-- FIXME change it to the project's website -->
<url>http://maven.apache.org/</url>
<inceptionYear>2001</inceptionYear>
<distributionManagement>
<site>
<id>website</id>
<url>scp://webhost.company.com/www/website</url>
</site>
</distributionManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>5.0.2.RELEASE</spring.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<shiro.version>1.2.3</shiro.version>
<mysql.version>5.1.6</mysql.version>
<mybatis.version>3.4.5</mybatis.version>
</properties>
<dependencies>
<!-- spring -->
<!--
https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using
Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-
plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<locales>en,fr</locales>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
</plugin>
</plugins>
</reporting>
</project>
评论