Spring-AOP、Spring整合MyBatis、Spring聲明式事務、SpringMVC詳解

1、AOP:面向切面編程

AOP可以在不改動源代碼的情況下增加新的功能

在這裏插入圖片描述

傳統的編程方式都是縱向開發,從 數據庫–>dao層—>service層—>controller層—>前端頁面,而AOP是橫向開發,面向切面編程。

利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。

如下圖,業務邏輯中的增刪改查是問我們要具體實現的代碼,而對於日誌、驗證參數等固定操作,就不用我們每次都自己實現,可以使用AOP,將驗證參數、日誌等操作提取出來,切進增刪改查業務中,從而降低程序的耦合度,提高程序可重用性

在這裏插入圖片描述

1、AOP在Spring中的應用

允許用戶自定義切面,切入點等
在這裏插入圖片描述

  • 橫切關注點

    跨越應用程序多個模塊的方法或功能,與業務邏輯無關,但是程序中還必須要有的部分,比如日誌、緩存、安全、事務等

  • 切面

    可以理解爲一個類,在這個類中定義要切入的方法,即通知

  • 通知

    切面類中的方法,用來切入其他類中,比如處理日誌、緩存、事務的方法

  • 目標

    被通知的對象

  • 代理

    向目標對象應用通知之後創建的對象

  • 切入點

    通知執行的地點,就是切面中的方法在哪個地方生效

  • 連接點

    與切面匹配的執行點

Spring中的AOP,通過Advice定義橫切邏輯(前置、後置、環繞、異常拋出、引介通知),分別如下

在這裏插入圖片描述

2、方式一:使用增強配置類(實現接口)

不影響原來的業務情況下,動態添加功能,也是爲了解耦

  1. 導入Maven依賴

    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.4</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.1.RELEASE</version>
    </dependency>
    
  2. 創建UserService接口及實現類

    //接口
    public interface UserService {
        void insert();
        void delete();
    }
    
    //接口實現類
    public class UserServiceImpl implements UserService {
        public void insert() {
            System.out.println("插入方法");
        }
    
        public void delete() {
            System.out.println("刪除方法");
        }
    }
    
  3. 創建config配置包,創建切面類

    1. 實現MethodBeforeAdvice接口—前置

      在業務代碼之前執行的方法

      import org.springframework.aop.MethodBeforeAdvice;
      import java.lang.reflect.Method;
      
      //實現MethodBeforeAdvice接口,表示該切面中的方法會在目標方法執行後執行
      public class UserServiceBefore implements MethodBeforeAdvice {
          public void before(Method method, Object[] objects, Object o) throws Throwable {
              //打印類名和方法名
              System.out.println(o.getClass().getName()+"類的"+method.getName()+"方法在之前被執行了");
      
          }
      }
      
    2. 實現AfterReturningAdvice接口—後置

      在業務代碼之後前執行的方法

      import org.springframework.aop.AfterReturningAdvice;
      import java.lang.reflect.Method;
      
      //實現AfterReturningAdvice接口,在目標方法之後執行
      public class UserServiceAfter implements AfterReturningAdvice {
          public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
              //打印類名和方法名
              System.out.println(o1.getClass().getName()+"類的"+method.getName()+"方法在之後被執行了");
          }
      }
      
  4. 將類配置到配置文檔中

    1. 配置xml文件頭
    2. 配置bean
    3. 配置AOP
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
             http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--開啓註解支持-->
        <context:annotation-config/>
    
        <!--第一種方式-->
        <!--定義bean-->
        <bean id="userservice" class="org.westos02.service.impl.UserServiceImpl"/>
        <bean id="beforelog" class="org.westos02.config.UserServiceBefore"/>
        <bean id="afterlog" class="org.westos02.config.UserServiceAfter"/>
    
        <!--定義AOP配置-->
        <aop:config>
            <!--定義切入點,expression後的表達式爲切入點,表示UserServiceImpl類下所有的方法,..表示方法的參數列表-->
            <aop:pointcut id="pc-userservice" expression="execution(* org.westos02.service.impl.UserServiceImpl.*(..))"/>
    
            <!--定義在切入點切入的方法(通知),引用上面定義的切面類的bean-->
            <aop:advisor advice-ref="afterlog" pointcut-ref="pc-userservice"/>
            <aop:advisor advice-ref="beforelog" pointcut-ref="pc-userservice"/>
        </aop:config>
    
    </beans>
    
  5. 測試

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("users.xml");
        UserService userservice = (UserService) context.getBean("userservice");
    
        userservice.insert();
        /*
        輸出結果
        在org.westos02.service.impl.UserServiceImpl類的insert方法之前被執行了
        插入方法
        在org.westos02.service.impl.UserServiceImpl類的insert方法之後被執行了
        */
    }
    

