处理 transfer 请求的 servlet
package com.wsd.web; 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; /** * @description: * @author: Mr.Wang * @create: 2023-07-02 00:52 **/ @WebServlet("transfer") public class AccountServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取页面表单数据 String fromActno = req.getParameter("fromActno"); String toActno = req.getParameter("toActno"); Double money = Double.parseDouble( req.getParameter("money") ) ; //调用service } }
AccountService interface:
package com.wsd.service; public interface AccountService { void transfer(String fromActno, String toActno, double money); }
dao interface
package com.wsd.dao; import com.wsd.pojo.Account; /** * @author: Mr.Wang * @create: 2023-07-02 01:30 **/ public interface AccountDao { /** * 根据账号获取账户信息 * @param actno 账号 * @return 账户信息 */ Account selectByActno(String actno); /** * 更新账户信息 * @param act 账户信息 * @return 1表示更新成功,其他值表示失败 */ int update(Account act); }
实现类:
package com.wsd.dao.impl; import com.wsd.dao.AccountDao; import com.wsd.pojo.Account; import com.wsd.util.SqlSessionUtil; import org.apache.ibatis.session.SqlSession; /** * @author: Mr.Wang * @create: 2023-07-02 01:36 **/ public class AccountDaoImpl implements AccountDao { @Override public Account selectByActno(String actno) { //Get a SqlSession instance SqlSession sqlSession = SqlSessionUtil.openSession(); //执行 selectByActno Account act = (Account)sqlSession.selectOne("selectByActno", actno); sqlSession.close(); return act; } @Override public int update(Account act) { //Get a SqlSession instance SqlSession sqlSession = SqlSessionUtil.openSession(); //执行 update int count = sqlSession.update("update", act); sqlSession.commit(); sqlSession.close(); return count; } }
AccountMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="account"> <select id="selectByActno" resultType="com.wsd.pojo.Account"> select * from t_act where actno = #{actno} </select> <update id="update"> update t_act set balance = #{balance} where actno = #{actno} </update> </mapper>
定义 MoneyNotEnoughExcecption
转账操作时,余额不足的情况下使用
package com.wsd.exception; /** * @author: Mr.Wang * @create: 2023-07-02 09:06 **/ public class MoneyNotEnoughExcecption extends Exception{ public MoneyNotEnoughExcecption() { } public MoneyNotEnoughExcecption(String message) { super(message); } }
修改接口,抛出异常
package com.wsd.service; public interface AccountService { void transfer(String fromActno, String toActno, double money) throws Exception; }
操作数据库失败时使用的异常
package com.wsd.exception; /** * @author: Mr.Wang * @create: 2023-07-02 11:57 **/ public class AppException extends Exception { public AppException() { } public AppException(String message) { super(message); } }
service 实现类
package com.wsd.service.impl; import com.wsd.dao.AccountDao; import com.wsd.dao.impl.AccountDaoImpl; import com.wsd.exception.AppException; import com.wsd.exception.MoneyNotEnoughException; import com.wsd.pojo.Account; import com.wsd.service.AccountService; /** * @author: Mr.Wang * @create: 2023-07-02 01:19 **/ public class AccountServiceImpl implements AccountService { private AccountDao accountDao = new AccountDaoImpl(); @Override public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException,AppException{ // 查询转出账户的余额 Account fromAct = accountDao.selectByActno(fromActno); //余额不足,抛出异常 if (fromAct.getBalance() < money) { throw new MoneyNotEnoughException("对不起,您的余额不足。"); } // 程序如果执行到这里说明余额充足 // 修改账户余额 Account toAct = accountDao.selectByActno(toActno); fromAct.setBalance(fromAct.getBalance() - money); toAct.setBalance(toAct.getBalance() + money); // 更新数据库 int count = accountDao.update(fromAct); count += accountDao.update(toAct); if (count != 2) { throw new AppException("转账失败,未知原因!"); } } }
修改接口抛出的异常:
package com.wsd.service; import com.wsd.exception.AppException; import com.wsd.exception.MoneyNotEnoughException; public interface AccountService { void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException; }
继续实现servlet:
package com.wsd.web; import com.wsd.exception.AppException; import com.wsd.exception.MoneyNotEnoughException; import com.wsd.service.AccountService; import com.wsd.service.impl.AccountServiceImpl; 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; /** * @description: * @author: Mr.Wang * @create: 2023-07-02 00:52 **/ @WebServlet("/transfer") public class AccountServlet extends HttpServlet { private AccountService accountService = new AccountServiceImpl(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取页面表单数据 String fromActno = req.getParameter("fromActno"); String toActno = req.getParameter("toActno"); Double money = Double.parseDouble( req.getParameter("money") ) ; //调用service try { accountService.transfer(fromActno,toActno,money); //Show the result after transfer success resp.sendRedirect(req.getContextPath() + "/success.html"); } catch (MoneyNotEnoughException e) { resp.sendRedirect(req.getContextPath() + "/error1.html"); } catch (AppException e) { resp.sendRedirect(req.getContextPath() + "/error2.html"); } } }
error1.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>transfer result</title> </head> <body> <h1>The transfer failed because of insufficient balance</h1> </body> </html>
error2.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>transfer result</title> </head> <body> <h1>The transfer failed, error occurred</h1> </body> </html>
success.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>transfer result</title> </head> <body> <h1>The transfer success</h1> </body> </html>
运行:
tomcat 乱码
tomcat的/conf/logging.properties
Restart server
或则 修改idea 控制台的 编码方式为 utf-8,使与tomcat log 使用的 编码方式保持一致
在IDEA里修改idea64.exe.vmoptions
菜单Help -> Edit Custom VM Options,在末尾增加如下代码,重启 idea
-Dfile.encoding=UTF-8test:
模拟异常
package com.wsd.service.impl; import com.wsd.dao.AccountDao; import com.wsd.dao.impl.AccountDaoImpl; import com.wsd.exception.AppException; import com.wsd.exception.MoneyNotEnoughException; import com.wsd.pojo.Account; import com.wsd.service.AccountService; /** * @author: Mr.Wang * @create: 2023-07-02 01:19 **/ public class AccountServiceImpl implements AccountService { private AccountDao accountDao = new AccountDaoImpl(); @Override public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException,AppException{ // 查询转出账户的余额 Account fromAct = accountDao.selectByActno(fromActno); //余额不足,抛出异常 if (fromAct.getBalance() < money) { throw new MoneyNotEnoughException("对不起,您的余额不足。"); } // 程序如果执行到这里说明余额充足 // 修改账户余额 Account toAct = accountDao.selectByActno(toActno); fromAct.setBalance(fromAct.getBalance() - money); toAct.setBalance(toAct.getBalance() + money); // 更新数据库 int count = accountDao.update(fromAct); //模拟异常 String s = null; s.toString(); count += accountDao.update(toAct); if (count != 2) { throw new AppException("转账失败,未知原因!"); } } }
retest :
before test
出现异常
after test:
数据不一致
reason:
public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException,AppException{ // 查询转出账户的余额 Account fromAct = accountDao.selectByActno(fromActno); //余额不足,抛出异常 if (fromAct.getBalance() < money) { throw new MoneyNotEnoughException("对不起,您的余额不足。"); } // 程序如果执行到这里说明余额充足 // 修改账户余额 Account toAct = accountDao.selectByActno(toActno); fromAct.setBalance(fromAct.getBalance() - money); toAct.setBalance(toAct.getBalance() + money); // 更新数据库 int count = accountDao.update(fromAct); //模拟异常 String s = null; s.toString(); count += accountDao.update(toAct); if (count != 2) { throw new AppException("转账失败,未知原因!"); } }
1.更新 table
2.模拟异常
3.更新table
2 出现异常后,3没有执行
1.3 没有形成一个事务