14SSM框架整合

对于Java EE应用程序的开发,行业中提供了非常多的技术框架,但是不管如何进行技术选型,Java EE应用都可以分为表现层、业务逻辑层和数据持久层,当前,这3个层的主流框架分别是Spring MVC、Spring和MyBatis,简称为SSM框架,Java EE应用程序也经常通过整合这3大框架来完成开发。SSM框架的整合有多种方式,本章将对目前常用的整合方式纯注解的整合方式来对SSM框架的整合进行介绍。

14.1 常用方式整合SSM框架

14.1.1 整合思路

进行SSM框架整合时,3个框架的分工如下所示。

  • MyBatis负责与数据库进行交互。
  • Spring负责事务管理,Spring可以管理持久层的Mapper对象及业务层的Service对象。由于Mapper对象和Service对象都在Spring容器中,所以可以在业务逻辑层通过Service对象调用持久层的Mapper对象。
  • Spring MVC负责管理表现层的Handler。Spring MVC容器是Spring容器的子容器,因此Spring MVC容器可以调用Spring容器中的Service对象。

下面通过一个图书信息查询案例来描述SSM框架的整合,案例实现思路如下。

  • 搭建项目基础结构。首先需要在数据库中搭建项目对应的数据库环境;然后创建一个Maven Web项目,并引入案例所需的依赖;最后创建项目的实体类,创建三层架构对应的模块、类和接口。
  • 整合Spring和MyBatis。在Spring配置文件中配置数据源信息,并且将SqlSessionFactory对象和Mapper对象都交由Spring管理。
  • 整合Spring和Spring MVC。Spring MVC是Spring框架中的一个模块,所以Spring整合Spring MVC只需在项目启动时分别加载各自的配置即可。

    14.1.2 项目基础结构搭建

    接下来,根据14.1.1中的整合思路搭建SSM框架整合的项目基础结构,具体如下所示。
    1.搭建数据库环境:在已有的spring数据库中创建一个名称为tb_book的表,并在tb_book表中插入数据。创建数据库和表,以及往表中插入数据的SQL语句如下所示。

    1. USE spring;
    2. CREATE TABLE `tb_book` (
    3. `id` INT(11) ,
    4. `name` VARCHAR(32) ,
    5. `press` VARCHAR(32) ,
    6. `author` VARCHAR(32) );
    7. INSERT INTO `tb_book` VALUES
    8. (1, 'Java EE企业级应用开发教程', '人民邮电出版社', '黑马程序员');

    2.创建一个MavenWeb项目,名称为chapter14SSM(创建过程参考第10章笔记);在pom.xml文件中引入项目依赖。
    (1)Spring相关依赖。

  • spring-context : Spring上下文;

  • spring-tx : Spring事务管理;
  • spring-jdbc : SpringJDBC;
  • spring-test : Spring单元测试;
  • spring-webmvc : Spring MVC核心。

(2)MyBatis相关依赖。mybatis : MyBatis核心;
(3)MyBatis与Spring整合包。mybatis-spring :MyBatis与Spring整合。
(4)数据源相关。druid : 阿里提供的数据库连接池。
(5)单元测试相关的依赖。junit : 单元测试,与spring-test放在一起做单元测试。
(6)ServletAPI相关的依赖。jsp-api : jsp页面使用request等对象;servlet-api : java文件使用request等对象。
(7)数据库相关的依赖。mysql-connector-java : mysql的数据库驱动包。

<?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>cn.edu.imust</groupId>
    <artifactId>chapter14SSM</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>chapter14 Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- Spring相关依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <!--Spring事务管理-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <!--Spring MVC的相关依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <!--MyBatis相关依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--MyBatis与Spring整合相关依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.1</version>
        </dependency>
        <!--数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <!--单元测试相关的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- 相关的依赖-->
        <!--ServletAPI:引入servlet的功能-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!--ServletAPI: jsp页面的功能包 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <!-- 数据库驱动相关依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>chapter14SSM</finalName>
        <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>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <configuration>
                        <port>8080</port>
                        <path>/chapter14SSM</path>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

3.在项目的src/main/java目录下,创建一个名为cn.edu.imust.domain的包;在该包中创建名称为Book的实体类。

package cn.edu.imust.domain;

public class Book {
    private Integer id;            //图书id
    private String name;        //图书名称
    private String press;        //出版社
    private String author;        //作者

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPress() {
        return press;
    }

