實現銀行系統的余額查詢在我們之前寫的token認證登陸功能完成的基礎上實現,token認證登陸功能代碼地址:https://github.com/yeyuting-1314/selectFuPan_tokenAndRedisfengzhuagn.git
銀行系統余額查詢、轉賬、入賬、出賬功能項目代碼地址:https://github.com/yeyuting-1314/tokenLogin1.0.git
一、准備工作
新建一個數據庫,數據庫名字是tokenLogin,數據庫內新建兩張表,第一張是用戶賬戶信息表,第二張是轉賬、入賬、出賬記錄表,分別如下所示:
1. sys_user用戶賬戶信息表:
CREATE TABLE tokenLogin.sys_user( `id` bigint NOT NULL comment 'ID ', `username` varchar(50) comment '用戶名', `password` varchar(50) comment '密碼', PRIMARY KEY (`id`) ); insert into tokenLogin.sys_user values('1' , 'admmin' , '1') insert into tokenLogin.sys_user values('2' , 'superadmmin' , '11') insert into tokenLogin.sys_user values('3' , 'user' , '111') alter table tokenLogin.sys_user add column account double default null;
接着對account進行賦值,賦值完成后表內容如下:
2. 轉賬記錄表:
CREATE TABLE tokenLogin.trasf_record( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) default null, `account_time` TIMESTAMP DEFAULT now() , /*交易時間,默認是幾率生成的時間,也就是交易操作完成的時間*/ `old_account` double default null, /*原賬戶的余額*/ `new_account` double default null, /*交易后賬戶最新余額*/ `target_account` varchar(50) default null , /*交易對方賬戶*/ `account_type` varchar(50) default null , /*交易類型*/ PRIMARY KEY (`id`) ); alter table tokenLogin.trasf_record add column transaction_amount double default null after old_account ; /*在原賬戶余額和交易后賬戶余額中間插入交易余額*/
創建一張空表即可,后面產生交易的時候將數據插入,實現資金追溯。
3. 常量設置:在轉賬記錄表中,有一個字段account_type , 這個字段無非有兩個結果,要么是入賬類型,要么是出賬類型,所以這里我們進行常量設置。
在constants包下面新建TransactionType類,類下內容如下:
/** * @author yeyuting * @create 2021/2/18 */ public class TransactionType { public static final String SAVEMONEY = "入賬" ; public static final String WITHDRAWMONEY = "出賬" ; }
這樣一來,准備工作就做好了,現在我們依次來實現賬戶余額查詢、轉賬、入賬和出賬記錄。
二、賬戶余額查詢
1. 首先控制層創建余額查詢接口:
@GetMapping("/selectByUserName") public Result selectByUserName(@RequestParam("userName") String username){ return Results.successWithData(userService.selectByUserName(username) , BaseEnums.SUCCESS.code()) ; }
2. service層進行數據傳遞:
//UserService類: public User selectByUserName(String username) ; //UserServiceImpl類: //查詢金額 public User selectByUserName(String username) { return userMapper.selectByUserName(username) ; }
3. mapper層,將參數進行傳遞並和數據庫打交道:
UserMapper.java:
public User selectByUserName(String username) ;
userMapper.xml:
<!--查詢金額--> <select id="selectByUserName" resultType="User"> select * from sys_user where username = #{userName} </select>
4. 進行登陸操作,訪問LoginCheck接口,生成對應的token,將token塞到余額查詢接口的頭信息中,過攔截器,進而順利執行接口代碼邏輯。
4. postman前端模擬:
這樣一來,最簡單的賬戶余額查詢就實現了。
三、轉賬功能實現:
1. controller層創建轉賬接口:
@PostMapping("/transferAccount") public Result transferAccount (@RequestParam("accountMoney") Double accountMoney , @RequestParam("targetAccount") String targetAccount , HttpServletRequest request){ return Results.successWithData(userService.transferAccount(accountMoney , targetAccount , request) , BaseEnums.SUCCESS.code()) ; }
2. service層實現:
service接口:
//轉賬 public String transferAccount(Double accountMoney , String targetAccount , HttpServletRequest request) ;
serviceImpl實現:
//轉賬 public String transferAccount(Double accountMoney , String targetAccount , HttpServletRequest request){ Jedis jedis = jedisUtil.getSource() ; String token = request.getHeader("token") ; String userName = jedis.get(token) ; User user = userMapper.selectByName(userName) ; double nowAccountMoney = user.getAccount() ; if(accountMoney > nowAccountMoney){ return "余額不足" ; } User user1 = userMapper.selectByName(targetAccount) ; if (user1.equals(null)){ return "對方賬戶不存在" ; } //轉出賬戶余額更新 boolean result = userMapper.updateAccountOut(accountMoney , userName) ; //轉入賬戶余額更新 boolean result1 = userMapper.updateAccountIn(accountMoney , user1.getUserName()) ; if ((result == false)||(result1 == false) ){ return "轉賬操作失敗" ; } //轉賬記錄生成------------ //String accountType = TransactionType.WITHDRAWMONEY ; //出賬記錄生成 boolean insertReult = userMapper.accountOutInsert(userName ,user.getAccount() , accountMoney , targetAccount , TransactionType.WITHDRAWMONEY ) ; //入賬記錄生成 //String accountType1 = TransactionType.SAVEMONEY ; boolean insertReult1 = userMapper.accountInInsert(user1.getUserName() , user1.getAccount() , accountMoney , user.getUserName() , TransactionType.SAVEMONEY ) ; if((insertReult == false) || (insertReult1 == false)){ return "轉賬記錄生成失敗" ; } return "轉賬成功!" ; }
service實現中每一行代碼都有詳細的講解,總的來說,就是要實現出賬方賬戶余額相應減少,入賬方賬戶余額相應增加,同時生成對應的轉賬記錄。
3. mapper層實現:
//轉出更新 public boolean updateAccountOut (Double accountMoney , String userName) ; //轉入更新 public boolean updateAccountIn (Double accountMoney , String userName) ; //轉出記錄插入 public boolean accountOutInsert(String userName ,Double account , Double accountMoney , String targetAccount , String accountType) ; //轉入記錄插入 public boolean accountInInsert(String userName ,Double account , Double accountMoney , String targetAccount , String accountType) ;
<update id="updateAccountOut"> update sys_user set account = (account - #{accountMoney}) where username = #{userName} </update> <update id="updateAccountIn"> update sys_user set account = (account + #{accountMoney}) where username = #{userName} </update> <insert id="accountOutInsert"> insert into trasf_record ( username , old_account ,transaction_amount , new_account , target_account , account_type ) values ( #{userName} ,#{account} , #{accountMoney} , (#{account} - #{accountMoney}) , #{targetAccount} , #{accountType}) </insert> <insert id="accountInInsert"> insert into trasf_record (username , old_account ,transaction_amount , new_account , target_account , account_type ) values (#{userName} ,#{account} , #{accountMoney} , (#{account} + #{accountMoney}) , #{targetAccount} , #{accountType}) </insert>
4. postman前端模擬:
將上面生成的token塞到轉賬接口頭信息中,訪問數據庫:
數據庫信息刷新:
這樣一來,轉賬功能也就實現了,在充分理解了轉賬功能后,入賬出賬功能就迎刃而解了。接下來繼續實現賬戶入賬和出賬功能。
四、入賬功能
1. controller層:
//存錢 @PostMapping("/saveMoney") public Result saveMoney (@RequestParam("accountMoney") Double accountMoney , HttpServletRequest request){ return Results.successWithData(userService.saveMoney(accountMoney , request) , BaseEnums.SUCCESS.code()) ; }
2. service層:
service接口:
//存錢 public String saveMoney(Double accountMoney , HttpServletRequest request) ;
serviceImpl實現:
//存錢 public String saveMoney(Double accountMoney , HttpServletRequest request){ Jedis jedis = jedisUtil.getSource() ; String token = request.getHeader("token") ; String userName = jedis.get(token) ; User user = userMapper.selectByName(userName) ; //存入余額更新 boolean result = userMapper.updateAccountIn(accountMoney , userName) ; if(result = false){ return "存入失敗" ; } //存入記錄生成 boolean insertResult = userMapper.accountInInsert(userName ,user.getAccount() , accountMoney , userName , TransactionType.SAVEMONEY) ; if((insertResult == false)){ return "入賬記錄生成失敗" ; } return "成功存入" + accountMoney + "元!" ; }
3. mapper層和轉賬公用一套代碼。
4. postman前端實現:
和轉賬一樣,要記得將token塞進頭信息中。
執行后結果如下:
數據庫刷新結果如下:
五、出賬功能
1. controller層:
//取錢 @PostMapping("withdrawMoney") public Result withdrawMoney (@RequestParam("accountMoney") Double accountMoney , HttpServletRequest request){ return Results.successWithData(userService.withdrawMoney(accountMoney , request) , BaseEnums.SUCCESS.code()) ; }
2. service層:
service接口:
//取錢 public String withdrawMoney(Double accountMoney , HttpServletRequest request) ;
serviceImpl具體實現:
//取錢 public String withdrawMoney(Double accountMoney , HttpServletRequest request){ Jedis jedis = jedisUtil.getSource() ; String token = request.getHeader("token") ; String userName = jedis.get(token) ; User user = userMapper.selectByName(userName) ; double nowAccountMoney = user.getAccount() ; if(accountMoney > nowAccountMoney){ return "余額不足" ; } boolean result = userMapper.updateAccountOut(accountMoney , userName) ; if(result = false){ return "取錢失敗" ; } //出賬記錄生成 boolean insertResult = userMapper.accountOutInsert(userName ,user.getAccount() , accountMoney , userName , TransactionType.WITHDRAWMONEY) ; if((insertResult == false)){ return "出賬記錄生成失敗" ; } return "成功取出" + accountMoney + "元!" ; }
3. mapper層和轉賬公用一套代碼。
4. postman前端實現:
和轉賬一樣,要記得將token塞進頭信息中。
這樣一來,出賬功能也就實現了。
待解決問題:
1. redis暫未實現redis緩存對象,因此每次訪問redis只是為了拿到token和對應的value,並未真正的利用到redis,因此,后期要將對象完整的存入到redis中,便於后期數據的獲取。
2. 這里的轉賬記錄表還可以做成索引表,每個用戶單列一張表出來,更加的淺顯易懂,但是任務量過大,需商榷后再決定是否將整表分開。
至此,結束。