1.SSM集成框架

1.1.SSM集成框架简介

1.1.1.为什么要使用SSM集成框架

时至今日,MVC三层架构仍然是我们开发应用程序时所采用的主流架构模式,而 SpringMVC 就是一款优秀的 MVC 框架。那么,为什么我们仍然要将 SpringMVC 与 Spring、MyBatis 集成在一起使用呢。
首先,SpringMVC 对持久层没有任何支持,所以持久层需要使用 MyBatis。其次,为了将 SpringMVC 和 MyBatis 所需组件解耦,需要由 Spring 为其注入。这就是为什么要 SSM 集成的原因。

1.1.2.SSM集成分析

简单来说:SSM集成就是使用 Spring 给 SpringMVC 和 MyBatis 注入所需要组件。
具体来说:SSM集成就是:

  1. 由 SpringMVC 负责搭建 MVC 架构,由 MyBatis 负责持久层。
  2. 由 Spring 给 SpringMVC 注入控制层组件、业务层组件、数据层组件等。
  3. 由 Spring 给 MyBatis 注入数据源、SqlSessionFactory、事务等。

    1.2.SSM集成

    1.2.1.创建Maven工程并添加依赖

    02.SSM集成 - 图1
    在pom.xml文件中添加如下依赖
    1. <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    2. <modelVersion>4.0.0</modelVersion>
    3. <groupId>com.neusoft</groupId>
    4. <artifactId>ssm</artifactId>
    5. <version>0.0.1-SNAPSHOT</version>
    6. <packaging>war</packaging>
    7. <!-- 添加项目jdk编译插件 -->
    8. <build>
    9. <plugins>
    10. <!-- 设置jdk版本 -->
    11. <plugin>
    12. <groupId>org.apache.maven.plugins</groupId>
    13. <artifactId>maven-compiler-plugin</artifactId>
    14. <configuration>
    15. <source>1.8</source>
    16. <target>1.8</target>
    17. <encoding>utf-8</encoding>
    18. </configuration>
    19. </plugin>
    20. </plugins>
    21. </build>
    22. <properties>
    23. <spring.version>5.2.8.RELEASE</spring.version>
    24. </properties>
    25. <dependencies>
    26. <!-- 此依赖会关联引用Spring中的所有基础jar包 -->
    27. <dependency>
    28. <groupId>org.springframework</groupId>
    29. <artifactId>spring-context</artifactId>
    30. <version>${spring.version}</version>
    31. </dependency>
    32. <!-- SpringMVC的jar包 (会依赖spring-web)-->
    33. <dependency>
    34. <groupId>org.springframework</groupId>
    35. <artifactId>spring-webmvc</artifactId>
    36. <version>${spring.version}</version>
    37. </dependency>
    38. <!-- Spring支持jdbc的jar包(会依赖 spring-tx事务jar包) -->
    39. <dependency>
    40. <groupId>org.springframework</groupId>
    41. <artifactId>spring-jdbc</artifactId>
    42. <version>${spring.version}</version>
    43. </dependency>
    44. <!-- aspectj依赖jar包 -->
    45. <dependency>
    46. <groupId>org.aspectj</groupId>
    47. <artifactId>aspectjweaver</artifactId>
    48. <version>1.8.7</version>
    49. </dependency>
    50. <!-- jackson依赖jar包 -->
    51. <dependency>
    52. <groupId>com.fasterxml.jackson.core</groupId>
    53. <artifactId>jackson-databind</artifactId>
    54. <version>2.9.0</version>
    55. </dependency>
    56. <!--mybatis 依赖包 -->
    57. <dependency>
    58. <groupId>org.mybatis</groupId>
    59. <artifactId>mybatis</artifactId>
    60. <version>3.5.1</version>
    61. </dependency>
    62. <!-- mybatis-spring 依赖包 -->
    63. <dependency>
    64. <groupId>org.mybatis</groupId>
    65. <artifactId>mybatis-spring</artifactId>
    66. <version>2.0.0</version>
    67. </dependency>
    68. <!-- mysql驱动 依赖包 -->
    69. <dependency>
    70. <groupId>mysql</groupId>
    71. <artifactId>mysql-connector-java</artifactId>
    72. <version>5.1.6</version>
    73. </dependency>
    74. </dependencies>
    75. </project>

    1.2.2.加载Spring容器

    在Web项目中,如果每次请求时都要读取 Spring 配置文件并加载 Spring 容器,将会很耗费资源。所以我们要在服务器启动时,就加载 Spring 容器。
    所以,我们可以在 ServletContext 监听器中监听 服务器启动,然后加载 Spring 容器。而且,这个监听器 Spring已经做好了,我们只要在 web.xml 文件中配置即可。
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
    3. <!-- Spring整合web项目用的ServletContext监听器 -->
    4. <listener>
    5. <listener-class>
    6. org.springframework.web.context.ContextLoaderListener
    7. </listener-class>
    8. </listener>
    9. <!-- 指定spring配置文件路径,默认加载 /WEB-INF/applicationContext.xml -->
    10. <context-param>
    11. <param-name>contextConfigLocation</param-name>
    12. <param-value>classpath:applicationContext.xml</param-value>
    13. </context-param>
    14. </web-app>

    1.2.3.创建Spring容器

    创建applicationContext.xml 配置文件,也就是 Spring 容器。
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans
    3. xmlns="http://www.springframework.org/schema/beans"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xmlns:tx="http://www.springframework.org/schema/tx"
    6. xmlns:aop="http://www.springframework.org/schema/aop"
    7. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    8. xsi:schemaLocation="http://www.springframework.org/schema/beans
    9. http://www.springframework.org/schema/beans/spring-beans.xsd
    10. http://www.springframework.org/schema/context
    11. http://www.springframework.org/schema/context/spring-context.xsd
    12. http://www.springframework.org/schema/tx
    13. http://www.springframework.org/schema/tx/spring-tx.xsd
    14. http://www.springframework.org/schema/aop
    15. http://www.springframework.org/schema/aop/spring-aop.xsd">
    16. <!-- 后面会陆续的添加内容 -->
    17. </beans>

    1.2.4.集成MyBatis

    1.2.4.1.创建Mapper接口

    1. package com.neusoft.ssm.mapper;
    2. import org.apache.ibatis.annotations.Mapper;
    3. import com.neusoft.ssm.po.Dept;
    4. @Mapper
    5. public interface DeptMapper {
    6. public Dept getDeptById(Integer deptno);
    7. }

    注意:Mapper接口需要使用 @Mapper 注解

