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";
    }
}

 

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