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>, javax.servlet.ServletContext) 方法)接收实现,扩展或已经由注释指定的类类型进行注释的
应用程序类的集合。

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 的映射,并注册我们的配置类。

具体代码

  1. 创建项目,并导入相关 jar 包(与之前 xml 方式的步骤一致)
  2. 创建 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 整合

  1. 整合说明:SSM整合可以使用多种方式,咱们会选择XML + 注解的方式
  2. 整合的思路
  3. 先搭建整合的环境
  4. 先把Spring的配置搭建完成
  5. 再使用Spring整合SpringMVC框架
  6. 最后使用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>

评论