Spring=Spring事務及集成web環境

一.Spring的事務

Spring的事務控制可以分爲編程式事務控制和聲明式事務控制。

編程式事務:

就是將業務代碼和事務代碼放在一起書寫,它的耦合性太高,開發中不使用

聲明式事務

其實就是將事務代碼和業務代碼隔離開發, 然後通過一段配置讓他們組裝運行, 最後達到事務控制的目的.

聲明式事務就是通過AOP原理實現的.

(1)Spring的聲明式事務:

在 Spring 配置文件中聲明式的處理事務來代替代碼式的處理事務。底層採用AOP思想來實現的

思想:

目標對象:AccountServiceImpl

通知對象:DataSourceTransactionManager

配置切面:xml,註解

(2)項目搭建:

創建java模塊:Maven項目pom.xml文件依賴:

 <!--依賴管理-->
    <dependencies>
        <!--mysql驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--druid連接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.15</version>
        </dependency>
        <!--spring-jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!--spring核心-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--spring整合junit-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

編寫AccountDao

public interface AccountDao {
//轉出
    void  outUser(String outUser, Double money);
//轉入
    void inUser(String inUser, Double money);
}
public class AccountDaoImpl implements AccountDao {

    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public void outUser(String outUser, Double money) {
        // 1.編寫sql
        String sql = "update account set money = money - ? where name = ?";
        // 2.執行sql
        jdbcTemplate.update(sql, money, outUser);
    }

    @Override
    public void inUser(String inUser, Double money) {
        // 1.編寫sql
        String sql = "update account set money = money + ? where name = ?";
        // 2.執行sql
        jdbcTemplate.update(sql, money, inUser);
    }
}

編寫AccountService

public interface AccountService {

    // 轉賬
    void transfer(String outUser, String inUser, Double money);
}
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String outUser, String inUser, Double money) {

        // 核心業務
        accountDao.outUser(outUser, money);
        // 模擬異常..
        int i = 1 / 0;
        accountDao.inUser(inUser, money);
    }
}

編寫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:aop="http://www.springframework.org/schema/aop"
       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/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">

    <!--加載第三方配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--druid交給ioc-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    
    <!--jdbcTemplate交給ioc-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>

    <!--dao交給ioc-->
    <bean id="accountDao" class="com.wsl.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!--將service交給ioc-->
    <bean id="accountService" class="com.wsl.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--事務管理器交給ioc-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

測試:

@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AccountServiceTest {

    @Autowired
    private AccountService accountService;

    @Test
    public void test01() throws Exception {
        accountService.transfer("tom", "jerry", 100d);
    }
}

(3)事務的xml配置:

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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--加載第三方配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--druid交給ioc-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--jdbcTemplate交給ioc-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>

    <!--dao交給ioc-->
    <bean id="accountDao" class="com.wsl.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <!--將service交給ioc:目標對象-->
    <bean id="accountService" class="com.wsl.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--事務管理器交給ioc-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--將事務管理器升級爲事務通知類-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--定義事務管理器信息 DefaultTransactionDefinition-->
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!--aop配置-->
    <aop:config>
        <!--
            僅spring的事務切面配置使用此標籤
                通知+切點=切面
        -->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.com.service..*.*(..))"></aop:advisor>
    </aop:config>

</beans>

測試:即可

重要:

事務通知類細節補充;

<!--將事務管理器升級爲事務通知類-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--
            定義事務管理器信息 DefaultTransactionDefinition
            我們可以控制指定的方法,設置事務隔離級別、傳播行爲、是否只讀、是否超時...
                name="transfer" 需要控制事務的方法名
                isolation="DEFAULT" 設置當前方法的事務隔離界別,mysql默認級別:repeatable_read
                propagation="REQUIRED" 設置當前方法的事務傳播行爲 ,REQUIRED:當前方法必須有一個事務(單獨使用開啓,別人調用加入對方事務)
                read-only="false" 當前方式爲非只讀(增刪改用的)
                timeout="-1" 事務超時時間,-1:永不超時
        -->
    <tx:attributes>
        <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
        <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
        <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
        <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
        <tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>
    </tx:attributes>
</tx:advice>

(4)註解配置anno

開啓註解配置:刪除上述事務的xml配置:

開啓tx事務的註解支持:

在目標對象上,AccountService 使用事務註解:

然後測試接口,事務已經添加上了:

 

重要:

註解事務細節補充:

二.Spring集成Web環境

(1)web環境搭建:

新建java項目,利用JBjavaToWeb工具轉換成web項目:

新建UserServlet:

@WebServlet("/UserServlet")
public class UserServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取spring容器的上下文對象
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 調用service,實現保存功能
        UserService userService = app.getBean(UserService.class);
        userService.save();
    }

}

部署項目即可運行:

 

問題:我們在Servlet中的方法中,直接創建spring容器,每次訪問每次創建,浪費內容空間和性能

(2)自定義監聽器和工具類:

利用servletContextListener監聽器,在項目啓動時執行,我們就可以創建ClassPathXmlApplicationContext,我可以將這個spring的app對象,設置到ServletContext域,所有servlet都可以從這個域中,獲取此對象

自定義監聽器:

web.xml


	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>applicationContext.xml</param-value>
	</context-param>
	
	<listener>
	<listener-class>com.wsl.web.listener.MyContextLoaderListener</listener-class>
</listener>
public class MyContextLoaderListener implements ServletContextListener {

