https://www.bilibili.com/video/BV1Sb411s7qa 
P46~54
 
三层架构 
 
先保证每个框架能单独运行
然后用Spring整合另外2个
准备数据库 account表,以前建过了,继续用
 
搭建环境 创建Maven工程,选webapp
解决创建项目过慢,加一对archetypeCatalog:internal
pom.xml 版本锁定
1 2 3 4 5 6 7 8 9 10 <properties >   <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding >    <maven.compiler.source > 1.8</maven.compiler.source >    <maven.compiler.target > 1.8</maven.compiler.target >    <spring.version > 5.0.2.RELEASE</spring.version >    <slf4j.version > 1.6.6</slf4j.version >    <log4j.version > 1.2.12</log4j.version >    <mysql.version > 5.1.6</mysql.version >    <mybatis.version > 3.4.5</mybatis.version >  </properties > 
 
加依赖
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 <dependencies >      <dependency >      <groupId > org.springframework</groupId >      <artifactId > spring-context</artifactId >      <version > ${spring.version}</version >    </dependency >       <dependency >      <groupId > org.aspectj</groupId >      <artifactId > aspectjweaver</artifactId >      <version > 1.6.8</version >    </dependency >    <dependency >      <groupId > org.springframework</groupId >      <artifactId > spring-aop</artifactId >      <version > ${spring.version}</version >    </dependency >       <dependency >      <groupId > org.springframework</groupId >      <artifactId > spring-jdbc</artifactId >      <version > ${spring.version}</version >    </dependency >       <dependency >      <groupId > org.springframework</groupId >      <artifactId > spring-tx</artifactId >      <version > ${spring.version}</version >    </dependency >       <dependency >      <groupId > org.springframework</groupId >      <artifactId > spring-test</artifactId >      <version > ${spring.version}</version >    </dependency >    <dependency >      <groupId > junit</groupId >      <artifactId > junit</artifactId >      <version > 4.12</version >      <scope > compile</scope >    </dependency >       <dependency >      <groupId > mysql</groupId >      <artifactId > mysql-connector-java</artifactId >      <version > ${mysql.version}</version >    </dependency >       <dependency >      <groupId > c3p0</groupId >      <artifactId > c3p0</artifactId >      <version > 0.9.1.2</version >      <type > jar</type >      <scope > compile</scope >    </dependency >       <dependency >      <groupId > org.springframework</groupId >      <artifactId > spring-web</artifactId >      <version > ${spring.version}</version >    </dependency >    <dependency >      <groupId > org.springframework</groupId >      <artifactId > spring-webmvc</artifactId >      <version > ${spring.version}</version >    </dependency >       <dependency >      <groupId > javax.servlet</groupId >      <artifactId > servlet-api</artifactId >      <version > 2.5</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 >       <dependency >      <groupId > log4j</groupId >      <artifactId > log4j</artifactId >      <version > ${log4j.version}</version >    </dependency >    <dependency >      <groupId > org.slf4j</groupId >      <artifactId > slf4j-api</artifactId >      <version > ${slf4j.version}</version >    </dependency >    <dependency >      <groupId > org.slf4j</groupId >      <artifactId > slf4j-log4j12</artifactId >      <version > ${slf4j.version}</version >    </dependency >       <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 >  </dependencies > 
 
创建目录 java和resources文件夹
 
用到的类
 
Account三个属性
1 2 3 private  Integer id;private  String name;private  Double money;
 
做2个方法
1 2 public  List<Account> findAll ()  ;public  void  saveAccount (Account account)  ;
 
Spring框架 配置 applicationContext.xml resources下新建applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?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.xsd 	http://www.springframework.org/schema/context 	http://www.springframework.org/schema/context/spring-context.xsd 	http://www.springframework.org/schema/aop 	http://www.springframework.org/schema/aop/spring-aop.xsd 	http://www.springframework.org/schema/tx 	http://www.springframework.org/schema/tx/spring-tx.xsd" >         <context:component-scan  base-package ="com.coconutnut"  >                   <context:exclude-filter  type ="annotation"  expression ="org.springframework.stereotype.Controller"  />      </context:component-scan >  </beans > 
 
controller是表现层的,Spring框架不管
加注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Service("accountService") public  class  AccountServiceImpl  implements  IAccountService   {    @Override      public  List<Account> findAll ()   {         System.out.println("业务层:查询所有" );         return  null ;     }     @Override      public  void  saveAccount (Account account)   {         System.out.println("业务层:保存账户" );     } } 
 
