1. 背景

  • 需求
    • 利用 SSM(SpringMVC+Spring+Mybatis) 框架实现 account表 的“查询所有用户”和“保存用户”功能;
  • 环境
    • jdb 版本:jdk1.8.0_131;
    • IDE 工具:IntelliJ IDEA 2019.3 community;
    • Tomcat:apache-tomcat-9.0.21,利用插件 Smart Tomcat 与 IDE 的集成(社区版限制);
    • Maven:apache-maven-3.6.1;
  • 思路:
    • 先撘 spring,然后撘 springmvc 并整合 spring + springmvc,再撘 mybatis 并整合 spring + mybatis,最终进行集成测试;
  • jar 包准备(配置 pom.xml)

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0</modelVersion>
    5. <groupId>cn.tjufe</groupId>
    6. <artifactId>springmvc_1</artifactId>
    7. <version>1.0-SNAPSHOT</version>
    8. <packaging>war</packaging>
    9. <name>springmvc_1 Maven Webapp</name>
    10. <!-- FIXME change it to the project's website -->
    11. <url>http://www.example.com</url>
    12. <!--版本锁定-->
    13. <properties>
    14. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    15. <maven.compiler.source>1.8</maven.compiler.source>
    16. <maven.compiler.target>1.8</maven.compiler.target>
    17. <spring.version>5.0.2.RELEASE</spring.version>
    18. <slf4j.version>1.6.6</slf4j.version>
    19. <log4j.version>1.2.12</log4j.version>
    20. <mysql.version>5.1.6</mysql.version>
    21. <mybatis.version>3.4.5</mybatis.version>
    22. </properties>
    23. <dependencies>
    24. <!--1. spring相关的依赖包-->
    25. <dependency>
    26. <groupId>org.aspectj</groupId>
    27. <artifactId>aspectjweaver</artifactId>
    28. <version>1.6.8</version>
    29. </dependency>
    30. <dependency>
    31. <groupId>org.springframework</groupId>
    32. <artifactId>spring-aop</artifactId><!--spring切面-->
    33. <version>${spring.version}</version>
    34. </dependency>
    35. <dependency>
    36. <groupId>org.springframework</groupId>
    37. <artifactId>spring-context</artifactId><!--spring上下文-->
    38. <version>${spring.version}</version>
    39. </dependency>
    40. <dependency>
    41. <groupId>org.springframework</groupId>
    42. <artifactId>spring-web</artifactId><!--提供contextLoaderListener类实现spring+springmvc-->
    43. <version>${spring.version}</version>
    44. </dependency>
    45. <dependency>
    46. <groupId>org.springframework</groupId>
    47. <artifactId>spring-webmvc</artifactId>
    48. <version>${spring.version}</version>
    49. </dependency>
    50. <dependency>
    51. <groupId>org.springframework</groupId>
    52. <artifactId>spring-tx</artifactId><!--spring事务管理-->
    53. <version>${spring.version}</version>
    54. </dependency>
    55. <dependency>
    56. <groupId>org.springframework</groupId>
    57. <artifactId>spring-jdbc</artifactId><!--spring操作数据库-->
    58. <version>${spring.version}</version>
    59. </dependency>
    60. </dependency>
    61. <!--2. springmvc相关依赖包-->
    62. <dependency>
    63. <groupId>javax.servlet</groupId>
    64. <artifactId>servlet-api</artifactId>
    65. <version>2.5</version>
    66. <scope>provided</scope>
    67. </dependency>
    68. <dependency>
    69. <groupId>javax.servlet.jsp</groupId>
    70. <artifactId>jsp-api</artifactId>
    71. <version>2.0</version>
    72. <scope>provided</scope>
    73. </dependency>
    74. <dependency>
    75. <groupId>jstl</groupId>
    76. <artifactId>jstl</artifactId><!--JSP标准标签库-->
    77. <version>1.2</version>
    78. </dependency>
    79. <!--3. mybatis相关的依赖包-->
    80. <dependency>
    81. <groupId>org.mybatis</groupId>
    82. <artifactId>mybatis</artifactId>
    83. <version>${mybatis.version}</version>
    84. </dependency>
    85. <dependency>
    86. <groupId>org.mybatis</groupId>
    87. <artifactId>mybatis-spring</artifactId><!--支持springmybatis集成-->
    88. <version>1.3.0</version>
    89. </dependency>
    90. <dependency>
    91. <groupId>c3p0</groupId>
    92. <artifactId>c3p0</artifactId><!--数据连接池-->
    93. <version>0.9.1.2</version>
    94. <type>jar</type>
    95. <scope>compile</scope>
    96. </dependency>
    97. <!--4. spring单元测试-->
    98. <dependency>
    99. <groupId>org.springframework</groupId>
    100. <artifactId>spring-test</artifactId>
    101. <version>${spring.version}</version>
    102. <scope>compile</scope>
    103. </dependency>
    104. <dependency>
    105. <groupId>junit</groupId>
    106. <artifactId>junit</artifactId>
    107. <version>4.12</version>
    108. <scope>compile</scope>
    109. </dependency>
    110. <dependency>
    111. <groupId>mysql</groupId>
    112. <artifactId>mysql-connector-java</artifactId>
    113. <version>${mysql.version}</version>
    114. </dependency>
    115. <!--5. 打印log-->
    116. <dependency>
    117. <groupId>log4j</groupId>
    118. <artifactId>log4j</artifactId>
    119. <version>${log4j.version}</version>
    120. </dependency>
    121. <dependency>
    122. <groupId>org.slf4j</groupId>
    123. <artifactId>slf4j-api</artifactId>
    124. <version>${slf4j.version}</version>
    125. </dependency>
    126. <dependency>
    127. <groupId>org.slf4j</groupId>
    128. <artifactId>slf4j-log4j12</artifactId>
    129. <version>${slf4j.version}</version>
    130. </dependency>
    131. <!--6. json解析-->
    132. <dependency>
    133. <groupId>com.fasterxml.jackson.core</groupId>
    134. <artifactId>jackson-databind</artifactId>
    135. <version>2.9.0</version>
    136. </dependency>
    137. <dependency>
    138. <groupId>com.fasterxml.jackson.core</groupId>
    139. <artifactId>jackson-core</artifactId>
    140. <version>2.9.0</version>
    141. </dependency>
    142. <dependency>
    143. <groupId>com.fasterxml.jackson.core</groupId>
    144. <artifactId>jackson-annotations</artifactId>
    145. <version>2.9.0</version>
    146. </dependency>
    147. </dependencies>
    148. <build>
    149. <finalName>springmvc_day01_01_start</finalName>
    150. <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
    151. <plugins>
    152. <plugin>
    153. <artifactId>maven-clean-plugin</artifactId>
    154. <version>3.0.0</version>
    155. </plugin>
    156. <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
    157. <plugin>
    158. <artifactId>maven-resources-plugin</artifactId>
    159. <version>3.0.2</version>
    160. </plugin>
    161. <plugin>
    162. <artifactId>maven-compiler-plugin</artifactId>
    163. <version>3.7.0</version>
    164. </plugin>
    165. <plugin>
    166. <artifactId>maven-surefire-plugin</artifactId>
    167. <version>2.20.1</version>
    168. </plugin>
    169. <plugin>
    170. <artifactId>maven-war-plugin</artifactId>
    171. <version>3.2.0</version>
    172. </plugin>
    173. <plugin>
    174. <artifactId>maven-install-plugin</artifactId>
    175. <version>2.5.2</version>
    176. </plugin>
    177. <plugin>
    178. <artifactId>maven-deploy-plugin</artifactId>
    179. <version>2.8.2</version>
    180. </plugin>
    181. </plugins>
    182. </pluginManagement>
    183. </build>
    184. </project>

    2. 实现

  • 目录安排