1.2.4.2.创建映射文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  4. <mapper namespace="com.neusoft.ssm.mapper.DeptMapper">
  5. <select id="getDeptById" parameterType="int" resultType="Dept">
  6. select * from dept where deptno=#{deptno}
  7. </select>
  8. </mapper>

1.2.4.3.在Spring容器中配置MyBatis

  1. jdbc.driver=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://localhost:3306/emp?characterEncoding=utf-8
  3. jdbc.username=root
  4. jdbc.password=123
  1. <!-- 引入db配置文件 -->
  2. <context:property-placeholder location="classpath:db.properties" />
  3. <!-- 配置dataSource数据源 -->
  4. <bean id="dataSource"
  5. class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  6. <property name="driverClassName" value="${jdbc.driver}"></property>
  7. <property name="url" value="${jdbc.url}"></property>
  8. <property name="username" value="${jdbc.username}"></property>
  9. <property name="password" value="${jdbc.password}"></property>
  10. </bean>
  11. <!-- 创建SqlSessionFactory,并配置实体对象别名 -->
  12. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  13. <property name="dataSource" ref="dataSource"></property>
  14. <property name="typeAliasesPackage" value="com.neusoft.ssm.po" />
  15. </bean>
  16. <!-- 配置Mapper。自动扫描Mapper接口,并为其注入SqlSessionFactory -->
  17. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  18. <property name="basePackage" value="com.neusoft.ssm.mapper"></property>
  19. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
  20. </bean>
  21. <!-- 配置Spring提供的事务管理器 -->
  22. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  23. <property name="dataSource" ref="dataSource"></property>
  24. </bean>
  25. <!-- 开启注解事务 -->
  26. <tx:annotation-driven transaction-manager="transactionManager"/>