测试 用junit单元测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public  class  TestSpring   {    @Test      public  void  test ()  {                  ApplicationContext ac = new  ClassPathXmlApplicationContext("classpath:applicationContext.xml" );                  IAccountService as = (IAccountService) ac.getBean("accountService" );                  as.findAll();     } } 
 
 
WARNING说没有log4j的配置文件
复制一个log4j.properties到resources目录下即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 log4j.rootCategory =info, CONSOLE, LOGFILE log4j.logger.org.apache.axis.enterprise =FATAL, CONSOLE 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 log4j.appender.LOGFILE =org.apache.log4j.FileAppender log4j.appender.LOGFILE.File =/Users/coconutnut/TREE/Midgard/Idea/SSM/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 
 
要改一下路径
SpringMVC框架 配置 web.xml WEB-INF文件夹下的web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <web-app >   <display-name > Archetype Created Web Application</display-name >       <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 >       <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 >  </web-app > 
 
配置 springmvc.xml resources文件夹下新建springmvc.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?xml version="1.0" encoding="UTF-8"?> <beans  xmlns ="http://www.springframework.org/schema/beans"         xmlns:mvc ="http://www.springframework.org/schema/mvc"  xmlns:context ="http://www.springframework.org/schema/context"         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 ="com.coconutnut" >          <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  name ="suffix"  value =".jsp" />      </bean >           <mvc:resources  location ="/css/"  mapping ="/css/**"  />      <mvc:resources  location ="/images/"  mapping ="/images/**"  />      <mvc:resources  location ="/js/"  mapping ="/js/**"  />           <mvc:annotation-driven />  </beans > 
 
页面 index.jsp中加一个超链接
1 2 3 4 5 6 7 8 9 10 <html> <head>     <title>Title</title> </head> <body>     <a href="account/findAll" >测试</a> </body> </html> 
 
WEB-INF中新建pages文件夹,新建list.jsp
1 2 3 4 5 6 7 8 9 10 <html> <head>     <title>Title</title> </head> <body>     <h3>查询所有的账户信息</h3> </body> </html> 
 
控制器 1 2 3 4 5 6 7 8 9 10 11 @Controller @RequestMapping("/account") public  class  AccountController   {    @RequestMapping("/findAll")      public  String findAll ()  {         System.out.println("表现层:查询所有" );         return  "TODO" ;     } } 
 
部署  
测试  
 
Spring整合SpringMVC 目标:Controller中调用业务层方法
方法:要把Service注入到Controller中
问题:web.xml中配置了springmvc.xml,springmvc.xml中配置了对Controller的扫描,其它扫描的配置在applicationContext.xml中,而这个文件始终没有被加载过
解决:启动tomcat服务器时,加载Spring的配置文件applicationContext.xml
ServletContext对象生命周期和服务器相同,可以用监听器监听其创建和销毁
于是,可以在web.xml中用监听器加载Spring的配置文件
监听器是spring-web提供的
它默认只加载WEB-INF目录下的applicationContext.xml配置文件
可以复制一份丢到WEB-INF目录,或者手动设置路径
1 2 3 4 5 6 7 8 <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 >  
 
这样启动服务器时,Spring的配置文件也加载了
Service和Controller都放到容器中了
于是可以在AccountController中进行依赖注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Controller @RequestMapping("/account") public  class  AccountController   {    @Autowired      private  IAccountService accountService;     @RequestMapping("/findAll")      public  String findAll ()  {         System.out.println("表现层:查询所有" );         accountService.findAll();         return  "list" ;     } } 
 
测试 点击浏览器中测试按钮
 
成功
MyBatis框架 加注解 1 2 3 4 5 6 7 8 9 public  interface  IAccountDao   {    @Select("select * from account")      public  List<Account> findAll ()  ;     @Insert("insert into account (name,money) values (#{name},#{money})")      public  void  saveAccount (Account account)  ; } 
 
配置 sqlMapConfig.xml 在resources中新建sqlMapConfig.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration          PUBLIC  "-//mybatis.org//DTD Config 3.0//EN"          "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration >          <environments  default ="mysql" >          <environment  id ="mysql" >              <transactionManager  type ="JDBC" />              <dataSource  type ="POOLED" >                  <property  name ="driver"  value ="com.mysql.jdbc.Driver" />                  <property  name ="url"  value ="jdbc:mysql://localhost:3306/groot?characterEncoding=utf8" />                  <property  name ="username"  value ="root" />                  <property  name ="password"  value ="iamgroot" />              </dataSource >          </environment >      </environments >           <mappers >          <package  name ="com.coconutnut.dao" />      </mappers >  </configuration > 
 