3、方式二:使用切面實現(自定義切面)

  1. 創建切面類,和普通類一樣

    public class UserServiceAop {
    
        public void before() {
            System.out.println("方法執行前");
        }
    
        public void after() {
            System.out.println("方法執行後");
        }
    }
    
  2. 在xml中註冊配置

    使用配置標籤來控制增強的類型

    <!--第二種方式-->
    <!--要切入的類-->
    <bean id="userservice2" class="org.westos02.service.impl.UserServiceImpl"/>
    <!--切面類-->
    <bean id="aop" class="org.westos02.config.UserServiceAop"/>
    
    <aop:config>
        <!--定義切面-->
        <aop:aspect ref="aop">
            <!--定義切點-->
            <aop:pointcut id="pc-userservice2" expression="execution(* org.westos02.service.impl.UserServiceImpl.*(..))"/>
    
            <!--定義通知類型、切入的通知、切點-->
            <aop:before method="before" pointcut-ref="pc-userservice2"/>
            <aop:after method="after" pointcut-ref="pc-userservice2"/>
        </aop:aspect>
    </aop:config>
    
  3. 測試

    @Test
    public void test2() {
        //獲得Spring配置文檔連接對象
        ApplicationContext context = new ClassPathXmlApplicationContext("users.xml");
        //獲得配置文檔中注入的對象
        UserService userservice = (UserService) context.getBean("userservice2");
    
        //執行插入方法
        userservice.insert();
        /*
        執行結果
        方法執行前
        插入方法
        方法執行後
         */
    }
    

3、方式三:使用註解實現增強

  1. 創建註解類

    • @Aspect,表示這是一個切面類
    • @Before,通知類型爲前置環繞
    • @After,通知類型爲後置環繞
    • @Around,通知類型爲包圍
    • execution(表達式),表示該通知生效的地方
    package org.westos02.config;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    //切面類
    @Aspect
    public class UserAnnotation {
    
        @Before("execution(* org.westos02.service.impl.UserServiceImpl.*(..))")
        public void before() {
            System.out.println("方法執行前");
        }
    
        @After("execution(* org.westos02.service.impl.UserServiceImpl.*(..))")
        public void after() {
            System.out.println("方法執行後");
        }
    
        @Around("execution(* org.westos02.service.impl.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("環繞前");
            System.out.println(joinPoint.getSignature());
            Object proceed = joinPoint.proceed();
            System.out.println("環繞後");
            System.out.println(proceed);
        }
    }
    
  2. xml配置

    <!--第三種方式,註解-->
    <bean id="userservice3" class="org.westos02.service.impl.UserServiceImpl"/>
    <!--讓Spring識別註解,一定要添加-->
    <aop:aspectj-autoproxy/>
    
  3. 測試

    @Test
    public void test3() {
        ApplicationContext context = new ClassPathXmlApplicationContext("users.xml");
        UserService userservice = (UserService) context.getBean("userservice3");
    
        userservice.insert();
    }
    

2、Spring整合MyBatis

對應版本要求

在這裏插入圖片描述