    public void setPress(String press) {
        this.press = press;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

4.创建三层架构对应模块的类和接口:
(1)在项目的src/main/java目录下,创建一个名为cn.edu.imust.dao的包;在该包中创建名称为BookMapper的持久层接口,在BookMapper接口中定义findBookById()方法,通过图书id获取对应的图书信息。

package cn.edu.imust.dao;

import cn.edu.imust.domain.Book;

public interface BookMapper {
    public Book findBookById(Integer id);
}

(2)在项目的src/main/resources目录下,创建路径为cn/edu/imust/dao的文件夹;在该文件夹中创建BookMapper接口对应的映射文件BookMapper.xml。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.edu.imust.dao.BookMapper">
    <select id="findBookById" parameterType="int" resultType="cn.edu.imust.domain.Book">
        select * from tb_book where id = #{id}
    </select>
</mapper>

(3)在项目的src/main/java目录下,创建一个名为cn.edu.imust.service的包;在该包中创建名称为BookService的业务层接口,在BookService接口中定义findBookById()方法,通过id获取对应的Book信息。

package cn.edu.imust.service;

import cn.edu.imust.domain.Book;

public interface BookService {
    public Book findBookById(Integer id);
}

(4)在项目的src/main/java目录下,创建一个名为cn.edu.imust.service.impl的包;在该包中创建BookService接口的业务层实现类BookServiceImpl。BookServiceImpl类实现BookService接口的findBookById()方法。 并在类中注入一个BookMapper对象。findBookById()方法通过注入的BookMapper对象调用findBookById()方法,根据id查询对应的图书信息。

package cn.edu.imust.service.impl;

import cn.edu.imust.dao.BookMapper;
import cn.edu.imust.domain.Book;
import cn.edu.imust.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookMapper bookMapper;
    @Override
    public Book findBookById(Integer id) {
        return bookMapper.findBookById(id);
    }
}

(5)在项目的src/main/java目录下,创建一个名为cn.edu.imust.controller的包;在该包中创建名称为BookController的类。在BookController类中注入一个BookService对象,并且定义一个名称为findBookById()的方法。

package cn.edu.imust.controller;

import cn.edu.imust.domain.Book;
import cn.edu.imust.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class BookController {
    @Autowired
    private BookService bookService;

    @RequestMapping("/book")
    public ModelAndView findBookById(Integer id){
        Book book = bookService.findBookById(id);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("book.jsp");
        modelAndView.addObject("book",book);
        return modelAndView;
    }
}

至此,项目基础结构已经搭建完成,项目基础结构如图所示。
image.png

14.1.3 Spring和MyBatis整合

Spring和MyBatis的整合可以分为2步来完成,首先搭建Spring环境,然后整合MyBatis到Spring环境中
框架环境包含框架对应的依赖和配置文件,其中Spring的依赖、MyBatis的依赖、Spring和MyBatis整合的依赖,在项目基础结构搭建时候已经引入到项目中了,接下来,只需编写Spring的配置文件、Spring和MyBatis整合的配置文件即可。
1.Spring的配置文件
在项目的src/main/resources目录下,创建配置文件application-service.xml,用于配置Spring对Service层的扫描信息。application-service.xml具体代码如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
                  http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/context
                  http://www.springframework.org/schema/context/spring-context.xsd
           ">
    <!--开启注解扫描, 扫描包-->
    <context:component-scan base-package="cn.edu.imust.service"/>
</beans>

2.Spring和MyBatis整合的配置
Spring和MyBatis的整合包中提供了一个SqlSessionFactoryBean对象,该对象的Bean需要注入数据源,也可以根据需求在SqlSessionFactoryBean的Bean中配置MyBatis核心文件路径、别名映射和Mapper映射文件路径。
在项目的src/main/resources目录下,创建数据源属性文件jdbc.properties,jdbc.properties配置的数据源信息如下所示。

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring?useUnicode=true\
  &characterEncoding=utf-8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456

接下来,将MyBatis整合到Spring的环境中。在src\main\resources目录下创建配置文件application-dao.xml,用于配置Spring和MyBatis整合信息。
application-dao.xml中包含的内容如下:
(1)引入属性文件;
(2)配置数据源;
(3)创建SqlSessionFactory对象;
(4)配置包扫描。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
     ">
    <!-- 引入属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties" />
    <!-- 数据源 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!-- 创建SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 扫描Dao包,创建动态代理对象, 会自动存储到spring IOC容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定要扫描的dao的包 -->
        <property name="basePackage" value="cn.edu.imust.dao"/>
    </bean>
</beans>

3.整合测试:在项目的src/test目录下的java文件中,创建名称为BookServiceTest的测试类,用于对Spring和MyBatis的整合进行测试。

import cn.edu.imust.domain.Book;
import cn.edu.imust.service.BookService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-service.xml","classpath:application-dao.xml"})
public class BookServiceTest {
    @Autowired
    private BookService bookService;