测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public  class  TestMyBatis   {    @Test      public  void  test01 ()  throws  Exception  {                  InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml" );                  SqlSessionFactory factory = new  SqlSessionFactoryBuilder().build(in);                  SqlSession session = factory.openSession();                  IAccountDao dao = session.getMapper(IAccountDao.class);                  List<Account> list = dao.findAll();         for (Account account : list){             System.out.println(account);         }                  session.close();         in.close();     }       @Test      public  void  test02 ()  throws  Exception  {         Account account = new  Account();         account.setName("熊大" );         account.setMoney(400d );                  InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml" );                  SqlSessionFactory factory = new  SqlSessionFactoryBuilder().build(in);                  SqlSession session = factory.openSession();                  IAccountDao dao = session.getMapper(IAccountDao.class);                  dao.saveAccount(account);                  session.commit();                  session.close();         in.close();     } } 
 
测试查询
 
测试保存
 
Spring整合MyBatis 目标:Service能调用Dao
此时Service已经在容器中了,需要把生成的Dao的代理对象也存到容器中
配置 在Spring的配置文件applicationContext.xml中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <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/groot?characterEncoding=utf8" />    <property  name ="user"  value ="root" />    <property  name ="password"  value ="iamgroot" />  </bean > <bean  id ="sqlSessionFactory"  class ="org.mybatis.spring.SqlSessionFactoryBean" >   <property  name ="dataSource"  ref ="dataSource"  />  </bean > <bean  id ="mapperScanner"  class ="org.mybatis.spring.mapper.MapperScannerConfigurer" >   <property  name ="basePackage"  value ="com.coconutnut.dao" />  </bean > 
 
有了这段配置,sqlMapConfig.xml其实就不需要了,可以删除
加注解 在AccountDao上加@Repository注解
在AccountServiceImpl中注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Service("accountService") public  class  AccountServiceImpl  implements  IAccountService   {    @Autowired      private  IAccountDao accountDao;     @Override      public  List<Account> findAll ()   {         System.out.println("业务层:查询所有" );         return  accountDao.findAll();     }     @Override      public  void  saveAccount (Account account)   {         System.out.println("业务层:保存账户" );         accountDao.saveAccount(account);     } } 
 
在AccountController中把查出的数据存入Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Controller @RequestMapping("/account") public  class  AccountController   {    @Autowired      private  IAccountService accountService;     @RequestMapping("/findAll")      public  String findAll (Model model)  {         System.out.println("表现层:查询所有" );         List<Account> list = accountService.findAll();         model.addAttribute("list" ,list);         return  "list" ;     } } 
 
页面 在list.jsp中打印出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <%@ 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>查询所有的帐户</h3> <c:forEach items="${list}"  var ="account" >     ${account.name} </c:forEach> </body> </html> 
 
测试查询 出了一个异常
1 2 3 4 5 2020-04-07 12:31:59,102 36291  [r$PoolThread-#0] WARN  resourcepool.BasicResourcePool  - com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@64fe7a60 -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30). Last acquisition attempt exception:  java.sql.SQLException: Unknown system variable 'tx_isolation' 	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055) 	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) 	... 
 
查询发现是mysql-connector-java版本太低导致
在pom.xml中将
1 <mysql.version > 5.1.6</mysql.version > 
 
改为
1 <mysql.version > 5.1.48</mysql.version > 
 
再试
 
成功
事务 保存方法还需管理事务
Spring中进行声明式事务管理,在applicationContext.xml中增加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <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:config >   <aop:advisor  advice-ref ="txAdvice"  pointcut ="execution(* com.coconutnut.service.impl.*ServiceImpl.*(..))" />  </aop:config > 
 
页面 在index.jsp中新增表单
1 2 3 4 5 6 7 8 9 10 11 12 13 <body>     <a href="account/findAll" >测试查询</a>     <h3>测试保存</h3>     <form action="account/save"  method="post" >         姓名:<input type="text"  name="name"  /><br/>         金额:<input type="text"  name="money"  /><br/>         <input type="submit"  value="保存" /><br/>     </form> </body> 
 
控制器 增加save方法
1 2 3 4 5 6 @RequestMapping("/save") public  void  save (Account account, HttpServletRequest request, HttpServletResponse response)  throws  IOException  {  accountService.saveAccount(account);   response.sendRedirect(request.getContextPath()+"/account/findAll" );   return ; } 
 
存完重定向到list页面
测试保存  
点击保存
 
成功
项目结构