手寫ioc&aop
- 1.概念
- IOC:Inversion of control 控制反轉
- AOP:Aspect oriented Programming 面向切面編程
- 2.通過銀行轉賬案例手寫IOC和AOP
- 2.1.表結構
- 2.2.銀行轉賬呼叫關系
- 2.3.分析存在的問題
- 2.4.解決問題思路
- 2.5.通過IOC及AOP進行改造
- 2.5.0.pom.xml
- 2.5.1.index.xml
- 2.5.2.beans.xml
- 2.5.3.工具類
- 2.5.4.pojo
- 2.5.5.工廠類
- 2.5.6.dao層
- 2.5.7.service層
- 2.5.8.controller層
- 2.5.9.注意事項
1.概念
IOC:Inversion of control 控制反轉
- 控制:指的是物件創建(實體化、管理)的權利
- 反轉:控制權交給外部環境了(spring框架、IoC容器)
- 傳統開發?式:?如類A依賴于類B,往往會在類A中new?個B的物件
- IoC思想下開發方式:我們不???去new物件了,?是由IoC容器(Spring框架)去幫助我們實體化物件并且管理它,我們需要使?哪個物件,去問IoC容器要即可,
- 解決的問題:解決物件之間的耦合問題,避免new關鍵字
- Ioc和DI區別:IOC和DI是從不同角度描述同一件事情(物件實體化及依賴關系維護這件事情),IOC是站在物件的角度,物件實體化及其管理的權力交給了(反轉)容器,DI:Dependancy Injection(依賴注?),是站在容器的角度,容器會把物件依賴的其他物件注入(送進去),比如A物件實體化程序中因為宣告了一個B型別的屬性,那么就需要容器把B物件注入給A
AOP:Aspect oriented Programming 面向切面編程
- 起源:aop是oop的延續,oop三大特征:封裝、繼承、多型,是一種垂直縱向的繼承體系,OOP編程思想可以解決?多數的代碼重復問題,但是有?些情況是處理不了的,?如在頂級?類中的多個?法中相同位置出現了重復代碼,OOP就解決不了
- 橫切邏輯代碼問題:1.橫切代碼重復問題,2.橫切邏輯代碼和業務代碼混雜在?起,代碼臃腫,維護不?便
- AOP解決的問題:在不改變原有業務邏輯情況下,增強橫切邏輯代碼,根本上解耦合,避免橫切邏輯代碼重復
- 面向切面編程理解:「切」:指的是橫切邏輯,原有業務邏輯代碼我們不能動,只能操作橫切邏輯代碼,所以?向橫切邏輯,「?」:橫切邏輯代碼往往要影響的是很多個?法,每?個?法都如同?個點,多個點構成?,有?個?的概念在??
2.通過銀行轉賬案例手寫IOC和AOP
2.1.表結構
CREATE TABLE `account` (
`name` varchar(255) DEFAULT NULL COMMENT '用戶名',
`money` varchar(255) DEFAULT NULL COMMENT '賬戶金額',
`cardNo` varchar(255) NOT NULL COMMENT '銀行卡號'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.2.銀行轉賬呼叫關系
2.3.分析存在的問題
- (1)問題?:在上述案例實作中,service 層實作類在使? dao 層物件時,直接在TransferServiceImpl 中通過 AccountDao accountDao = new JdbcAccountDaoImpl() 獲得了 dao層物件,然??個 new 關鍵字卻將 TransferServiceImpl 和 dao 層具體的?個實作類JdbcAccountDaoImpl 耦合在了?起,如果說技術架構發??些變動,dao 層的實作要使?其它技術,?如 Mybatis,思考切換起來的成本?每?個 new 的地?都需要修改源代碼,重新編譯,?向接?開發的意義將?打折扣?
- (2)問題?:service 層代碼沒有竟然還沒有進?事務控制 ?!如果轉賬程序中出現例外,將可能導致資料庫資料錯亂,后果可能會很嚴重,尤其在?融業務
2.4.解決問題思路
- 實體化物件的?式除了 new 之外,還有什么技術?反射 (需要把類的全限定類名配置在xml中)
- 考慮使?設計模式中的??模式解耦合,另外項?中往往有很多物件需要實體化,那就在??中使?反 射技術實體化物件,??模式很合適
- service 層沒有添加事務控制,怎么辦?沒有事務就添加上事務控制,?動控制 JDBC 的Connection 事務,但要注意將Connection和當前執行緒系結(即保證?個執行緒只有?個Connection,這樣操作才針對的是同?個 Connection,進?控制的是同?個事務),分析:資料庫的事務歸根結底是Connection的事務connection.commit();提交事務 connection.rollback();回滾事務
2.5.通過IOC及AOP進行改造
2.5.0.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.lagou.edu</groupId>
<artifactId>lagou-transfer</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>lagou-transfer Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- 單元測驗Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- mysql資料庫驅動包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!--druid連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- jackson依賴 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<!--dom4j依賴-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!--xpath運算式依賴-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<!--引入cglib依賴包-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_2</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Maven的JDK編譯級別 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- tomcat7插件 -->
<!-- 注意:目前來說,maven中央倉庫還沒有tomcat8的插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.5.1.index.xml
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>轉賬匯款</title>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<style type="text/css">
body {
background-color:#00b38a;
text-align:center;
}
.lp-login {
position:absolute;
width:500px;
height:300px;
top:50%;
left:50%;
margin-top:-250px;
margin-left:-250px;
background: #ffffff;
border-radius: 4px;
box-shadow: 0 0 10px #12a591;
padding: 57px 50px 35px;
box-sizing: border-box
}
.lp-login .submitBtn {
display:block;
text-decoration:none;
height: 48px;
width: 150px;
line-height: 48px;
font-size: 16px;
color: #fff;
text-align: center;
background-image: -webkit-gradient(linear, left top, right top, from(#09cb9d), to(#02b389));
background-image: linear-gradient(90deg, #09cb9d, #02b389);
border-radius: 3px
}
input[type='text'] {
height:30px;
width:250px;
}
span {
font-style: normal;
font-variant-ligatures: normal;
font-variant-caps: normal;
font-variant-numeric: normal;
font-variant-east-asian: normal;
font-weight: normal;
font-stretch: normal;
font-size: 14px;
line-height: 22px;
font-family: "Hiragino Sans GB", "Microsoft Yahei", SimSun, Arial, "Helvetica Neue", Helvetica;
}
</style>
<script type="text/javascript">
$(function(){
$(".submitBtn").bind("click",function(){
var fromAccount = $("#fromAccount").val();
var toAccount = $("#toAccount").val();
var money = $("#money").val();
if(money == null || $.trim(money).length == 0){
alert("sorry,必須輸入轉賬金額~");
return;
}
$.ajax({
url:'/transferServlet',
type:'POST', //GET
async:false, //或false,是否異步
data:{
fromCardNo:fromAccount.split(' ')[1],
toCardNo:toAccount.split(' ')[1],
money:money
},
timeout:5000, //超時時間
dataType:'json', //回傳的資料格式:json/xml/html/script/jsonp/text
success:function(data){
if("200" == data.status){
alert("轉賬成功~~~");
}else{
alert("轉賬失敗~~~,message:" + data.message);
}
}
})
})
})
//檢查輸入值是否為整數
function checkFormat(obj){
var reg = /^[0-9]+[0-9]*]*$/;
if($.trim($(obj).val()).length>0){
if(!reg.test($(obj).val())){
alert("輸入格式錯誤!請輸整數!");
$(obj).val("");
}else{
$(obj).val(parseInt($(obj).val()));
}
}
}
</script>
</head>
<body>
<form>
<table class="lp-login">
<tr>
<td align="right"><span>收款賬戶</span></td>
<td align="center">
<input type="text" id="toAccount" value="韓梅梅 6029621011001" disabled></input>
</td>
</tr>
<tr>
<td align="right"><span>付款賬戶</span></td>
<td align="center">
<input type="text" id="fromAccount" value="李大雷 6029621011000" disabled></input>
</td>
</tr>
<tr>
<td align="right"><span>轉賬金額</span></td>
<td align="center">
<input type="text" id="money" onblur="checkFormat(this)"></input>
</td>
</tr>
<tr align="center">
<td colspan="2">
<a href="javasrcipt:void(0)" class="submitBtn"><span>轉 出</span></a>
</td>
</tr>
</table>
</form>
</body>
</html>
2.5.2.beans.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<!--id:唯一標識, class類的全路徑-->
<bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl">
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
<bean id="transferService" class="com.lagou.edu.service.impl.TransferServiceImpl">
<!--set+ name,將屬性注入-->
<property name="AccountDao" ref="accountDao"></property>
</bean>
<!--配置新增的三個組件-->
<!--連接池工具類-->
<bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils"></bean>
<!--事務管理器-->
<bean id="transactionManager" class="com.lagou.edu.utils.TransactionManager">
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
<!--代理物件工廠-->
<bean id="proxyFactory" class="com.lagou.edu.factory.ProxyFactory">
<property name="TransactionManager" ref="transactionManager"></property>
</bean>
</beans>
2.5.3.工具類
- ConnectionUtils
package com.lagou.edu.utils;
import com.alibaba.druid.pool.DruidPooledConnection;
import java.sql.Connection;
import java.sql.SQLException;
/**
* 獲取資料庫連接工具類
*/
public class ConnectionUtils {
/* private ConnectionUtils(){}
public static ConnectionUtils getInstance(){
return new ConnectionUtils();
}*/
// 1.單例,保證執行緒獲取到的連接是同一個,(每次新new ConnectionUtils,那么里面的threadlocal也是新的,connection也是新的)
private ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
public Connection getCurrentThreadConn() throws SQLException {
Connection connection = threadLocal.get();
if (connection == null){
connection = DruidUtils.getInstance().getConnection();
// 創建完成后一定要設定回去
threadLocal.set(connection);
}
return connection;
}
}
- DruidUtils
package com.lagou.edu.utils;
import com.alibaba.druid.pool.DruidDataSource;
public class DruidUtils {
private DruidUtils(){
}
private static DruidDataSource druidDataSource = new DruidDataSource();
static {
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/bank");
druidDataSource.setUsername("root");
druidDataSource.setPassword("123456");
}
public static DruidDataSource getInstance() {
return druidDataSource;
}
}
- TransactionManager
package com.lagou.edu.utils;
import java.sql.Connection;
import java.sql.SQLException;
/**
* 事務管理器
*/
public class TransactionManager {
private ConnectionUtils connectionUtils;
public void setConnectionUtils(ConnectionUtils connectionUtils) {
this.connectionUtils = connectionUtils;
}
/* private TransactionManager(){}
private static TransactionManager transactionManager = new TransactionManager();
public static TransactionManager getInstance(){
return transactionManager;
}*/
public void beginTranscation() throws SQLException {
Connection conn = connectionUtils.getCurrentThreadConn();
conn.setAutoCommit(false);
System.out.println(conn.getAutoCommit() + ":開啟事務的連接:"+conn);
}
public void commit() throws SQLException {
connectionUtils.getCurrentThreadConn().commit();
System.out.println("提交的連接:"+connectionUtils.getCurrentThreadConn());
}
public void rollback() throws SQLException {
connectionUtils.getCurrentThreadConn().rollback();
System.out.println("回滾的連接:"+connectionUtils.getCurrentThreadConn());
}
}
- JsonUtils
package com.lagou.edu.utils;
import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* JSON工具類(使用的是jackson實作的)
*/
public class JsonUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 將物件轉換成json字串,
* @param data
* @return
*/
public static String object2Json(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 將json結果集轉化為物件
*
* @param jsonData json資料
* @param beanType 物件中的object型別
* @return
*/
public static <T> T json2Pojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 將json資料轉換成pojo物件list
* @param jsonData
* @param beanType
* @return
*/
public static <T>List<T> json2List(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
2.5.4.pojo
- Account
package com.lagou.edu.pojo;
public class Account {
private String cardNo;
private String name;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public String getCardNo() { return cardNo; }
public void setCardNo(String cardNo) { this.cardNo = cardNo;}
@Override
public String toString() {
return "Account{" +
"cardNo='" + cardNo + '\'' +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
2.5.5.工廠類
- BeanFactory
package com.lagou.edu.factory;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 工廠類
* 作用1:決議xml檔案,使用反射技術實體化bean物件,放入map中待用;
* 作用2:提供介面方法根據id從map中獲取bean(靜態方法)
*
*/
public class BeanFactory {
private static Map<String,Object> map = new HashMap<>();
// 0.服務一啟動,就將物件加載至容器中,這里使用靜態代碼塊
static{
// 1.決議物件組態檔
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
try {
// 使用dom4j技術,首先獲取根節點 <beans>
Element rootElement = new SAXReader().read(resourceAsStream).getRootElement();
// 使用xpath,尋找 <bean > 節點
List<Element> beanList = rootElement.selectNodes("//bean");
for (Element element : beanList) {
String id = element.attributeValue("id");
String aClass = element.attributeValue("class");
// 2.使用反射技術,根據類的全路徑創建物件
Class<?> aClass1 = Class.forName(aClass);
Object o = aClass1.newInstance();
// 3.將決議后的物件放入容器中(map)
map.put(id,o);
}
// 遍歷property標簽,將屬性注入,維護bean之間的依賴關系
List<Element> propertyList = rootElement.selectNodes("//property");
for (Element element : propertyList) {
String name = element.attributeValue("name");
String ref = element.attributeValue("ref");
// 使用反射技術,設定屬性
Element parent = element.getParent();
String parentId = parent.attributeValue("id");
Object parentObj = map.get(parentId);
Method[] methods = parentObj.getClass().getMethods();
// 獲取所有方法,尋找set+name,將ref設定
for (Method method : methods) {
if(method.getName().equalsIgnoreCase("set"+name)){
Object propertyObj = map.get(ref);
method.invoke(parentObj,propertyObj);
}
}
// 維護依賴關系后重新將bean放入map中
map.put(parentId,parentObj);
}
} catch (DocumentException | ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
// 3.提供獲取物件的方法
public static Object getBean(String id){
return map.get(id);
}
}
- ProxyFactory
package com.lagou.edu.factory;
import com.lagou.edu.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
*
* 代理物件工廠:生成代理物件的
*/
public class ProxyFactory {
private TransactionManager transactionManager;
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/*private ProxyFactory(){
}
private static ProxyFactory proxyFactory = new ProxyFactory();
public static ProxyFactory getInstance() {
return proxyFactory;
}*/
/**
* Jdk動態代理
* @param obj 委托物件
* @return 代理物件
*/
public Object getJdkProxy(Object obj) {
// 獲取代理物件
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try{
// 開啟事務(關閉事務的自動提交)
transactionManager.beginTranscation();
result = method.invoke(obj,args);
// 提交事務
transactionManager.commit();
}catch (Exception e) {
e.printStackTrace();
// 回滾事務
transactionManager.rollback();
// 拋出例外便于上層servlet捕獲
throw e;
}
return result;
}
});
}
/**
* 使用cglib動態代理生成代理物件
* @param obj 委托物件
* @return
*/
public Object getCglibProxy(Object obj) {
return Enhancer.create(obj.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
try{
// 開啟事務(關閉事務的自動提交)
transactionManager.beginTranscation();
result = method.invoke(obj,objects);
// 提交事務
transactionManager.commit();
}catch (Exception e) {
// 回滾事務
transactionManager.rollback();
e.printStackTrace();
// 拋出例外便于上層servlet捕獲
throw e;
}
return result;
}
});
}
}
2.5.6.dao層
- AccountDao
package com.lagou.edu.dao;
import com.lagou.edu.pojo.Account;
public interface AccountDao {
Account queryAccountByCardNo(String cardNo) throws Exception;
int updateAccountByCardNo(Account account) throws Exception;
}
- JdbcAccountDaoImpl
package com.lagou.edu.dao.impl;
import com.lagou.edu.pojo.Account;
import com.lagou.edu.dao.AccountDao;
import com.lagou.edu.utils.ConnectionUtils;
import com.lagou.edu.utils.DruidUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JdbcAccountDaoImpl implements AccountDao {
private ConnectionUtils connectionUtils;
public void setConnectionUtils(ConnectionUtils connectionUtils) {
this.connectionUtils = connectionUtils;
}
public void init() {
System.out.println("初始化方法.....");
}
public void destory() {
System.out.println("銷毀方法......");
}
@Override
public Account queryAccountByCardNo(String cardNo) throws Exception {
//從連接池獲取連接
// Connection con = DruidUtils.getInstance().getConnection();
// 從當前執行緒中獲取連接池物件
Connection con = connectionUtils.getCurrentThreadConn();
String sql = "select * from account where cardNo=?";
PreparedStatement preparedStatement = con.prepareStatement(sql);
preparedStatement.setString(1,cardNo);
ResultSet resultSet = preparedStatement.executeQuery();
Account account = new Account();
while(resultSet.next()) {
account.setCardNo(resultSet.getString("cardNo"));
account.setName(resultSet.getString("name"));
account.setMoney(resultSet.getInt("money"));
}
resultSet.close();
preparedStatement.close();
// con.close(); // 不能將當前執行緒的連接關閉了,不然同個執行緒同個業務中其他更新方法獲取的連接就不是同一個
return account;
}
@Override
public int updateAccountByCardNo(Account account) throws Exception {
// 從連接池獲取連接
// 改造為:從當前執行緒當中獲取系結的connection連接
// Connection con = DruidUtils.getInstance().getConnection();
// 從當前執行緒中獲取連接池物件
Connection con = connectionUtils.getCurrentThreadConn();
String sql = "update account set money=? where cardNo=?";
PreparedStatement preparedStatement = con.prepareStatement(sql);
preparedStatement.setInt(1,account.getMoney());
preparedStatement.setString(2,account.getCardNo());
int i = preparedStatement.executeUpdate();
preparedStatement.close();
// con.close();
return i;
}
}
2.5.7.service層
- TransferService
package com.lagou.edu.service;
public interface TransferService {
void transfer(String fromCardNo,String toCardNo,int money) throws Exception;
}
- TransferServiceImpl
package com.lagou.edu.service.impl;
import com.lagou.edu.dao.AccountDao;
import com.lagou.edu.pojo.Account;
import com.lagou.edu.service.TransferService;
import com.lagou.edu.utils.TransactionManager;
public class TransferServiceImpl implements TransferService {
// private AccountDao accountDao = new JdbcAccountDaoImpl();
// private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");
// 最佳狀態
private AccountDao accountDao;
// 建構式傳值/set方法傳值
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String fromCardNo, String toCardNo, int money) throws Exception {
// try {
// // 開啟事務(設定自動提交關閉)
// TransactionManager.getInstance().beginTranscation();
Account from = accountDao.queryAccountByCardNo(fromCardNo);
Account to = accountDao.queryAccountByCardNo(toCardNo);
from.setMoney(from.getMoney()-money);
to.setMoney(to.getMoney()+money);
accountDao.updateAccountByCardNo(to);
int c = 1/0;
accountDao.updateAccountByCardNo(from);
// 事務提交
// TransactionManager.getInstance().commit();
// }catch (Exception e){
// // 事務回滾
// TransactionManager.getInstance().rollback();
// throw e;
// }
}
}
2.5.8.controller層
- TransferServlet
package com.lagou.edu.servlet;
import com.lagou.edu.factory.BeanFactory;
import com.lagou.edu.factory.ProxyFactory;
import com.lagou.edu.service.impl.TransferServiceImpl;
import com.lagou.edu.utils.JsonUtils;
import com.lagou.edu.pojo.Result;
import com.lagou.edu.service.TransferService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name="transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
// 1. 實體化service層物件
// private TransferService transferService = new TransferServiceImpl();
// private TransferService transferService = (TransferService) BeanFactory.getBean("transferService");
// 從工廠獲取委托物件,使用代理物件,主要增加了事務控制
private ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
private TransferService transferService = (TransferService) proxyFactory.getJdkProxy((TransferService) BeanFactory.getBean("transferService"));
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 設定請求體的字符編碼
req.setCharacterEncoding("UTF-8");
String fromCardNo = req.getParameter("fromCardNo");
String toCardNo = req.getParameter("toCardNo");
String moneyStr = req.getParameter("money");
int money = Integer.parseInt(moneyStr);
Result result = new Result();
try {
// 2. 呼叫service層方法
transferService.transfer(fromCardNo,toCardNo,money);
result.setStatus("200");
} catch (Exception e) {
e.printStackTrace();
result.setStatus("201");
result.setMessage(e.toString());
}
// 回應
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().print(JsonUtils.object2Json(result));
}
}
2.5.9.注意事項
com.lagou.edu.utils.ConnectionUtils#getCurrentThreadConn中一定要注意,第一次獲取連接為空時,創建連接后要設定到當前執行緒中,
if (connection == null){
connection = DruidUtils.getInstance().getConnection();
// 創建完成后一定要設定回去
threadLocal.set(connection);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/287799.html
標籤:其他