1.2.5.集成SpringMVC

实际上,Spring 框架中包含 SpringMVC ,所以 SpringMVC 本身不需要集成。所以,下面除了做SpringMVC的相关配置外,主要是注入 service 组件。

1.2.5.1.配置SpringMVC前端控制器

  1. <servlet>
  2. <servlet-name>springmvc</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <init-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>classpath:springmvc-servlet.xml</param-value>
  7. </init-param>
  8. </servlet>
  9. <servlet-mapping>
  10. <servlet-name>springmvc</servlet-name>
  11. <url-pattern>/</url-pattern>
  12. </servlet-mapping>

1.2.5.2.创建SpringMVC配置文件

创建springmvc-servlet.xml 配置文件,也就是 SpringMVC的配置文件。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:context="http://www.springframework.org/schema/context"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:mvc="http://www.springframework.org/schema/mvc"
  6. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context.xsd
  11. http://www.springframework.org/schema/aop
  12. http://www.springframework.org/schema/aop/spring-aop.xsd
  13. http://www.springframework.org/schema/mvc
  14. http://www.springframework.org/schema/mvc/spring-mvc.xsd">
  15. <mvc:annotation-driven />
  16. <context:component-scan base-package="com.neusoft.ssm.controller" />
  17. </beans>

1.2.5.3.创建service组件

  1. package com.neusoft.ssm.service;
  2. import com.neusoft.ssm.po.Dept;
  3. public interface DeptService {
  4. public Dept getDeptById(Integer deptno);
  5. }
  1. package com.neusoft.ssm.service.impl;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.transaction.annotation.Transactional;
  5. import com.neusoft.ssm.mapper.DeptMapper;
  6. import com.neusoft.ssm.po.Dept;
  7. import com.neusoft.ssm.service.DeptService;
  8. @Service
  9. public class DeptServiceImpl implements DeptService{
  10. @Autowired
  11. private DeptMapper deptMapper;
  12. @Override
  13. @Transactional
  14. public Dept getDeptById(Integer deptno) {
  15. return deptMapper.getDeptById(deptno);
  16. }
  17. }

注意:

  1. 使用 @Service 注解标识这是一个 service 组件。
  2. 使用 @Autowired 注解自动注入 mapper 组件。

1.2.5.3.创建SpringMVC处理器

  1. package com.neusoft.ssm.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.ResponseBody;
  6. import com.neusoft.ssm.po.Dept;
  7. import com.neusoft.ssm.service.DeptService;
  8. @Controller
  9. public class DeptController {
  10. @Autowired
  11. private DeptService deptService;
  12. @ResponseBody
  13. @RequestMapping("/getDeptById")
  14. public Dept getDeptById(Integer deptno) throws Exception{
  15. return deptService.getDeptById(deptno);
  16. }
  17. }

注意:使用 @Autowired 注解注入 service 组件。

1.2.5.4.在Spring容器中添加service组件

  1. <context:component-scan base-package="com.neusoft.ssm.service" />

1.2.6.测试

至此,SSM集成完毕。整个工程的目录结构如下:
02.SSM集成 - 图2
接下来,将此工程部署在Tomcat中,启动Tomcat,在浏览器地址栏中输入:http://localhost:8080/ssm/getDeptById?deptno=10 进行测试。