mvc1.png

2.1 配置一:springmvc 与 spring 整合

  • 需要配置 springmvc.xml、applicationContext.xml 和 web.xml,并在 web.xml 配置 springmvc.xml 和 applicationContext.xml 的匹配路径;
  • springmvc.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"
         xmlns:mvc="http://www.springframework.org/schema/mvc"
         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-4.1.xsd
         http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
    
      <!-- 包扫描 -->
      <context:component-scan base-package="cn.tjufe">
          <!--只扫描 controller 下的包-->
          <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
    
      <!-- 视图解析器对象-->
      <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          <property name="prefix" value="/WEB-INF/pages/"></property>
          <property name="suffix" value=".jsp"></property>
      </bean>
    
      <!--设置静态资源过滤器,哪些静态资源不拦截-->
      <mvc:resources mapping="/js/**" location="/js/"/>
      <mvc:resources mapping="/css/**" location="/css/"/>
      <mvc:resources mapping="/images/**" location="/images/"/>
    
      <!--开启 SpringMVC 框架注解的支持-->
      <mvc:annotation-driven/>
    </beans>
    
  • applicationContext.xml(后续与 mybatis 的再补充)

    <?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"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-4.2.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
    
      <!--开启注解的扫描,只处理 dao 和 service,controller 交给 springmvc.xml-->
      <context:component-scan base-package="cn.tjufe">
          <!--配置哪些注解不扫描-->
          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
    
      <!--spring整合mybatis框架在2.2有补充-->
    </beans>
    
  • web.xml(配置 springmvc.xml 和 applicationContext.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!--配置解决中文乱码的过滤器-->
    <filter>
      <filter-name>characterEncodingFilter</filter-name>
      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
      <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
      </init-param>
    </filter>
    <filter-mapping>
      <filter-name>characterEncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!--1. 配置 spring 的监听器实现spring与springmvc整合,注意:默认加载路径为WEB-INF 下的 applicationContext.xml-->
    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContext.xml</param-value><!--配置监听器的文件路径在系统路径下-->
    </context-param>
    <!--2. 配置dispatcherServlet并说明springmvc.xml的配置路径-->
    <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:springmvc.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.2 配置二:mybatis 与 spring 整合

    <?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"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-4.2.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
    
      <!--开启注解的扫描,只处理 dao 和 service,controller 交给 springmvc.xml-->
      <context:component-scan base-package="cn.tjufe">
          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      </context:component-scan>
    
      <!--spring整合mybatis框架,实际上此部分有 SqlMapConfig.xml 和 MyTest.testMybatis 的东西整合而成-->
      <!--配置连接池,注意!!!! property 的 name 不能修改,否则会使容器创建不成功-->
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
          <property name="driverClass" value="com.mysql.jdbc.Driver"/>
          <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test_jdbc"/>
          <property name="user" value="root"/>
          <property name="password" value="1234"/>
      </bean>
      <!--配置SqlSessionFactory-->
      <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource"/>
      </bean>
      <!--配置AccountDao接口所在包-->
      <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
          <property name="basePackage" value="cn.tjufe.dao"/>
      </bean>
    
      <!--配置spring框架声明式事务管理-->
      <!--配置事务管理器-->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource"/>
      </bean>
      <!--配置事务通知-->
      <tx:advice id="txAdvice" transaction-manager="transactionManager">
          <tx:attributes>
              <tx:method name="find" read-only="true"/>
              <tx:method name="*" isolation="DEFAULT"/>
          </tx:attributes>
      </tx:advice>
      <!--配置AOP增强-->
      <aop:config>
          <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.tjufe.Service.impl.*ServiceImpl.*(..))"/>
      </aop:config>
    </beans>
    

    2.3 代码

    2.3.1 springmvc 相关代码

  • 示意图