    @Test
    public void findBookById(){
        Book book = bookService.findBookById(1);
        System.out.println("图书Id: " + book.getId());
        System.out.println("图书名称:" + book.getName());
        System.out.println("作者:" + book.getAuthor());
        System.out.println("出版社:" + book.getPress());
    }
}

运行测试方法findBookById(),方法运行后控制台打印信息如图所示。
image.png
从图中所示的信息可以看出,程序打印出了id为1的图书信息。这表明测试类中成功装配了BookService对象,BookService对象成功调用Service层的findBookById()方法,Service层的findBookById()方法成功调用Dao层的findBookById()方法完成了数据查询。说明Spring和MyBatis已经整合成功。

14.1.4 Spring和Spring MVC整合

1.Spring的配置
之前Spring和MyBatis整合时,已经完成了Spring的配置文件,Spring和Spring MVC整合,只需在项目启动时加载Spring容器和Spring的配置文件即可。
在项目的web.xml文件中配置Spring的监听器来加载Spring容器及Spring的配置文件,具体配置如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置文件加载-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application-*.xml</param-value>
    </context-param>
      <!--容器加载的监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
      <!--Spring MVC 前端控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
            <!--初始化参数-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
            <!--项目启动时候,初始化前端控制器-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

2.Spring MVC的配置
本案例主要测试SSM整合的情况,因此在Spring MVC的配置文件中只配置SSM整合案例必须的配置。必须配置的项有以下2个。
配置包扫描,指定需要扫描到Spring MVC中的Controller层所在的包路径。
配置注解驱动,让项目启动时启用注解驱动,并且自动注册HandlerMapping和HandlerAdapter。 在项目的src\main\resources目录下创建Spring MVC的配置文件spring-mvc.xml。Spring-mvc.xml文件配置完成之后,在web.xml中配置Spring MVC的前端控制器,并在初始化前端控制器时加载Spring MVC的配置文件。 (有关web.xml中的内容,在上一步的内容中已经添加)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/mvc
               http://www.springframework.org/schema/mvc/spring-mvc.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置要扫描的包 -->
    <context:component-scan base-package="cn.edu.imust.controller"/>
    <!-- 配置注解驱动 -->
    <mvc:annotation-driven/>
</beans>

3.SSM框架整合测试
(1)在项目的src/main/webapp目录下,创建名称为book.jsp的文件,用于展示处理器返回的图书信息。

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head><title>图书信息查询</title></head>
<body>
<table border="1">
    <tr>
        <th>图书id</th>
        <th>图书名称</th>
        <th>出版社</th>
        <th>作者</th>
    </tr>
    <tr>
        <td>${book.id}</td>
        <td>${book.name}</td>
        <td>${book.press}</td>
        <td>${book.author}</td>
    </tr>
</table>
</body>
</html>

(2)将chapter14项目部署到Tomcat中,启动项目,在浏览器中访问地址http://localhost:8080/chapter14SSM/book?id=1来进行图书查询,页面显示效果如图所示。
image.png
从图中所示的信息可以看出,程序成功查询到了id为1的图书信息。表明Controller层成功将Service层获取的图书信息返回给页面了,由此可以得出SSM框架整合成功。

14.2 纯注解方式整合SSM框架

14.2.1 整合思路

使用注解整合SSM框架,其实就是使用配置类替代原来XML配置文件在项目的作用。在14.1节中,使用XML配置文件完成了SSM框架整合;使用到的XML配置文件具体如下:
1.application-dao.xml
application-dao.xml配置文件中配置的内容包含以下4项。

  • 读取jdbc.properties文件中的数据连接信息。
  • 创建Druid对象,并将读取的数据连接信息注入到Druid数据连接池对象中。
  • 创建SqlSessionFactoryBean对象,将并将Druid对象注入到SqlSessionFactoryBean对象中。
  • 创建MapperScannerConfigurer对象,并指定扫描的Mapper的路径。

2.application-service.xml
application-service.xml配置文件中只配置了包扫描,指定需要扫描到Spring 的Service层所在的包路径。
3.spring-mvc.xml
spring-mvc.xml配置文件中配置了Spring MVC扫描的包路径和注解驱动。
4.web.xml
web.xml配置文件配置了项目启动时加载的信息,包含如下3个内容。