1.2.7.SSM中两个Spring容器的总结

  1. springmvc-servlet.xml:这是SpringMVC框架的专用Spring容器。所以这里只写与SpringMVC相关组件的配置。
  2. applicationContext.xml:这是整个工程的Spring容器。所以,除了SpringMVC之外的其它组件,都要配置在这里。比如:dao、service、事务等等。

  3. 2.纯注解式SSM集成

    时下还是非常流行注解方式编程的,那么下面就使用纯注解的方式实现SSM集成。
    所谓纯注解方式就是:除了pom.xml文件外,工程中没有任何一个配置文件。

    2.1.创建Maven工程并添加依赖

    pom.xml文件中的内容同上。只是添加一个servlet-api的依赖即可:

    1. <project>
    2. <!-- 同上 -->
    3. <dependencies>
    4. <!-- 同上 -->
    5. <!-- 增加servlet-api依赖 -->
    6. <dependency>
    7. <groupId>javax.servlet</groupId>
    8. <artifactId>javax.servlet-api</artifactId>
    9. <version>4.0.0</version>
    10. <scope>provided</scope>
    11. </dependency>
    12. </dependencies>
    13. </project>

    2.2.创建工程总配置类

    在类路径下创建AppInitializer.java文件

    1. package com.neusoft.ssma;
    2. import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    3. public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
    4. /**
    5. * 返回一个带有@Configuration注解的类。
    6. * 用来创建整个应用程序的全局Spring容器。
    7. * 也就是等同于创建applicationContext.xml容器
    8. */
    9. @Override
    10. protected Class<?>[] getRootConfigClasses() {
    11. return new Class[] {RootConfig.class};
    12. }
    13. /**
    14. * 返回一个带有@Configuration注解的类。
    15. * 用来创建SpringMVC(即Web相关)的Spring容器。
    16. * 也就是等同于创建springmvc-servlet.xml容器
    17. */
    18. @Override
    19. protected Class<?>[] getServletConfigClasses() {
    20. return new Class[] {WebConfig.class};
    21. }
    22. //配置SpringMVC前端控制器映射路径
    23. @Override
    24. protected String[] getServletMappings() {
    25. return new String[] {"/"};
    26. }
    27. }

    在servlet3.0以上环境中,web容器会在类路径中查找实现了javax.servlet.ServletContainerInitializer接口的类,如果能找到此类就会用它来配置Servlet容器。
    Spring3.2之后,提供了这个接口的实现,它是一个抽象类:AbstractAnnotationConfigDispatcherServletInitializer。
    要实现AbstractAnnotationConfigDispatcherServletInitializer的三个抽象方法:

  4. getRootConfigClasses:用来创建整个应用程序的全局Spring容器(等同于applicationContext.xml)。

  5. getServletConfigClasses:用来创建SpringMVC(即Web相关)的Spring容器。(等同于springmvc-servlet.xml)
  6. getServletMappings:配置SpringMVC前端控制器映射路径(SpringMVC前端控制器已自动注入)。

    总结:AppInitializer.java就相当于:web.xml + applicationContext.xml + springmvc-servlet.xml

2.3.创建Spring容器配置类

在类路径下创建RootConfig.java文件,它就相当于applicationContext.xml。

  1. package com.neusoft.ssma;
  2. import javax.sql.DataSource;
  3. import org.mybatis.spring.SqlSessionFactoryBean;
  4. import org.mybatis.spring.annotation.MapperScan;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.ComponentScan;
  7. import org.springframework.context.annotation.Configuration;
  8. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  9. import org.springframework.jdbc.datasource.DriverManagerDataSource;
  10. import org.springframework.transaction.PlatformTransactionManager;
  11. @Configuration
  12. //@ComponentScan用于扫描通用组件,这里用来扫描Service组件
  13. @ComponentScan(basePackages={"com.neusoft.ssma.service"})
  14. //@MapperScan用于扫描Mapper组件
  15. @MapperScan(basePackages="com.neusoft.ssma.mapper")
  16. public class RootConfig {
  17. //创建dataSource组件并放入Spring容器
  18. @Bean
  19. public DataSource dataSource() {
  20. DriverManagerDataSource dataSource = new DriverManagerDataSource();
  21. dataSource.setDriverClassName("com.mysql.jdbc.Driver");
  22. dataSource.setUrl("jdbc:mysql://localhost:3306/emp?characterEncoding=utf-8");
  23. dataSource.setUsername("root");
  24. dataSource.setPassword("123");
  25. return dataSource;
  26. }
  27. //创建SqlSessionFactory组件并放入Spring容器
  28. @Bean
  29. public SqlSessionFactoryBean sqlSessionFactoryBean(){
  30. SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
  31. sqlSessionFactoryBean.setDataSource(dataSource());
  32. return sqlSessionFactoryBean;
  33. }
  34. //创建PlatformTransactionManager组件并放入Spring容器
  35. @Bean
  36. public PlatformTransactionManager transactionManager(DataSource dataSource){
  37. //dataSource也可以通过参数注入
  38. return new DataSourceTransactionManager(dataSource());
  39. }
  40. }