mvc1.png

  • controller 代码
    • 注意:saveAccount 由于返回值为 void,所以需进行转发或重定向,否则会报错 ```java package cn.tjufe.controller;

import cn.tjufe.Service.IAccountService; import cn.tjufe.domain.Account2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List;

@Controller @RequestMapping(“/account/“) public class AccountController {

@Autowired
private IAccountService accountService;//实现 service 的注入

@RequestMapping("findAllAccount")
public String findAllAccount(Model model){
    System.out.println("表现层:查询所有账户信息...");
    List<Account2> accounts = accountService.findAllAccount();
    model.addAttribute("accountList",accounts);
    return "success";
}

@RequestMapping("saveAccount")
public void saveAccount(Account2 account, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("表现层:保存账户信息...");
    accountService.saveAccount(account);
    response.sendRedirect(request.getContextPath()+"/account/findAllAccount");
    return;
}

}


- union.jsp
```java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="account/findAllAccount">查询所有账户</a>
    <br/>
    <h3>保存账户</h3>
    <form action="account/saveAccount" method="post">
        用户ID: <input type="text" name="id"/><br/>
        姓名: <input type="text" name="name"/><br/>
        金额: <input type="text" name="money"/><br/>
        <input type="submit" value="保存"/>
    </form>
</body>
</html>
  • success.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
      <title>Title</title>
    </head>
    <body>
      <h3>SSM 整合练习</h3>
      <h4>获取到所有账户信息</h4>
      <c:forEach items="${accountList}" var="account">
          ${account.name}
      </c:forEach>
    </body>
    </html>
    

    2.3.2 spring 代码+ mybatis 注解

  • 示意图