1、創建MyBatis項目

  1. 創建Maven項目,導入Maven依賴

    <dependencies>
    
        <!--junit依賴-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
    
        <!--spring-webmvc依賴-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
    
        <!-- lombok依賴 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    
        <!--spring-aop依賴-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
    
        <!--aspectjweaver依賴-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    
        <!--spring-jdbc依賴-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.10.RELEASE</version>
        </dependency>
    
        <!--mybatis依賴-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
    
        <!--mysql依賴-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
    </dependencies>
    
  2. 添加Web框架支持,編寫Mybatis.config.xml配置文件

    <?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核心配置文件-->
    <configuration>
    
        <!--別名設置,簡化開發-->
        <typeAliases>
            <package name="org.westos.pojo"/>
            <!--<typeAlias type="org.westos.pojo.User" alias="User"/>-->
        </typeAliases>
    
        <!--一個environments裏面可以有多個environment標籤,通過id值進行切換-->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <!--固定寫法,驅動和URL-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url"
                              value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                    <!--MySQL數據庫賬號-->
                    <property name="username" value="root"/>
                    <!--MySQL數據庫密碼-->
                    <property name="password" value="123"/>
                </dataSource>
            </environment>
        </environments>
    
        <!--添加用戶映射配置,掃描dao包下的所有的mapper接口-->
        <mappers>
            <package name="org.westos.dao"/>
        </mappers>
    
    </configuration>
    
  3. 添加工具類

    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisUtil {
        private static SqlSessionFactory sqlSessionFactory;
    
        static {
            try {
                //因爲mybatis-config.xml配置文件在resource根目錄下,所以可以直接寫文件名
                String resource = "mybatis-config.xml";
                //固定的寫法
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        // 獲取sqlSession的連接
        public static SqlSession getSession() {
            return sqlSessionFactory.openSession();
        }
    
        // 獲取sqlSession的連接,可以設置自動提交事務
        public static SqlSession getSession(boolean flag) {
            return sqlSessionFactory.openSession(flag);
        }
    }
    
  4. 創建實體類和對應dao層接口

    //實體類
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class User {
    
        private int id;
        private String name;
        private String pwd;
    }
    
    //接口
    import org.westos.pojo.User;
    import java.util.List;
    
    public interface UserMapper {
        List<User> getUserList();
    }
    
  5. 創建對應的mapper.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="org.westos.dao.UserMapper">
        <!--查詢數據庫user表中所有的記錄-->
        <select id="getUserList" resultType="User">
            select * from user;
        </select>
    
    </mapper>
    
  6. 測試類測試

    @Test
    public void test1() throws IOException {
        UserMapper mapper = MyBatisUtil.getSession().getMapper(UserMapper.class);
        for (User user : mapper.getUserList()) {
            System.out.println(user);
        }
    }
    

2、整合MyBatis

步驟

  1. 創建applicationContext.xml

    • 編寫數據源,使用Spring的數據源替換mybatis配置
    • sqlSessionFactory工廠,綁定MyBatis配置文件和mapper.xml路徑
    • 根據構造器索引,從sqlSessionFactory中獲取sqlSession
    • 使用sqlSession給Mapper實現類的屬性賦值,並將Mapper實現類注入到IOC容器中
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--
        1、整合mybatis數據源
        使用Spring的數據源替換Mybatis配置
        org.springframework.jdbc.datasource.DriverManagerDataSource
        -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url"
                      value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="123"/>
        </bean>
    
        <!--
        2、注入sqlSessionFactory
        sqlSession工廠
        -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!--綁定Mabatis配置文件-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <!--綁定映射器的路徑,在dao包下找對應的xml配置文件-->
            <property name="mapperLocations" value="classpath:org/westos/dao/*.xml"/>
        </bean>
    
        <!--
        3、創建sqlSession
        SqlSessionTemplate:就是我們使用的sqlSession
        從sqlSession工廠中獲得sqlSession
        -->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <!--只能使用構造器注入sqlSessionFactory,因爲它沒有set方法-->
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    
        <!--4、
        使用獲得的sqlSession給UserMapper實現類屬性賦值
        -->
        <bean id="userMapperImpl" class="org.westos.dao.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    
    </beans>
    
  2. 創建UserMapper實現類

    import org.mybatis.spring.SqlSessionTemplate;
    import org.westos.pojo.User;
    import java.util.List;
    
    public class UserMapperImpl implements UserMapper {
    
        //sqlSession屬性由Spring自動注入
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        public List<User> getUserList() {
            //具體的sql實現還是由mapper.xml完成
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.getUserList();
        }
    }
    
  3. 創建mapper.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="org.westos.dao.UserMapper">
        <!--查詢數據庫user表中所有的記錄-->
        <select id="getUserList" resultType="User">
            select * from user;
        </select>
    
    </mapper>
    
  4. 測試

    @Test
    public void test2() {
        //得到IOC容器連接對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //從容器中得到UserMapperImpl實現類對象
        UserMapperImpl userMapperImpl = (UserMapperImpl) context.getBean("userMapperImpl");
        //調用對象的方法,打印信息
        for (User user : userMapperImpl.getUserList()) {
            System.out.println(user);
        }
    }
    

3、Spring聲明式事務

  1. mapper接口

    import java.util.List;
    public interface UserMapper {
        //查詢表中的所有用戶信息
        List<User> getUserList();
    
        //添加用戶
        int addUser(User user);
    
        //根據ID刪除用戶
        int deleteUser(int id);
    }
    
  2. mapper.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="org.westos.dao.UserMapper">
        <!--查詢數據庫user表中所有的記錄-->
        <select id="getUserList" resultType="User">
            select * from user;
        </select>
    
        <!--添加用戶-->
        <insert id="addUser" parameterType="User">
            INSERT INTO `user` (`id`,`name`,`pwd`) VALUES (#{id},#{name},#{pwd})
        </insert>
    
        <!--
        根據id刪除用戶
        在這裏我們先故意寫錯delete語句,測試一下事務
        -->
        <delete id="deleteUser" parameterType="int">
            DELETE FROM `user` WHERE `id`=#{id}
        </delete>
    
    </mapper>
    
  3. mapperImpl實現類實現

    import org.mybatis.spring.SqlSessionTemplate;
    import org.westos.dao.UserMapper;
    import org.westos.pojo.User;
    import java.util.List;
    
    
    public class UserMapperImpl implements UserMapper {
    
        //sqlSession屬性由Spring自動注入
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        //得到user表中的所有用戶的信息
        public List<User> getUserList() {
            //具體的sql實現還是由mapper.xml完成
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            //我們在getUserList方法裏面進行一些錯誤的操作
            mapper.addUser(new User(5, "田七", "777777"));
            //deleteUser方法的sql語句是有錯誤的
            mapper.deleteUser(4);
    
            return mapper.getUserList();
        }
    
        //添加用戶
        public int addUser(User user) {
            //具體的sql實現還是由mapper.xml完成
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.addUser(user);
        }
    
        //根據ID刪除用戶
        public int deleteUser(int id) {
            //具體的sql實現還是由mapper.xml完成
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.deleteUser(id);
        }
    }
    
  4. 測試

    //測試getUserList方法
    @Test
    public void test3() {
        //得到IOC容器連接對象
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //從容器中得到UserMapperImpl實現類對象
        UserMapper userMapperImpl = (UserMapperImpl) context.getBean("userMapperImpl");
        //調用對象的方法,打印信息
        for (User user : userMapperImpl.getUserList()) {
            System.out.println(user);
        }
    }
    
    //異常:Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELETES FROM `user` WHERE `id`=4' at line 1
    //顯示SQl異常,我們在mapper.xml文檔中故意寫錯的delete語句
    

    但是我們查看user表中的數據,發現在getUserList()方法中的SQL操作中,插入操作成功了但是刪除和查詢操作卻失敗了,這對於數據庫的ACID原則就造成了破壞,同一組SQ操作應該要麼都成功,要麼都失敗

在這裏插入圖片描述

一組事務中有錯誤的SQL語句,但是還是有一部分執行成功了,這種情況下就應該添加事務,事務不影響業務代碼

  1. 整合事務,使用AOP給數據庫操作添加事務

    1. 導入事務的命名空間tx
    2. 整合事務
    3. 在pom.xml中配置aspectjweaver依賴
    4. 配置事務增強,相當於一個切面
    5. AOP配置,導入AOP命名空間,配置AOP
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--
        1.導入事務的命名空間tx
        2.整合事務
        3.在pom.xml中配置aspectjweaver依賴
        4.配置事務增強,相當於一個切面
        5.AOP配置,導入AOP命名空間,配置AOP
        -->
        
        <!--整合事務-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <constructor-arg ref="dataSource"/>
        </bean>
    
        <!--配置事務增強
            id連接AOP,transaction-manager連接前面的整合事務-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <!--所有的方法都配置事務
                propagation配置事務的傳播特性,常用的有REQUIRED,沒有就創建-->
                <tx:method name="*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>
    
        <!--配置AOP-->
        <aop:config>
            <!--定義切點-->
            <aop:pointcut id="txPointCut" expression="execution(* org.westos.dao.*.*(..))"/>
            <!--定義切入的通知(事務)-->
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
        </aop:config>
    
        <aop:aspectj-autoproxy proxy-target-class="true"/>
    
        <!--
        1、整合mybatis數據源
        使用Spring的數據源替換Mybatis配置
        org.springframework.jdbc.datasource.DriverManagerDataSource
        -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
            <property name="username" value="root"/>
            <property name="password" value="123"/>
        </bean>
    
        <!--
        2、注入sqlSessionFactory
        sqlSession工廠
        -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!--綁定Mabatis配置文件-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <!--綁定映射器的路徑,在dao包下找對應的xml配置文件-->
            <property name="mapperLocations" value="classpath:org/westos/dao/*.xml"/>
        </bean>
    
        <!--
        3、創建sqlSession
        SqlSessionTemplate:就是我們使用的sqlSession
        從sqlSession工廠中獲得sqlSession
        -->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <!--只能使用構造器注入sqlSessionFactory,因爲它沒有set方法-->
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    
        <!--4、
        使用獲得的sqlSession給UserMapper實現類屬性賦值
        -->
        <bean id="userMapperImpl" class="org.westos.dao.impl.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    
    </beans>
    
  2. 再次測試

    發現在程序繼續報錯,但是數據庫數據並沒有發生變化

  3. 修改mapper.xml中的錯誤,再次測試

    發現所有的操作都可以完成,事務完整

    以後寫SQL操作代碼就不用再寫事務操作,而是由AOP自動切入

  4. 思考

    爲什麼需要事務

    • 如果不配置事務,可能存在數據提交不一致的情況
    • 如果我們不在Spring中去配置聲明式事務,我們就需要在代碼中手動配置事務,麻煩
    • 事務在項目的開發中十分重要,設計到數據的一致性和完整性問題,不容馬虎

4、SpringMVC

入門案例:創建一個簡單的SpringMVC項目

  • 原始的:jsp+servlet+web.xml

  • SpringMVC

    SpringMVC給我們提供了一個DispatcherServelet,我們只需要將

  1. 創建Maven項目,添加Web框架支持,配置Tomcat服務器

    啓動服務器,確保服務器可以正常啓動

  2. 添加Maven依賴

    <!--spring-webmvc依賴-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <!--servlet依賴-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
    </dependency>
    
  3. 在web.xml文件中註冊servlet

    <?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">
    
        <!--註冊DispatcherServlet,Servlet調度,Spring提供-->
        <servlet>
            <servlet-name>DispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--關聯SpringMVC的配置文件-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            <!--設置初始化參數-->
            </init-param>
            <!--服務器啓動的時候就啓動-->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <!--    /   和   /*  的區別
        /   匹配所有的請求,不包括.jsp文件
        /*  匹配所有的請求,包括.jsp文件
        -->
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <!--匹配所有的請求,不包括.jsp文件-->
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
  4. springmvc-servlet.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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!--固定配置-->
        <!--掃描控制層包,和前端進行頁面數據交互的-->
        <context:component-scan base-package="org.westos.controller"/>
        <!--開啓註解驅動-->
        <mvc:annotation-driven/>
        <!--開啓靜態資源掃描-->
        <mvc:default-servlet-handler/>
    
    
        <!--視圖解析器-->
        <!--匹配好的路徑爲:/WEB-INF/views/***.jsp-->
        <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--文件路徑前綴-->
            <property name="prefix" value="/WEB-INF/views/"/>
            <!--文件名後綴-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
    </beans>
    
  5. 創建hello.jsp頁面,用來跳轉到的界面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Hello</title>
    </head>
    <body>
    
    <h1>11111</h1>
        
    <%-- 從Controller中獲得的參數,打印在頁面上 --%>
    <h1>${msg}</h1>
    
    </body>
    </html>
    
  6. 創建HelloController類

    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    //註解表示是控制層的
    @Controller
    public class HelloController {
        
        //URL請求路徑
        @RequestMapping("/hello")
        //Model可以用來想前端傳遞參數
        public String hello(Model model) {
            //設置值,msg:Hello,SpringMvc
            model.addAttribute("msg", "Hello,SpringMvc");
            //返回jsp界面
            //經過視圖解析器解析後成爲:/WEB-INF/views/hello.jsp
            //有該界面就返回,沒有就報404
            return "hello";
        }
    }
    
  7. 創建lib目錄
    在這裏插入圖片描述

  8. 啓動Tomcat服務器測試

在這裏插入圖片描述

網站的核心就是交互

  • 前端傳值

  • 後臺處理數據,與數據庫打交道,返回數據給前端

  • 控制層控制頁面跳轉,控制請求

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章