• spring 事物(二)—— 编程式事物实现与扩展


    简介

    使用TransactionTemplate 不需要显式地开始事务,甚至不需要显式地提交事务。这些步骤都由模板完成。但出现异常时,应通过TransactionStatus 的setRollbackOnly 显式回滚事务。 
    TransactionTemplate 的execute 方法接收一个TransactionCallback 实例。Callback 也是Spring 的经典设计,用于简化用户操作。

    TransactionCallback 包含如下方法。 

    • Object dolnTransaction(TransactionStatus status) 。 
    该方法的方法体就是事务的执行体。 
    如果事务的执行体没有返回值,则可以使用TransactionCallbackWithoutResultl类的实例。这是个抽象类,不能直接实例化,只能用于创建匿名内部类。它也是TransactionCallback 接口的子接口,该抽象类包含一个抽象方法: 

    • void dolnTransactionWithoutResult(TransactionStatus status)该方法与dolnTransaction 的效果非常相似,区别在于该方法没有返回值,即事务执行体无须返回值。 

    transactionTemplate.execute(new TransactionCallback() { 
        public Object doInTransaction(TransactionStatus status) { 
            try{ 
    
            } 
            catch (Exception e) {
                 status.setRollbackOnly(); 
            } 
        }
    }); 

    简单实现

    SQL:

    
    create table `account` (
        `username` varchar (99),
        `salary` int (11)
    ); 
    insert into `account` (`username`, `salary`) values('小王','3000');
    insert into `account` (`username`, `salary`) values('小马','3000');
    
    

    注意: 通过添加/删除accountMoney() 方法中int i = 10 / 0这个语句便可验证事务管理是否配置正确。

    OrdersDao.java(Dao层)

    package com.gm.dao;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    
    public class OrdersDao {
        // 注入jdbcTemplate模板对象
        private JdbcTemplate jdbcTemplate;
    
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
        // 对数据操作的方法不包含业务操作
        /**
         * 小王少钱的方法
         */
        public void reduceMoney() {
            String sql = "update account set salary=salary-? where username=?";
            jdbcTemplate.update(sql, 1000, "小王");
        }
    
        /**
         * 小马多钱的方法
         */
        public void addMoney() {
            String sql = "update account set salary=salary+? where username=?";
            jdbcTemplate.update(sql, 1000, "小马");
        }
    }
    

    OrdersService.java(业务逻辑层)

    package com.gm.service;
    
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.TransactionCallback;
    import org.springframework.transaction.support.TransactionTemplate;
    
    import com.gm.dao.OrdersDao;
    
    public class OrdersService {
    
        private final static Logger LOG = LoggerFactory.getLogger(OrdersService.class);
        
        // 注入Dao层对象
        private OrdersDao ordersDao;
    
        public void setOrdersDao(OrdersDao ordersDao) {
            this.ordersDao = ordersDao;
        }
    
        // 注入TransactionTemplate对象
        private TransactionTemplate transactionTemplate;
    
        public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
            this.transactionTemplate = transactionTemplate;
        }
    
        // 调用dao的方法
        // 业务逻辑,写转账业务
        public void accountMoney() {
            transactionTemplate.execute(new TransactionCallback<Object>() {
    
                @Override
                public Object doInTransaction(TransactionStatus status) {
                    Object result = null;
                    try {
                        // 小马多1000
                        ordersDao.addMoney();
                        // 加入出现异常如下面int
                        // i=10/0(银行中可能为突然停电等。。。);结果:小马账户多了1000而小王账户没有少钱
                        // 解决办法是出现异常后进行事务回滚
                        int i = 10 / 0;// 事务管理配置后异常已经解决
                        // 小王 少1000
                        ordersDao.reduceMoney();
                    } catch (Exception e) {
                        status.setRollbackOnly();
                        result = false;
                        LOG.error("Transfer Error!,"+e.getMessage());
                    }
    
                    return result;
                }
            });
    
        }
    }
    

    TestService.java(测试方法)

    package com.gm.service;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestService {
        @Test
        public void testAdd() {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    "beans.xml");
            OrdersService userService = (OrdersService) context
                    .getBean("ordersService");
            userService.accountMoney();
        }
    }
    
    

    配置文件:

    <?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-2.5.xsd  
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd  
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
        <!-- 配置c3po连接池 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <!-- 注入属性值 -->
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb"></property>
            <property name="user" value="root"></property>
            <property name="password" value="153963"></property>
        </bean>
        <!-- 编程式事务管理 -->
        <!-- 配置事务管理器 -->
        <bean id="dataSourceTransactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!-- 注入dataSource -->
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
        <!-- 配置事务管理器模板 -->
        <bean id="transactionTemplate"
            class="org.springframework.transaction.support.TransactionTemplate">
            <!-- 注入真正进行事务管理的事务管理器,name必须为 transactionManager否则无法注入 -->
            <property name="transactionManager" ref="dataSourceTransactionManager"></property>
        </bean>
    
        <!-- 对象生成及属性注入 -->
        <bean id="ordersService" class="com.gm.service.OrdersService">
            <property name="ordersDao" ref="ordersDao"></property>
            <!-- 注入事务管理的模板 -->
            <property name="transactionTemplate" ref="transactionTemplate"></property>
        </bean>
    
        <bean id="ordersDao" class="com.gm.dao.OrdersDao">
            <property name="jdbcTemplate" ref="jdbcTemplate"></property>
        </bean>
        <!-- JDBC模板对象 -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    </beans> 

    log4j.properties

    #Level:ERROR,WARN,INFO,DEBUG
    log4j.rootLogger=ERROR, console
    log4j.appender.console=org.apache.log4j.ConsoleAppender
    log4j.appender.console.target=System.out
    log4j.appender.console.layout=org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
    

    执行,输出

    [ERROR] 2018-09-06 14:03:06,937 method:com.gm.service.OrdersService$1.doInTransaction(OrdersService.java:54)
    Transfer Error!,/ by zero

    扩展

    首先定义了两个接口:

    ServiceTemplate ---->   对TransactionTemplate进行了封装

    public interface ServiceTemplate {
    
        /**
         * <pre> 无事务模板执行业务处理
         * 1. 异常捕获,及分类处理
         * 2. 业务日志记录
         * </pre>
         *
         * @param <T>
         * @param clazz  返回对象
         * @param action 业务操作回调的接口
         * @return       服务返回对象
         */
        <T> T executeWithoutTransaction(Class<? extends Result> clazz, ServiceCallback action);
    
        /**
         * <pre> 支持本地事务模板执行业务处理
         * 1. 本地事务封装
         * 2. 异常捕获,及分类处理
         * 3. 业务日志记录
         * </pre>
         *
         * @param <T>
         * @param clazz  返回对象
         * @param action 业务操作回调的接口
         * @return       服务返回对象
         */
        <T> T execute(Class<? extends Result> clazz, ServiceCallback action);
    
    }

    ServiceCallback  ---->  对TransactionCallBack进行了封装 

    public interface ServiceCallback {
        /**
         * <pre> 校验
         * 对于校验不通过,异常驱动返回
         * </pre>
         */
        void doLock();
    
        /**
         * <pre> 校验
         * 对于校验不通过,异常驱动返回
         * </pre>
         */
        void check();
    
        /**
         * <pre> 执行业务逻辑
         * </pre>
         * @return
         */
        Result executeService();
    }

    ServiceTemplate的具体实现ServiceTemplateImpl.java

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.TransactionCallback;
    import org.springframework.transaction.support.TransactionTemplate;
    
    public class ServiceTemplateImpl implements ServiceTemplate {
    
    	private final static Logger LOG = LoggerFactory.getLogger(ServiceTemplateImpl.class);
    	
    	// 注入TransactionTemplate对象
    	private TransactionTemplate transactionTemplate;
    
    	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    		this.transactionTemplate = transactionTemplate;
    	}
    
    	@Override
    	public <T> T executeWithoutTransaction(Class<? extends Result> clazz,
    			ServiceCallback action) {
    		Result result = null;
    		try {
    			// 执行校验
    			action.check();
    			// 锁操作
    			action.doLock();
    			// 执行处理逻辑
    			result = action.executeService();
    			// 可以对结果进行初步校验TODO
    
    		} catch (Exception e) {//此处可换成具体异常或子定义异常
    			LOG.error("Transfer Error!,"+e.getMessage());
    			// 打日志TODO
    			return (T) result;
    
    		} catch (Throwable e2) {
    			LOG.error(e2.getMessage());
    			// 打日志TODO
    			return (T) result;
    		}
    
    		return (T) result;
    	}
    
    	@Override
    	@SuppressWarnings("unchecked")
    	public <T> T execute(final Class<? extends Result> clazz,
    			final ServiceCallback action) {
    		T acResult = (T) transactionTemplate.execute(new TransactionCallback() {
    			/**
    			 * @see org.springframework.transaction.support.TransactionCallback#doInTransaction(org.springframework.transaction.TransactionStatus)
    			 */
    			public Object doInTransaction(TransactionStatus status) {
    				Result result = null;
    				try {
    					result = clazz.newInstance();
    					// 执行校验逻辑
    					action.check();
    					// 锁操作
    					action.doLock();
    					// 执行处理逻辑
    					result = action.executeService();
    					// 返回值异常处理
    					if (result == null || !(result instanceof Result)) {
    						throw new Exception();
    					}
    				} catch (Exception e) {//此处可换成具体异常或子定义异常
    					// 业务异常捕获, 回滚, 打日志TODO
    					LOG.error("Transfer Error!,"+e.getMessage());
    					status.setRollbackOnly();
    					return result;
    				} catch (Throwable e2) {
    					// 系统异常捕获, 回滚, 打日志TODO
    					LOG.error(e2.getMessage());
    					status.setRollbackOnly();
    					return result;
    				}
    				return result;
    			}
    		});
    		return acResult;
    	}
    }
    

    在业务方法中使用ServiceTemplate, 通过构建ServiceCallBack匿名内部类的方式, 传递具体的业务代码

    OrdersService.java新增以下方法

    public void addMoney() {
    		serviceTemplate.execute(Result.class, new ServiceCallback() {
    			@Override
    			public void doLock() {
    				// 进行锁操作
    			}
    
    			@Override
    			public void check() {
    				// 进行校验
    			}
    
    			@Override
    			public Result executeService() {
    				Result result = new Result();
    				// 具体的业务代码
    				// 小马多1000
    				ordersDao.addMoney();
    				// 加入出现异常如下面int
    				// i=10/0(银行中可能为突然停电等。。。);结果:小马账户多了1000而小王账户没有少钱
    				// 解决办法是出现异常后进行事务回滚
    				int i = 10 / 0;// 事务管理配置后异常已经解决
    				// 小王 少1000
    				ordersDao.reduceMoney();
    				return result;
    			}
    		});
    	}

    修改beans.xml 

        <!-- 对象生成及属性注入 -->
        <bean id="ordersService" class="com.gm.service.OrdersService">
            <property name="ordersDao" ref="ordersDao"></property>
            <!-- 注入事务管理的模板 -->
            <property name="transactionTemplate" ref="transactionTemplate"></property>
            <property name="serviceTemplate" ref="serviceTemplate"></property>
        </bean>
        
        <bean id="serviceTemplate" class="com.gm.service.ServiceTemplateImpl">
            <!-- 注入事务管理的模板 -->
            <property name="transactionTemplate" ref="transactionTemplate"></property>
        </bean>

    修改TestService.java 

    public class TestService {
        @Test
        public void testAdd() {
            ApplicationContext context = new ClassPathXmlApplicationContext("dbBeans.xml");
            OrdersService userService = (OrdersService) context.getBean("ordersService");
            //userService.accountMoney();
            userService.addMoney();
        }
    }

    执行,输出

    [ERROR] 2018-09-06 14:08:51,524 method:com.gm.service.ServiceTemplateImpl$1.doInTransaction(ServiceTemplateImpl.java:71)
    Transfer Error!,/ by zero
    

    注意: 如果是不需要加事务的方法, 如查询 ,那么调用serviceTemplate的executeWithoutTransaction即可

    补充pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.test</groupId>
    	<artifactId>SpringTest</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<build />
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<!-- spring版本号 -->
    		<spring.version>4.1.5.RELEASE</spring.version>
    		<!-- mybatis版本号 -->
    		<mybatis.version>3.2.6</mybatis.version>
    		<!-- log4j日志文件管理包版本 -->
    		<slf4j.version>1.7.7</slf4j.version>
    		<log4j.version>1.2.17</log4j.version>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.11</version>
    			<!-- 表示开发的时候引入,发布的时候不会加载此包 -->
    			<scope>test</scope>
    		</dependency>
    		<!-- spring核心包 -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-core</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-web</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-oxm</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aop</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-jdbc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aop</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context-support</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-test</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- aop -->
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjweaver</artifactId>
    			<version>1.8.4</version>
    		</dependency>
    		<!-- mybatis核心包 -->
    		<dependency>
    			<groupId>org.mybatis</groupId>
    			<artifactId>mybatis</artifactId>
    			<version>${mybatis.version}</version>
    		</dependency>
    		<!-- mybatis/spring包 -->
    		<dependency>
    			<groupId>org.mybatis</groupId>
    			<artifactId>mybatis-spring</artifactId>
    			<version>1.2.2</version>
    		</dependency>
    		<!-- 导入java ee jar 包 -->
    		<dependency>
    			<groupId>javax</groupId>
    			<artifactId>javaee-api</artifactId>
    			<version>7.0</version>
    		</dependency>
    		<!-- 导入Mysql数据库链接jar包 -->
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<version>5.1.30</version>
    		</dependency>
    		<!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->
    		<dependency>
    			<groupId>commons-dbcp</groupId>
    			<artifactId>commons-dbcp</artifactId>
    			<version>1.2.2</version>
    		</dependency>
    		<!-- JSTL标签类 -->
    		<dependency>
    			<groupId>jstl</groupId>
    			<artifactId>jstl</artifactId>
    			<version>1.2</version>
    		</dependency>
    		<!-- 日志文件管理包 -->
    		<!-- log start -->
    		<dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>${log4j.version}</version>
    		</dependency>
    		<!-- 格式化对象,方便输出日志 -->
    		<dependency>
    			<groupId>com.alibaba</groupId>
    			<artifactId>fastjson</artifactId>
    			<version>1.1.41</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>
    		<!-- log end -->
    		<!-- 映入JSON -->
    		<dependency>
    			<groupId>com.fasterxml.jackson.core</groupId>
    			<artifactId>jackson-core</artifactId>
    			<version>2.7.5</version>
    		</dependency>
    		<dependency>
    			<groupId>com.fasterxml.jackson.core</groupId>
    			<artifactId>jackson-annotations</artifactId>
    			<version>2.7.5</version>
    		</dependency>
    		<dependency>
    			<groupId>com.fasterxml.jackson.core</groupId>
    			<artifactId>jackson-databind</artifactId>
    			<version>2.7.5</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.codehaus.jackson</groupId>
    			<artifactId>jackson-mapper-asl</artifactId>
    			<version>1.9.4</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.codehaus.jackson</groupId>
    			<artifactId>jackson-core-asl</artifactId>
    			<version>1.9.4</version>
    		</dependency>
    		<!-- 上传组件包 -->
    		<dependency>
    			<groupId>commons-fileupload</groupId>
    			<artifactId>commons-fileupload</artifactId>
    			<version>1.3.1</version>
    		</dependency>
    		<dependency>
    			<groupId>commons-io</groupId>
    			<artifactId>commons-io</artifactId>
    			<version>2.4</version>
    		</dependency>
    		<dependency>
    			<groupId>commons-codec</groupId>
    			<artifactId>commons-codec</artifactId>
    			<version>1.9</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.axis2</groupId>
    			<artifactId>axis2-adb</artifactId>
    			<version>1.6.3</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.axis2</groupId>
    			<artifactId>axis2-kernel</artifactId>
    			<version>1.6.3</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.axis2</groupId>
    			<artifactId>axis2-transport-local</artifactId>
    			<version>1.6.3</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.axis2</groupId>
    			<artifactId>axis2-transport-http</artifactId>
    			<version>1.6.3</version>
    			<exclusions>
    				<exclusion>
    					<artifactId>httpcore</artifactId>
    					<groupId>org.apache.httpcomponents</groupId>
    				</exclusion>
    			</exclusions>
    		</dependency>
    		<dependency>
    			<groupId>org.jdom</groupId>
    			<artifactId>jdom</artifactId>
    			<version>1.1.3</version>
    		</dependency>
    		<dependency>
    			<groupId>axis</groupId>
    			<artifactId>axis-jaxrpc</artifactId>
    			<version>1.4</version>
    		</dependency>
    		<dependency>
    			<groupId>axis</groupId>
    			<artifactId>axis</artifactId>
    			<version>1.4</version>
    		</dependency>
    		<dependency>
    			<groupId>org.freemarker</groupId>
    			<artifactId>freemarker</artifactId>
    			<version>2.3.23</version>
    		</dependency>
    		<dependency>
    			<groupId>org.codehaus.jettison</groupId>
    			<artifactId>jettison</artifactId>
    			<version>1.3.8</version>
    		</dependency>
    
    		<!--axis2 begin -->
    		<dependency>
    			<groupId>org.apache.axis2</groupId>
    			<artifactId>axis2</artifactId>
    			<version>1.6.3</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.axis2</groupId>
    			<artifactId>axis2-spring</artifactId>
    			<version>1.6.3</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.axis2</groupId>
    			<artifactId>axis2-xmlbeans</artifactId>
    			<version>1.6.3</version>
    		</dependency>
    		<!--axis2 end -->
    
    		<dependency>
    			<groupId>org.kie.modules</groupId>
    			<artifactId>org-apache-commons-net</artifactId>
    			<version>6.4.0.Final</version>
    			<type>pom</type>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.httpcomponents</groupId>
    			<artifactId>httpclient</artifactId>
    			<version>4.5.2</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.httpcomponents</groupId>
    			<artifactId>httpclient-cache</artifactId>
    			<version>4.5.2</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.httpcomponents</groupId>
    			<artifactId>httpcore</artifactId>
    			<version>4.4.5</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.httpcomponents</groupId>
    			<artifactId>httpcore-nio</artifactId>
    			<version>4.4.5</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.httpcomponents</groupId>
    			<artifactId>httpcore-ab</artifactId>
    			<version>4.4.5</version>
    		</dependency>
    
    		<!-- https://mvnrepository.com/artifact/org.eclipse.paho/org.eclipse.paho.client.mqttv3 -->
    		<dependency>
    			<groupId>org.eclipse.paho</groupId>
    			<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
    			<version>1.2.0</version>
    		</dependency>
    
    		<!-- oracle数据库驱动 -->
    		<dependency>
    			<groupId>oracle.driver</groupId>
    			<artifactId>oracle-driver</artifactId>
    			<version>11.2.0.4</version>
    		</dependency>
    
    		<dependency>
    			<groupId>dom4j</groupId>
    			<artifactId>dom4j</artifactId>
    			<version>1.6.1</version>
    		</dependency>
    
    		<dependency>
    			<groupId>net.sf.json-lib</groupId>
    			<artifactId>json-lib</artifactId>
    			<version>2.4</version>
    			<classifier>jdk15</classifier>
    		</dependency>
    
    		<dependency>
    			<groupId>c3p0</groupId>
    			<artifactId>c3p0</artifactId>
    			<version>0.9.1.2</version>
    		</dependency>
    	</dependencies>
    </project>
  • 相关阅读:
    css优化篇
    select超全超详细总结篇
    meta总结
    富文本编辑
    textarea 换行处理
    07 DRF响应类:Response
    06 内部类
    05 序列化组件
    04 APIView的请求生命周期
    python中if __name__ == '__main__'是什么?
  • 原文地址:https://www.cnblogs.com/gmhappy/p/11864072.html
Copyright © 2020-2023  润新知