mvc1.png

  • service 层代码 ```java // service 接口 package cn.tjufe.Service;

import cn.tjufe.domain.Account2; import java.util.List;

public interface IAccountService {

public List<Account2> findAllAccount();
public void saveAccount(Account2 account);

} // serviceImpl package cn.tjufe.Service.impl;

import cn.tjufe.Service.IAccountService; import cn.tjufe.dao.AccountDao; import cn.tjufe.domain.Account2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;

import java.util.List;

@Service(“accountService”) public class AccountServiceImpl implements IAccountService { @Autowired private AccountDao accountDao;//实现spring和mybatis整合之后,可将dao对象注入

@Override
public List<Account2> findAllAccount() {
    System.out.println("业务层: 查询所有账户信息...");
    return accountDao.findAllAccount();
}

@Override
public void saveAccount(Account2 account) {
    System.out.println("业务层: 保存账户信息...");
    accountDao.saveAccount(account);
}

}


- dao 层代码
```java
package cn.tjufe.dao;

import cn.tjufe.domain.Account2;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository("accountDao")
public interface AccountDao {
    /**
     * 查询所有账户
     */
    @Select("select * from account")
    public List<Account2> findAllAccount();

    /**
     * 保存账户信息
     */
    @Insert("insert into account(id,name,balance) values(#{id}, #{name}, #{balance})")
    public void saveAccount(Account2 account);
}

2.3 补充-其他配置内容

  • log.properties 的简单配置 ```java

    Set root category priority to INFO and its only appender to CONSOLE.

    log4j.rootCategory=INFO, CONSOLE debug info warn error fatal

    log4j.rootCategory=debug, CONSOLE, LOGFILE

Set the enterprise logger category to FATAL and its only appender to CONSOLE.

log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

CONSOLE is set to be a ConsoleAppender using a PatternLayout.

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

LOGFILE is set to be a File appender using a PatternLayout.

log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=d:\axis.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n ```

2.4 结果

  • 查询所有用户

mvc1.png

  • 保存用户

mvc1.png

2.5 异常记录

  • applicationContext.xml 中

mvc1.png
image.png

2.6 待优化

  • applicationContext.xml 中有关数据库的配置信息可单独写一个 properties 出来

image.png

3. 总结

  • 所谓的整合就是容器嵌套
  • 实现容器整合之后,才能实现bean的注入