2.4.创建Web相关Spring容器

在类路径下创建WebConfig.java文件,它就相当于springmvc-servlet.xml。

  1. package com.neusoft.ssma;
  2. import org.springframework.context.annotation.ComponentScan;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  5. @Configuration
  6. //SpringMVC注解,等同于<mvc:annotation-driven/>
  7. @EnableWebMvc
  8. //@ComponentScan用于扫描通用组件,这里用来扫描Controller组件
  9. @ComponentScan(basePackages={"com.neusoft.ssma.controller"})
  10. public class WebConfig{ }

2.5.创建其它组件

Controller组件、Service组件、Mapper组件同上,没有任何变化。

2.6.测试

至此,纯注解式SSM集成完毕。整个工程的目录结构如下:
02.SSM集成 - 图3
接下来,将此工程部署在Tomcat中,启动Tomcat,在浏览器地址栏中输入:http://localhost:8080/ssm/getDeptById?deptno=10 进行测试。

3.注解和XML

  • 注解:是一种分散式的元数据,与源代码紧绑定。
  • xml:是一种集中式的元数据,与源代码无绑定。

    元数据:描述数据的数据

3.1.XML的优点与缺点

  1. 优点:
    • xml是集中式的元数据,不需要和代码绑定的
    • 更具有扩展性。修改配置时只需要修改xml即可,不需要对现有的程序进行修改
    • 组件之间的关系一目了然
    • 有成熟的校验机制来保证正确。比如使用Schema或者是DTD来对xml的正确性进行校验
  2. 缺点:

    • 需要解析xml的工具或者是是第三方类库的支持
    • 解析xml的时候必然会占用资源,势必会影响到应用程序的性能
    • xml配置文件过多,会导致维护变得困难
    • 在程序编译期间无法对其配置项的正确性进行验证,只能在运行期发现

      3.2.注解的优点与缺点

  3. 优点:

    • 简化了XML配置,使用起来更直观
    • 类型安全,编译期即可验证正确性。XML只能在运行期才能发现问题
    • 只维护代码即可,不用再维护其它文件
  4. 缺点:

    • 注解分散到很多类中,不好管理和维护
    • 注解的开启/关闭必须修改源代码,因为注解是源代码绑定的
    • 在实现复杂的逻辑上,没有XML功能强大

      3.3.总结

      首先,不管使用注解还是XML,做的事情还是那些事情。而且注解和XML都各有各的优点和缺点,所以,能够满足自己的需求,且以一种自己认为简单的方式解决掉问题即可。
      其次,虽然Spring官方没有明说抛弃xml配置,不过事实上Spring已经转往注解配置方向前进了,SpringBoot就是最好的例子。
      SpringBoot中只有一个properties文件负责配置一些不可避免的设定,除此之外没有任何一个xml文件来定义bean,全部都是使用注解来配置。

      本章作业
  5. Spring 在SSM中起什么作用?

  6. 在SSM中还需要MyBatis配置文件吗?
  7. SSM中两个Spring容器的作用分别是什么?
  8. 什么是纯注解式SSM集成?
  9. 在纯注解式SSM集成中的配置入口是什么?
  10. AbstractAnnotationConfigDispatcherServletInitializer的三个抽象方法的作用是什么?
  11. 到底是使用xml配置方式,还是纯注解式来实现SSM集成?
  12. 编程题:
    1. 使用SSM集成框架实现一个登录案例。
    2. 使用前后端分离的模式实现。
    3. 服务器端要有数据层组件、业务层组件、控制层组件。
    4. 数据层组件使用MyBatis框架完成对数据库的操作。
    5. 控制层组件要向前端返回json数据。
    6. 前端使用ajax请求,并通过服务器端返回的json数据来判断是否登录成功。