银行转账案例
[1] 案例需求
用戶訪問登錄頁(yè)面,在頁(yè)面中輸入用戶名和密碼點(diǎn)擊登錄,登錄成功后 進(jìn)入到主頁(yè)中。如果登錄敗,則在登錄頁(yè)面中提示用戶用戶名或密碼錯(cuò)誤。在主頁(yè)面中,用戶在填寫銀行轉(zhuǎn)賬信息,包括:轉(zhuǎn)賬賬戶,轉(zhuǎn)賬賬 戶密碼,轉(zhuǎn)賬金額,收款賬號(hào),收款人姓名。點(diǎn)擊開始轉(zhuǎn)賬,完成轉(zhuǎn)賬。但是有如下特殊需求:
① 需要用戶的登錄日志。
② 當(dāng)轉(zhuǎn)賬賬戶的密碼失去焦點(diǎn)時(shí),檢驗(yàn)轉(zhuǎn)賬賬戶信息是否存在。
③在轉(zhuǎn)賬金額失去焦點(diǎn)時(shí),校驗(yàn)金額是否正確。
④ 收款人姓名失去焦點(diǎn)時(shí),校驗(yàn)收款人信息是否正確
⑤ 當(dāng)所有的信息驗(yàn)證無(wú)誤后,才能轉(zhuǎn)賬。
[2] 案例頁(yè)面效果圖
① 登錄頁(yè)面效果圖
② 轉(zhuǎn)賬主頁(yè)面效果圖
[3] 功能分析
① 創(chuàng)建登錄頁(yè)面
② 用戶登錄以及登錄失敗提示語(yǔ)
③ 登錄日志
④ 創(chuàng)建銀行轉(zhuǎn)賬頁(yè)面
⑤ 轉(zhuǎn)賬賬戶信息校驗(yàn)
⑥ 金額校驗(yàn)
⑦ 入賬賬戶信息校驗(yàn)
⑧ 轉(zhuǎn)賬功能
[4] 數(shù)據(jù)庫(kù)設(shè)計(jì)
① 用戶信息表: t_user
字段名 中文名 類型 大小 約束
uid 用戶編號(hào) int 10 主鍵、非空
uname 用戶名 varchar 100 非空
pwd 密碼 varchar 100 非空
② 銀行賬戶信息表:t_account
字段名 中文名 類型 大小 約束
aid 賬戶編號(hào) int 10 主鍵、非空
apwd 支付密碼 varchar 100 非空
money 賬戶金額 double
uid 用戶編號(hào) int 10 非空
[5] 功能實(shí)現(xiàn)
1. 完成數(shù)據(jù)庫(kù)的變現(xiàn)
-- ---------------------------- -- Table structure for `t_account` -- ---------------------------- DROP TABLE IF EXISTS `t_account`; CREATE TABLE `t_account` (`aid` int(10) NOT NULL AUTO_INCREMENT,`apwd` varchar(100) NOT NULL,`money` double DEFAULT NULL,`uid` int(10) NOT NULL,PRIMARY KEY (`aid`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of t_account -- ---------------------------- INSERT INTO `t_account` VALUES ('1', '123', '10000', '1'); INSERT INTO `t_account` VALUES ('2', '456', '10000', '2');-- ---------------------------- -- Table structure for `t_user` -- ---------------------------- DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` (`uid` int(10) NOT NULL AUTO_INCREMENT,`uname` varchar(100) NOT NULL,`pwd` varchar(100) NOT NULL,PRIMARY KEY (`uid`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ---------------------------- -- Records of t_user -- ---------------------------- INSERT INTO `t_user` VALUES ('1', '張三', '123'); INSERT INTO `t_user` VALUES ('2', '李四', '456');2. 搭建Spring+Mybatis項(xiàng)目開發(fā)的環(huán)境
(1) 創(chuàng)建web項(xiàng)目
(2) 在web-inf下創(chuàng)建lib文件夾,并導(dǎo)入整合的jar包
(3) 在src創(chuàng)建MVC的包結(jié)構(gòu)
注意:將表的實(shí)體類文件創(chuàng)建
(4) 在src下創(chuàng)建spring的配置文件
(5) 在web.xml文件中配置Spring文件路徑和監(jiān)聽器
3. 創(chuàng)建登錄頁(yè)面
效果圖:
代碼示例:
<%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><base href="<%=basePath %>"/><title>Title</title> </head> <body><h3 align="center">歡迎登錄502班級(jí)銀行轉(zhuǎn)賬系統(tǒng)</h3><hr><div style="width: 400px;margin: auto"><form action="userLogin" method="post"><table style="margin: auto;margin-top: 30px;" cellpadding="10px"><tr><td>用戶名:</td><td><input type="text" name="uname" value=""></td></tr><tr><td>密碼:</td><td><input type="password" name="pwd" value=""></td></tr><tr><td colspan="2"><input type="submit" value="點(diǎn)擊登錄"></td></tr></table></form></div> </body> </html>4. 完成登錄功能
(1) 創(chuàng)建UserServlet,處理登錄請(qǐng)求
package com.java.controller; import com.java.pojo.User; import com.java.service.UserService; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; 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 javax.servlet.http.HttpSession; import java.io.IOException;@WebServlet(value = "/userLogin",loadOnStartup = 1) public class UserServlet extends HttpServlet {//聲明init方法,完成Spring資源的初始化加載private UserService us;@Overridepublic void init() throws ServletException {//獲取Spring容器對(duì)象ApplicationContext ac= WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());//獲取業(yè)務(wù)層對(duì)象us= (UserService) ac.getBean("us");}//聲明service方法,完成請(qǐng)求的處理@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//設(shè)置請(qǐng)求編碼格式req.setCharacterEncoding("utf-8");//設(shè)置響應(yīng)編碼格式resp.setContentType("text/html;charset=utf-8");resp.setCharacterEncoding("utf-8");//獲取請(qǐng)求信息String uname=req.getParameter("uname");String pwd=req.getParameter("pwd");//處理請(qǐng)求//調(diào)用業(yè)務(wù)層方法根據(jù)用戶名和密碼獲取用戶信息User user = us.userLoginService(uname, pwd);//響應(yīng)處理結(jié)果//獲取Session對(duì)象HttpSession session=req.getSession();//響應(yīng)if(user!=null){//將用戶信息存儲(chǔ)到session中session.setAttribute("user",user);//重定向到主頁(yè)面resp.sendRedirect(req.getContextPath()+"/main.jsp");}else{//增加失敗標(biāo)記session.setAttribute("flag","userFail");//重定向到登錄頁(yè)面resp.sendRedirect(req.getContextPath()+"/login.jsp");}} }(2) 創(chuàng)建UserService,處理登錄請(qǐng)求
package com.java.service.impl; import com.java.mapper.UserMapper; import com.java.pojo.User; import com.java.service.UserService; public class UserServiceImpl implements UserService {//聲明mapper層屬性private UserMapper userMapper;public UserMapper getUserMapper() {return userMapper;}public void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;}//用戶登錄@Overridepublic User userLoginService(String uname, String pwd) {return userMapper.userLoginMapper(uname,pwd);} }(3) 創(chuàng)建UserMapper,根據(jù)用戶名和密碼獲取用戶信息
package com.java.mapper; import com.java.pojo.User; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; public interface UserMapper {//根據(jù)用戶名和密碼獲取用戶信息@Select("select * from t_user where uname=#{uname} and pwd=#{pwd}")User userLoginMapper(@Param("uname") String uname, @Param("pwd") String pwd); }(4) 在applicationcontext.xml文件中配置業(yè)務(wù)層bean
<!--配置業(yè)務(wù)層bean--><bean id="us" class="com.bjsxt.service.impl.UserServiceImpl"><property name="userMapper" ref="userMapper"></property></bean>5. 創(chuàng)建main.jsp主頁(yè)面
① 頁(yè)面示例圖:
② 代碼示例:
<%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><base href="<%=basePath %>"/><title>Title</title><%--引入jquery文件--%><script type="text/javascript" src="js/j.js"></script><%--聲明js代碼域--%><script type="text/javascript">//聲明頁(yè)面加載事件$(function () {//創(chuàng)建顏色數(shù)組var colors=["red","yellow","black","green","gray","blue","brown","darhorchid"];//使用間隔執(zhí)行window.setInterval(function () {//獲取0-8的隨機(jī)整數(shù),含0不含8var index=Math.floor(Math.random()*colors.length);//設(shè)置標(biāo)題顏色$("#title").css("color",colors[index]);},100)})</script> </head> <body><%--網(wǎng)頁(yè)的主題--%><h3 align="center"><%--跑馬燈效果--%><marquee width=400 behavior=alternate direction=left align=middle><font color="r" id="title">歡迎${sessionScope.user.uname}登錄502班級(jí)銀行轉(zhuǎn)賬系統(tǒng)</font></marquee></h3><%--水平線--%><hr><%--銀行轉(zhuǎn)賬表單--%><div style="width: 400px;margin: auto;"><form action=""><table style="margin: auto;margin-top: 30px;" cellpadding="10px"><tr><td>轉(zhuǎn)賬賬戶:</td><td><input type="text" name="outId" value=""></td></tr><tr><td>轉(zhuǎn)賬賬戶密碼:</td><td><input type="password" name="outPwd" value=""></td></tr><tr><td>金額:</td><td><input type="text" name="money" value=""></td></tr><tr><td>收款賬號(hào):</td><td><input type="text" name="inId" value=""></td></tr><tr><td>收款人姓名:</td><td><input type="text" name="inName" value=""></td></tr><tr><td colspan="2"><input type="submit" value="開始轉(zhuǎn)賬"></td></tr></table></form></div> </body> </html>6. 完成轉(zhuǎn)賬賬戶信息的校驗(yàn)
(1) 功能點(diǎn)需求:
用戶在輸入賬戶以及密碼后,在密碼失去焦點(diǎn)后,觸發(fā)校驗(yàn)。如果正確則在密碼框 后顯示√,錯(cuò)誤則顯示X.
(2) 功能點(diǎn)分析:
通過需求我們發(fā)現(xiàn),校驗(yàn)的結(jié)果是在當(dāng)前頁(yè)面中繼續(xù)顯示的。相當(dāng)于我們?cè)诋?dāng)前 頁(yè)面中顯示新的響應(yīng)結(jié)果 ,確定該功能使用ajax技術(shù)來(lái)實(shí)現(xiàn)。
(3) 前臺(tái)分析:
① ajax請(qǐng)求的觸發(fā)時(shí)機(jī):在密碼框失去焦點(diǎn)時(shí)觸發(fā)
② ajax請(qǐng)求的請(qǐng)求地址: Servlet的別名,checkAccount
③ ajax請(qǐng)求的請(qǐng)求數(shù)據(jù):賬戶和密碼
④ ajax請(qǐng)求的響應(yīng)數(shù)據(jù):true或者false的字符串
(4) 前臺(tái)代碼實(shí)現(xiàn):
//給密碼框添加焦點(diǎn)事件,完成校驗(yàn) $(function () {$("#outdPwd").blur(function () {//發(fā)起ajax請(qǐng)求$.post("checkAccount",{outId:$("#outId").val(),outPwd:$("#outdPwd").val(),methodName=”checkOutInfo”},function (data) {if(eval(data)){$("#outSpan").html("√").css("color","green");}else{$("#outSpan").html("X").css("color","red");}})}) })(5) 后臺(tái)分析:
① 創(chuàng)建Servlet,處理轉(zhuǎn)賬賬戶信息校驗(yàn)。checkAccount 注意:有,響應(yīng)”true”,沒有,響應(yīng)”false”
② 創(chuàng)建Service,處理賬戶信息校驗(yàn)。
③ 創(chuàng)建mapper,根據(jù)賬戶ID和密碼獲取賬戶信息。
(6) 后臺(tái)代碼實(shí)現(xiàn):
CheckAccountServlet
//聲明方法:校驗(yàn)轉(zhuǎn)賬賬戶信息private void checkOutInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//獲取請(qǐng)求信息String outId=req.getParameter("outId");String outPwd=req.getParameter("outPwd");//處理請(qǐng)求//調(diào)用業(yè)務(wù)層方法Account account = checkAccountService.checkOutAccountInfoService(outId, outPwd);//響應(yīng)結(jié)果resp.getWriter().write(account!=null?"true":"false");}CheckAccountService
//校驗(yàn)轉(zhuǎn)賬賬戶信息Account checkOutAccountInfoService(String outId,String outPwd);CheckAccountServiceImpl
//校驗(yàn)轉(zhuǎn)賬賬戶信息@Overridepublic Account checkOutAccountInfoService(String outId, String outPwd) {return checkAccountMapper.checkAccountOutInfoMapper(outId,outPwd);}CheckAccountMapper
//校驗(yàn)轉(zhuǎn)賬賬戶信息:根據(jù)賬戶ID和密碼獲取賬戶信息@Select("select * from t_account where aid=#{outId} and apwd=#{outPwd}")Account checkAccountOutInfoMapper(@Param("outId") String outId, @Param("outPwd") String outPwd);7. Servlet的優(yōu)化
(1) 問題:
目前我們每實(shí)現(xiàn)一個(gè)功能點(diǎn),就需要在后臺(tái)聲明一個(gè)對(duì)應(yīng)的Servlet進(jìn)行 請(qǐng)求的處理。這樣造成Servlet聲明過多,代碼繁瑣。
(2) 解決:
Servlet只聲明一個(gè),讓所有的相關(guān)請(qǐng)求,都請(qǐng)求該Servlet。 在該Servlet中的service方法中,不做具體的請(qǐng)求處理。在Service中,根據(jù)請(qǐng)求,調(diào)用對(duì)應(yīng)的邏輯代碼來(lái)處理請(qǐng)求即可。 類似:main方法的機(jī)制。
(3) 實(shí)現(xiàn):
在Servlet中將不同請(qǐng)求的處理邏輯代碼封裝成對(duì)應(yīng)的邏輯功能方法 然后在service方法中,根據(jù)請(qǐng)求調(diào)用對(duì)應(yīng)的邏輯方法處理請(qǐng)求。每次請(qǐng)求都需要在請(qǐng)求數(shù)據(jù)中攜帶要請(qǐng)求的方法的方法名。后臺(tái)service中 根據(jù)請(qǐng)求數(shù)據(jù)中的方法名調(diào)用對(duì)應(yīng)的邏輯方法即可。
package com.java.controller; import com.java.pojo.Account; import com.java.service.CheckAccountService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; 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(value = "/checkAccount",loadOnStartup = 2) public class CheckAccountServlet extends HttpServlet {//聲明業(yè)務(wù)層屬性private CheckAccountService checkAccountService;//重寫init方法@Overridepublic void init() throws ServletException {//獲取Spring容器對(duì)象ApplicationContext ac=new ClassPathXmlApplicationContext("applicationcontext.xml");//獲取業(yè)務(wù)層對(duì)象checkAccountService= (CheckAccountService) ac.getBean("checkAccountService");}//重寫service方法@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//設(shè)置請(qǐng)求編碼格式req.setCharacterEncoding("utf-8");//設(shè)置響應(yīng)編碼格式resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");//獲取請(qǐng)求數(shù)據(jù)中的方法名String methodName=req.getParameter("methodName");//根據(jù)請(qǐng)求調(diào)用對(duì)應(yīng)的邏輯代碼if("checkOutInfo".equals(methodName)){checkOutInfo(req,resp);}else if("checkMoneyInfo".equals(methodName)){checkMoneyInfo(req,resp);}else if("checInInfo".equals(methodName)){checInInfo(req,resp);}else if("transferInfo".equals(methodName)){transferInfo(req,resp);}else{System.out.println("沒有對(duì)應(yīng)的邏輯方法:"+methodName);}}//轉(zhuǎn)賬private void transferInfo(HttpServletRequest req, HttpServletResponse resp) {}//校驗(yàn)收款人信息private void checInInfo(HttpServletRequest req, HttpServletResponse resp) {}//校驗(yàn)金額private void checkMoneyInfo(HttpServletRequest req, HttpServletResponse resp) {}//聲明方法:校驗(yàn)轉(zhuǎn)賬賬戶信息private void checkOutInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//獲取請(qǐng)求信息String outId=req.getParameter("outId");String outPwd=req.getParameter("outPwd");//處理請(qǐng)求//調(diào)用業(yè)務(wù)層方法Account account = checkAccountService.checkOutAccountInfoService(outId, outPwd);//響應(yīng)結(jié)果resp.getWriter().write(account!=null?"true":"false");}}8. 校驗(yàn)金額
(1) 功能點(diǎn)需求:
用戶在金額框中輸入要轉(zhuǎn)賬的金額信息后,失去焦點(diǎn)時(shí),完成金額信息的校驗(yàn)。 余額足夠則在金額框后顯示√,否則顯示X
(2) 功能分析:
使用ajax技術(shù)。
① 前臺(tái)分析
i. 給金額框增加焦點(diǎn)事件
ii. 發(fā)起ajax請(qǐng)求
iii. 請(qǐng)求數(shù)據(jù)為金額,轉(zhuǎn)賬賬戶Id,后臺(tái)邏輯方法名
iv. 響應(yīng)數(shù)據(jù)為true或者false的字符串
示例代碼:
/*********************轉(zhuǎn)賬金額校驗(yàn)**************************************/ $(function () {$("#money").blur(function () {//發(fā)起ajax請(qǐng)求$.post("checkAccount",{outId:$("#outId").val(),money:$("#money").val(),methodName:"checkMoneyInfo"},function (data) {if(eval(data)){$("#moneySpan").html("√").css("color","green");}else{$("#moneySpan").html("X").css("color","red");}})})})② 后臺(tái)分析:
i. 在CheckAccountServlet中聲明金額校驗(yàn)邏輯方法,并在service方法完成調(diào)用
ii. 在CheckAccountService中新增金額校驗(yàn)的業(yè)務(wù)方法
//校驗(yàn)金額Account checkMoneyInfoService(String outId, String money); //校驗(yàn)金額@Overridepublic Account checkMoneyInfoService(String outId, String money) {return checkAccountMapper.checkMoneyInfoMapper(outId,money);}iii. 在CheckAccountMapper中新增金額校驗(yàn)的數(shù)據(jù)庫(kù)操作
//校驗(yàn)金額 @Select("select * from t_account where aid=#{outId} and money>=#{money}") Account checkMoneyInfoMapper(@Param("outId") String outId, @Param("money") String money);9. 收款人信息校驗(yàn)
(1) 功能點(diǎn)需求:
用戶在收款人姓名失去焦點(diǎn)時(shí),校驗(yàn)收款人信息。存在,則在收款人姓名框后顯示 √,不存在則顯示X
(2) 功能分析
i. 給收款人姓名框增加焦點(diǎn)事件
ii. 發(fā)起ajax請(qǐng)求完成校驗(yàn)
iii. 請(qǐng)求數(shù)據(jù)為收款人賬戶ID,收款人姓名,后臺(tái)邏輯方法名
iv. 響應(yīng)數(shù)據(jù) true或者false的字符串
代碼示例:
/*********************收款人信息校驗(yàn)**************************************/$(function () {$("#inName").blur(function () {//發(fā)起ajax請(qǐng)求$.post("checkAccount",{inId:$("#inId").val(),inName:$("#inName").val(),methodName:"checInInfo"},function (data) {if(eval(data)){$("#inNameSpan").html("√").css("color","green");}else{$("#inNameSpan").html("X").css("color","red");}})})})i. 在CheckAccountServlet中聲明對(duì)應(yīng)的邏輯方法完成校驗(yàn)
ii. 在CheckAccountService中聲明業(yè)務(wù)方法
//校驗(yàn)收款人信息Account checkInInfoService(String inId, String inName); //校驗(yàn)收款人信息@Overridepublic Account checkInInfoService(String inId, String inName) {return checkAccountMapper.checkInInfoMapper(inId,inName);}iii. 在CheckAccountMapper中聲明數(shù)據(jù)庫(kù)操作
//校驗(yàn)收款人信息@Select("select a.* from t_account a join t_user u on a.uid=u.uid where a.aid=#{inId} and u.uname=#{inName}")Account checkInInfoMapper(@Param("inId") String inId, @Param("inName") String inName);10. 開始轉(zhuǎn)賬
(1) 功能點(diǎn)需求:
點(diǎn)擊開始轉(zhuǎn)賬時(shí),保證所有的轉(zhuǎn)賬信息是正確的,如果有錯(cuò)誤的轉(zhuǎn)賬信息 提示用戶,請(qǐng)?zhí)顚懻_的信息。如果全部都是正確的,則直接發(fā)起轉(zhuǎn)賬請(qǐng)求,完成轉(zhuǎn)賬。
(2) 功能分析:
① 前臺(tái)分析
i. 給轉(zhuǎn)賬按鈕增加單擊事件
ii. 校驗(yàn)轉(zhuǎn)賬信息是否全部正確
iii. 提交轉(zhuǎn)賬請(qǐng)求
代碼示例:
/*********************轉(zhuǎn)賬賬戶信息校驗(yàn)**************************************///給密碼框添加焦點(diǎn)事件,完成校驗(yàn)$(function () {$("#outdPwd").blur(function () {//發(fā)起ajax請(qǐng)求$.post("checkAccount",{outId:$("#outId").val(),outPwd:$("#outdPwd").val(),methodName:"checkOutInfo"},function (data) {if(eval(data)){$("#outSpan").html("√").css("color","green").addClass("success").removeClass("error");}else{$("#outSpan").html("X").css("color","red").addClass("error").removeClass("success");}})})}) /*********************轉(zhuǎn)賬金額校驗(yàn)**************************************/$(function () {$("#money").blur(function () {//發(fā)起ajax請(qǐng)求$.post("checkAccount",{outId:$("#outId").val(),money:$("#money").val(),methodName:"checkMoneyInfo"},function (data) {if(eval(data)){$("#moneySpan").html("√").css("color","green").addClass("success").removeClass("error");}else{$("#moneySpan").html("X").css("color","red").addClass("error").removeClass("success");}})})}) /*********************收款人信息校驗(yàn)**************************************/$(function () {$("#inName").blur(function () {//發(fā)起ajax請(qǐng)求$.post("checkAccount",{inId:$("#inId").val(),inName:$("#inName").val(),methodName:"checInInfo"},function (data) {if(eval(data)){$("#inNameSpan").html("√").css("color","green").addClass("success").removeClass("error");}else{$("#inNameSpan").html("X").css("color","red").addClass("error").removeClass("success");}})})}) /*********************轉(zhuǎn)賬功能**************************************/$(function () {$("#btn").click(function () {//校驗(yàn)轉(zhuǎn)賬信息是否正確if($(".success").length==3){//提及表單$("#fm").submit();}else{alert("請(qǐng)?zhí)顚懻_的賬戶信息")}})})② 后臺(tái)分析
i. 在CheckAccountServlet中聲明轉(zhuǎn)賬的邏輯方法
//轉(zhuǎn)賬private void transferInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {//獲取請(qǐng)求數(shù)據(jù)String outId=req.getParameter("outId");String inId=req.getParameter("inId");String money=req.getParameter("money");//處理請(qǐng)求int i=checkAccountService.transferInfoService(outId,inId,money);//響應(yīng)結(jié)果if(i>0){resp.sendRedirect(req.getContextPath()+"/success.jsp");}else{resp.sendRedirect(req.getContextPath()+"/error.jsp");}}ii. 在CheckAccountService中聲明轉(zhuǎn)賬的業(yè)務(wù)方法
//轉(zhuǎn)賬功能int transferInfoService(String outId, String inId, String money); //轉(zhuǎn)賬功能@Overridepublic int transferInfoService(String outId, String inId, String money) {//1.出賬int i = checkAccountMapper.transferOut(outId, money);//2.入賬i+=checkAccountMapper.transferIn(inId,money);//返回return i;}iii. 在CheckAccountMapper中完成轉(zhuǎn)賬的數(shù)據(jù)庫(kù)操作
@Update("update t_account set money=money-#{money} where aid=#{outId}")int transferOut(@Param("outId") String outId,@Param("money") String money);//轉(zhuǎn)入@Update("update t_account set money=money+#{money} where aid=#{inId}")int transferIn(@Param("inId") String inId,@Param("money") String money);11. 登錄日志
(1) 功能點(diǎn)需求:
我們的銀行轉(zhuǎn)賬功能,在剛開始運(yùn)營(yíng)的時(shí)候,并沒有用戶登錄的日志信息的記錄。后來(lái),某天某個(gè)客戶他的賬號(hào)被登錄了,但是給該客戶又不知道是什么時(shí)間進(jìn)行的登錄,造成調(diào)查有困擾,怎么辦?在當(dāng)前登錄功能的基礎(chǔ)上,增加登錄日志,來(lái)記 錄用戶的登錄信息。便于我們后期的排查。
(2) 功能分析:
在保留當(dāng)前登錄功能的基礎(chǔ)上,完成對(duì)登錄功能的擴(kuò)展。但是又不希望改變?cè)械墓δ艽a邏輯。考慮使用SpringAOP。
前置通知:在日志文件中輸出XXX在XXX時(shí)間發(fā)起了登錄請(qǐng)求
切點(diǎn):登錄的業(yè)務(wù)方法
后置通知:在日志文件中輸出XXX在XXX時(shí)間登錄成功
建議使用SchemaBased方式實(shí)現(xiàn)。
(3) 功能實(shí)現(xiàn):
i. 在lib下導(dǎo)入AOP的jar包
ii. 在src下創(chuàng)建com.bjsxt.advice的包
iii. 在advice包中創(chuàng)建前置通知和后置通知
后置通知
package com.java.advice;import org.apache.log4j.Logger; import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class MyAfter implements AfterReturningAdvice {@Overridepublic void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {//獲取Log4j的對(duì)象Logger logger = Logger.getLogger(MyAfter.class);//日志輸出if(o!=null){logger.debug(objects[0]+"登錄成功");}} }前置通知
package com.java.advice;import org.apache.log4j.Logger; import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class MyBefore implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {//獲取Log4j的對(duì)象Logger logger = Logger.getLogger(MyBefore.class);//日志輸出logger.debug(objects[0]+"發(fā)起了登錄請(qǐng)求");} }iv. 在src下聲明log4j.properties配置文件
log4j.rootCategory=infolog4j.logger.com.bjsxt.mapper=debug, CONSOLE,LOGFILE log4j.logger.com.bjsxt.advice=debug, CONSOLE,LOGFILE log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=- %c-%d-%m%nlog4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=D:/axis.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=- %c-%d-%m%nv. 在applicationcontext.xml文件中配置通知bean以及組裝規(guī)則
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--配置數(shù)據(jù)源bean--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/502"></property><property name="username" value="root"></property><property name="password" value="1234"></property></bean><!--配置工廠bean--><bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property></bean><!--配置mapper掃描bean--><bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="sqlSessionFactory" ref="factory"></property><property name="basePackage" value="com.bjsxt.mapper"></property></bean><!--配置業(yè)務(wù)層bean--><!--用戶登錄--><bean id="us" class="com.bjsxt.service.impl.UserServiceImpl"><property name="userMapper" ref="userMapper"></property></bean><!--配置信息校驗(yàn)--><bean id="checkAccountService" class="com.bjsxt.service.impl.CheckAccountServiceImpl"><property name="checkAccountMapper" ref="checkAccountMapper"></property></bean><!--配置通知bean--><bean id="before" class="com.bjsxt.advice.MyBefore"></bean><bean id="after" class="com.bjsxt.advice.MyAfter"></bean><!--配置AOP組裝規(guī)則--><aop:config><aop:pointcut id="mp" expression="execution(* com.bjsxt.service.impl.UserServiceImpl.userLoginService(String,String))"/><aop:advisor advice-ref="before" pointcut-ref="mp"></aop:advisor><aop:advisor advice-ref="after" pointcut-ref="mp"></aop:advisor></aop:config><!--開啟cglib代理模式--><aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> </beans>總結(jié)
- 上一篇: 滚动字幕Marquee
- 下一篇: c语言中有关void,sizeof,结构