    ClassPathXmlApplicationContext app = null;

    // 在web項目啓動時,創建spring環境
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 獲取servletContext域對象
        ServletContext servletContext = sce.getServletContext();
        // 讀取全局配置參數
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
        // 創建spring環境
        app = new ClassPathXmlApplicationContext(contextConfigLocation);
        // 設置到域中
        servletContext.setAttribute("app", app);
        System.out.println("spring環境初始化");
    }

    // 在web項目卸載時,關閉spring環境
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        app.close();
        System.out.println("spring環境銷燬了");
    }
}

獲取spring容器的工具類:

// 專門從web最大的域中獲取spring環境
public class MyWebApplicationContextUtils {

    public static ApplicationContext getWebApplicationContext(ServletContext servletContext) {
        return (ApplicationContext) servletContext.getAttribute("app");
    }
}

修改UserServlet

@WebServlet("/UserServlet")
public class UserServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取spring容器的上下文對象
        // ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //  ApplicationContext app = (ApplicationContext) request.getServletContext().getAttribute("app");
        ApplicationContext app = MyWebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        // 調用service,實現保存功能
        UserService userService = app.getBean(UserService.class);
        userService.save();
    }

}

(3)改造Springweb項目:通過Spring提供的工具類:

導入spring-web座標

<!--spring整合web容器-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>

設置spring提供的監聽器

<!--全局配置參數-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

修改UserServlet

@WebServlet("/UserServlet")
public class UserServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取spring容器的上下文對象
        WebApplicationContext app = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        // 調用service,實現保存功能
        UserService userService = app.getBean(UserService.class);
        userService.save();
    }

}

 

三.SpringMVC簡介

(1)MVC模式

* model:模型 JavaBean(1.處理業務邏輯 2.封裝數據)

* view:視圖 Jsp/html(展示數據)

* controller:控制器 Servlet(1.接收請求 2.調用模型 3.轉發視圖)

三層架構:

* web層:用戶與java交互

* service層:處理業務邏輯

* dao層:java與數據庫交互

 

(2)SpringMVC介紹

SpringMVC 是一種基於 Java 的實現 MVC 設計模式的輕量級 Web 框架,它可以通過一套註解,讓一個簡單的Java類成爲控制器,而無須實現任何接口。

springMVC框架本質上就是一個servlet,封裝了共有的行爲(請求、響應),簡化代碼

 

四.SpringMVC快速入門

訪問一個url,可以在控制檯打印一句話,然後跳轉到一個新頁面:

分析:

創建web項目,並導入相關座標:

新增
<!--依賴管理-->
<dependencies>
    <!--springMVC-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>

    <!--servlet-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
    <!--jsp-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

配置前端控制器(Servlet)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <!--前端控制器-->
    <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>
        <!--指定servlet在tomcat啓動時創建-->
        <load-on-startup>4</load-on-startup>
    </servlet>

    <!--攔截url規則:/(默認)-->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

編寫controller和jsp

/*
    一個模塊對應一個控制器(類)
 */
public class UserController {

    // 一個功能(請求)對應一個方法
    public String quick() {
        System.out.println("quick....");
        // 轉發給一個視圖
        return "/WEB-INF/pages/success.jsp";
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>success</title>
</head>
<body>
<h3>success....</h3>
</body>
</html>

配置Controller

編寫spring-mvc.xml

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.wsl.web"/>
    
    <!--開啓mvc註解支持-->
    <mvc:annotation-driven/>


</beans>

部署並測試

 

運行流程:

 

五.SpringMVC組件概述

(1)執行流程:

springMVC內部執行流程,涉及11個步驟

 

(2)三大組件

* 處理器映射器:HandlerMapping
	將 請求url  和 處理器的方法 建立映射關係

* 處理器適配器:HandlerAdapter
	從多個處理器當中,適配其中一個,調用目標執行...

* 視圖解析器:ViewResolver
	將邏輯視圖解析爲物理視圖

Spring的DispatcherServlet默認配置文件:

 

相關配置:

 

學了SpringMVC後,在寫代碼的時候就重點關注這些了:

1. 編寫 處理器(controller)

2. 編寫 視圖(jsp、html)

 

(3)常用註解:

@Controller

SpringMVC基於Spring容器,所以在進行SpringMVC操作時,需要將Controller存儲到Spring容器中,故使用此註解

 

@RequestMapping

用於建立請求 URL 和處理請求方法之間的對應關係

/*
    一個模塊對應一個控制器(類)
 */
@Controller // 交給ioc容器
@RequestMapping("/user")
public class UserController {

    /*
         @RequestMapping
            功能:將請求的url  和 方法 建立映射關係
            位置:
                類上:建立一級url訪問路徑
                方法上:建立二級的url訪問路徑,與一級路徑組成一個完整url路徑
                舉個栗子:
                    /user/add
                    /user/update
                    /user/delete
                    /user/findAll

                    /order/add
                    /order/update
                    /order/delete
            常用屬性:
                value/path:聲明url訪問路徑
                method:限定請求方式,默認支持所有,共有7種(get、post、put、delete)
                params:限定請求參數
     */
    // 一個功能(請求)對應一個方法
    // @RequestMapping("/quick")
    @RequestMapping(value = "/quick", method = {RequestMethod.POST,RequestMethod.GET},params = {"username","password"})
    public String quick() {
        System.out.println("quick....");
        return "error";
    }
}

 

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