  • 使用元素加载Spring配置文件application-service.xml和Spring整合Mybatis的配置文件application-dao.xml。
  • Spring容器加载监听器。
  • 配置Spring MVC的前端控制器。

注:可以将以上文件删掉,或者将内容注释掉,来做如下案例内容,完成纯注解SSM框架整合。

14.2.2 纯注解SSM框架整合

接下来,将项目中的XML配置文件删除,使用纯注解的配置类依次替换对应的XML文件内容,以完成纯注解的SSM框架整合。具体实现步骤如下所示。
1.在项目的src\main\java目录下创建路径为cn.edu.imust.config的包,用于存放项目中的配置类。
在该包中创建名称为JdbcConfig的类,用于获取数据库连接信息并定义创建数据源的对象方法。
在JdbcConfig类中,通过@PropertySource注解读取jdbc.properties文件中的数据库连接信息,并定义getDataSource()方法,用于创建DruidDataSource对象, 通过DruidDataSource对象返回数据库连接信息。

package cn.edu.imust.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

/*
等同于<context:property-placeholder location="classpath*:jdbc.properties"/>
 */
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
    /*
    使用注入的形式,读取properties文件中的属性值,
    等同于<property name="*******" value="${jdbc.driver}"/>
     */
    @Value("${jdbc.driverClassName}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;

    /*定义dataSource的bean, 等同于
   <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    */
    @Bean("dataSource")
    public DataSource getDataSource(){
        //创建对象
        DruidDataSource ds = new DruidDataSource();
        /*
            等同于set属性注入<property name="driverClassName" value="driver"/>
             */
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

2.在cn.edu.imust.config包中创建名称为MyBatisConfig的类,在MyBatisConfig类中定义getSqlSessionFactoryBean()方法,用于创建SqlSessionFactoryBean对象并返回;定义getMapperScannerConfigurer()方法,用于创建getMapperScannerConfigurer对象并返回。

package cn.edu.imust.config;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class MyBatisConfig {
    /*
    定义MyBatis的核心连接工厂bean,
    等同于<bean class="org.mybatis.spring.SqlSessionFactoryBean">
     参数使用自动装配的形式加载dataSource,
    为set注入提供数据源,dataSource来源于JdbcConfig中的配置
     */
    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        //等同于<property name="dataSource" ref="dataSource"/>
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

    /*
    定义MyBatis的映射扫描,
    等同于<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
     */
    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        //等同于<property name="basePackage" value="cn.edu.imust.dao"/>
        msc.setBasePackage("cn.edu.imust.dao");
        return msc;
    }
}

3.在cn.edu.imust.config包中,创建名称为SpringConfig的类作为项目定义Bean的源头,并扫描Service层对应的包。

package cn.edu.imust.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
//将MyBatisConfig类和JdbcConfig类交给Spring管理
@Import({MyBatisConfig.class,JdbcConfig.class})
//等同于<context:component-scan base-package="cn.edu.imust.service">
@ComponentScan(value = "cn.edu.imust.service")
public class SpringConfig {
}

4.在cn.edu.imust.config包中,创建名称为SpringMvcConfig的类作为Spring MVC的配置类,在配置类中指定Controller层的扫描路径。

package cn.edu.imust.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
//等同于<context:component-scan base-package="cn.edu.imust.controller"/>
@ComponentScan("cn.edu.imust.controller")
//等同于<mvc:annotation-driven/>,还不完全相同
@EnableWebMvc
public class SpringMvcConfig {
}

5.在cn.edu.imust.config包中,创建名称为ServletContainersInitConfig的类,继承AbstractAnnotationConfigDispatcherServletInitializer抽象类,重写抽象类的方法。用于替代之前web.xml文件配置的信息 ,初始化Servlet容器时加载指定初始化的信息。

package cn.edu.imust.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class ServletContainersInitConfig extends
        AbstractAnnotationConfigDispatcherServletInitializer {
    /*
        加载Spring配置类中的信息,
        初始化Spring容器
    */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    /*
         加载Spring MVC配置类中的信息,
         初始化Spring MVC容器
    */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    //配置DispatcherServlet的映射路径
    @Override
    protected String[] getServletMappings() {
        System.out.println("纯注解方式整合SSM框架");
        return new String[]{"/"};
    }
}

至此,纯注解的SSM框架整合已经完成。
AbstractAnnotationConfigDispatcherServletInitializer抽象类
Spring提供了一个抽象类AbstractAnnotationConfigDispatcherServletInitializer,任意继承该抽象类的类都会在项目启动时自动创建DispatchServlet、初始化SpringMVC容器和Spring容器。
在项目中,可以通过继承该抽象类来设置DispatchServlet的映射路径,加载SpringMVC配置类到SpringMVC容器,并加载Spring配置类信息到Spring容器。
重写AbstractAnnotationConfigDispatcherServletInitializer抽象类的3个方法。

  • getRootConfigClasses()方法:将Spring配置类的信息加载到Spring容器中。
  • getServletConfigClasses()方法:将Spring MVC配置类的信息加载到Spring MVC容器中。
  • getServletMappings()方法:可以指定DispatcherServlet的映射路径。

6.启动项目,在浏览器中访问图书信息查询地址,地址为http://localhost:8080/chapter14SSM/book?id=1,页面显示效果如图所示。
image.png
image.png