您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

模拟银行转账(java+mysql+tomcat +JDBC+ druid连接池 + Servlet + Ajax)

模拟银行转账(java+mysql+tomcat +JDBC+ druid连接池 + Servlet + Ajax)

项目准备前提

1.准备数据表
2.准备实验数据
3.jar包准备
4.准备好JDBC工具类

1.准备数据表

创建用户数据表,所需字段有:用户id, 用户姓名, 用户密码, 用户金额.

CREATE TABLE `account` (
  `aid` int(11) NOT NULL AUTO_INCREMENT,
  `uname` varchar(255) DEFAULT NULL,
  `upwd` varchar(255) DEFAULT NULL,
  `balance` decimal(8,2) DEFAULT NULL,
  PRIMARY KEY (`aid`)
) ENGINE=InnoDB;

一个简单数据表创建就完成了

2.准备实验数据

INSERT INTO `account` VALUES (1, 'tesDest','112342', 1200.00);
INSERT INTO `account` VALUES (2, 'segvcw', '223352',680.50);

这边我们插入两条实验数据,用于模拟两个用户.

3.jar包准备

以下是我自己使用的jar包,分别是在项目下的lib目录下和web的项目leb目录下
在这里插入图片描述

注意 : 因为这边是使用web项目所以要先给项目加入web框架
在这里插入图片描述

3.1 加入web框架

选中项目文件夹右键, 点击如图选项:
在这里插入图片描述
勾选如图中的选项,后点击ok
在这里插入图片描述

4.准备JDBC工具类

我们使用JDBC技术时常需要进行许多的重复操作,于是我们可以将一些操作打包成工具类. 方便我们后面的操作.

package com.huawei.util;

import com.alibaba.druid.pool.DruidDataSource;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC工具类【加入事务控制  + 线程 + Druid连接池】
 */
public class DBUtils {
    static String USER=null;
    static String USER_PASS=null;
    static String DB_URL=null;
    static String DRIVER_CLASS=null;
    private static DataSource dataSource;
    //容器变量       [ThreadLocal用于隔离多线程并发 产生的数据混乱]
    private static ThreadLocal<Connection> local = new ThreadLocal<>();
    /**
     * 静态代码块加载属性配置文件
     */
    static {
        Properties config=new Properties();
        try {
            //找到文件
            //InputStream is= JdbcUtil.class.getResourceAsStream("/db.properties");
            InputStream is= DBUtils.class.getClassLoader().getResourceAsStream("db.properties");
            //并读取到内存
            config.load(is);
            //读取属性数据的key
            //DB_URL = config.getProperty("jdbc.url");
            //USER = config.getProperty("jdbc.username");
            //USER_PASS = config.getProperty("jdbc.password");
            DRIVER_CLASS = config.getProperty("jdbc.driverClassName");
            //初始化Durid连接池数据源
            DruidDataSource dds = new DruidDataSource();
            dds.configFromPropety(config);//加载属性文件到数据源对象
            dataSource = dds;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static DataSource getDataSource(){
        return dataSource;
    }

    /**
     * 注册驱动
     */
    static {
        try {
            Class.forName(DRIVER_CLASS);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取链接对象
     * @return
     */
    public static Connection getConn(){
        if(local.get()==null) {//当前线程是否有连接对象
            Connection conn = null;
            try {
                //conn = DriverManager.getConnection(DB_URL, USER, USER_PASS);
                conn = dataSource.getConnection();
                local.set(conn);//放入当前线程对象中
            } catch (Exception e) {
                e.printStackTrace();
            }
            //return conn;
        }
        return local.get();
    }
    /***************事务控制的方法********************/
    public static void beginTransaction() {
        try {
            getConn().setAutoCommit(false);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    public static void commit(){
        try {
            getConn().commit();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    public static void rollback(){
        try {
            getConn().rollback();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    /**
     * 资源释放方法
     * @param conn
     * @param stmt
     * @param rs
     */
    public static void close(Connection conn,Statement stmt,ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        if(stmt!=null){
            try {
                stmt.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.setAutoCommit(true);//设置回默认状态
                conn.close();
                local.remove();//清空当前线程中的数据,防止内存泄漏
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 通用的DML sql语句执行方法
     * @param sql
     * @param params
     * @return
     */
    public static  int update(String sql,Object... params) throws Exception{
        int result=0;
        Connection conn = getConn();
        PreparedStatement psmt=  conn.prepareStatement(sql);
        //获取参数化SQL中的?个数
        int count=  psmt.getParameterMetaData().getParameterCount();
        if(count != params.length){
            return -1;
        }
        //遍历参数个数,从动态数组中取值注入
        for (int i=1;i<=count;i++){
            psmt.setObject(i,params[i-1]);
        }
        //执行SQL
        result = psmt.executeUpdate();
        close(conn,psmt,null);
        return result;
    }

    public static ResultSet query(String sql,Object... params) throws Exception{
        ResultSet result=null;
        Connection conn = getConn();
        PreparedStatement psmt=  conn.prepareStatement(sql);
        //获取参数化SQL中的?个数
        int count=  psmt.getParameterMetaData().getParameterCount();
        if(count != params.length){
            return null;
        }
        //遍历参数个数,从动态数组中取值注入
        for (int i=1;i<=count;i++){
            psmt.setObject(i,params[i-1]);
        }
        //执行SQL
        result = psmt.executeQuery();
        return result;
    }
}

数据库要有配置文件db.properties 放在src目录下

druid.url=jdbc:mysql://localhost:3306/my?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
druid.username=root
druid.password=root
druid.driverClassName=com.mysql.jdbc.Driver
druid.maxActive=8
druid.maxWait=5000

项目开始

前端部分

创建表单,设定处理方法的servlet以及处理方法.

action="/transfer.do" method="post"
<h3>模拟银行转账</h3>
<form action="/transfer.do" method="post">
    <table border="1" cellpadding="0" cellspacing="0">
        <tr width="100px">
            <td>转账人</td>
            <td><input name="fromAc"> </td>
        </tr>
        <tr>
            <td>转账金额</td>
            <td><input name="money"> </td>
        </tr>
        <tr>
            <td>收款人</td>
            <td><input name="toAc"></td>
        </tr>
        <tr colspan="2"><input type="submit" value="提交"></tr>
    </table>
</form>

后端部分

创建实体账户类(根据数据库表中的字段创建属性)
然后生成get/set方法,以及toString方法

我的数据表(如图):
我的数据库为my, 记住数据库引擎必须是InnoDB. 不然无法使用事务
在这里插入图片描述

package com.huawei.entity;

/**
 * 账户实体类
 */
public class Account {
    private int aid;
    private String uname;
    private String upwd;
    private double balance;

    public int getAid() {return aid; }
    public void setAid(int aid) {this.aid = aid;}
    public String getUname() {return uname;}
    public void setUname(String uname) {this.uname = uname;}
    public String getUpwd() {return upwd;}
    public void setUpwd(String upwd) {this.upwd = upwd;}
    public double getBalance() {return balance;}
    public void setBalance(double balance) {this.balance = balance;}

    @Override
    public String toString() {
        return "Account{" +
                "aid=" + aid +
                ", uname='" + uname + '\'' +
                ", upwd='" + upwd + '\'' +
                ", balance=" + balance +
                '}';
    }
}

创建TransactionDao类, 写基本操作方法

public class TransactionDao{
    public QueryRunner runner = null;

    public TransactionDao() {
        this.runner = new QueryRunner();
    }

    //转入方法
    public void transationIn(String name1, double money){
        //TODO
        String sql = "update account set balance = balance+? where uname=?";
        try {
            //在dao持久层每做一个操作 都从当前线程对象进行操作
            runner.update(DBUtils.getConn(),sql,money,name1);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //转出方法
    public void transationOut(String name1, double money){
        String sql = "update account set balance = balance-? where uname=?";
        try {
            runner.update(DBUtils.getConn(),sql,money,name1);
        } catch (SQLException e) {
            e.printStackTrace();
        }
   }
   //查询方法
   public Account queryAccountByWhere(String accOn){
        Account account = null;
        String sql ="select * from account where uname=?";
       try {
           account =  runner.query(DBUtils.getConn(),sql,accOn,new BeanHandler<>(Account.class));
       } catch (SQLException e) {
           e.printStackTrace();
       }
       return account;
   }
}

创建业务类TransactionService, 实现业务

public class TransactionService{
    private TransactionDao tranDao;

    public TransactionService() {
        this.tranDao = new TransactionDao();
    }

    //确认账户是否存在
    public boolean chageAccount(String accNo){
        //TODO
        boolean falg = false;
        Account account = tranDao.queryAccountByWhere(accNo);
        if (account !=null){
            falg = true;
        }
        return  falg;
   }
    //确认账户余额是否足够
    public boolean balanceVerify(String accNo,double balance){
        //TODO
        boolean falg = false;
        Account account = tranDao.queryAccountByWhere(accNo);
        //如果为空返回失败
        if (account==null){
            return falg;
            //如果金额不够返回失败
        }else if (account.getBalance() <balance){
            return falg;
        }else {
            falg = true;
        }
        return  falg;
    }
    //转账方法
    public boolean transactionAccount(String accNo,String toAccount,double balance){
        boolean falg = false;
        try {
            //转入和转出同时进行
            tranDao.transationOut(accNo,balance);
//            int i = 1/0;
            tranDao.transationIn(toAccount,balance);
            //没出问题就为成功,否则失败
            falg=true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  falg;
    }
}

创建servlet类
注解中 value 的值一定要与表单中的 action 的值一致不然无法找到

@WebServlet(value = "/transfer.do")
public class TtansferServlet extends HttpServlet {
    @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 {
        boolean isFlag = false;
        //1.接收表单参数
        String fromAc = req.getParameter("fromAc");
        String toAc = req.getParameter("toAc");
        String moneyStr = req.getParameter("money");
        double money = 0.0;
        if (moneyStr!=null && !"".equals(moneyStr)){
            money = Double.parseDouble(moneyStr);
        }
        //2.创建业务层对象 调用业务层方法
        TransactionService tranService = new TransactionService();
        PrintWriter out = resp.getWriter();
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        if (tranService.chageAccount(fromAc)){
            if (tranService.chageAccount(toAc)){
                if (tranService.balanceVerify(fromAc,money)){
                    //3.根据业务方法的返回值进行处理
                     boolean iFlag= tranService.transactionAccount(fromAc,toAc,money);
                    if(iFlag) {
                        System.out.println("转账成功!");
                        //以响应输出成功标志到前端
                        out.println("<h3>转账成功</h3>");
                    }else {
                        System.out.println("转账失败!");
                        //以响应输出失败标志到前端
                        out.println("<h3>转账失败</h3>");
                        throw new RuntimeException("转账失败");
                    }
                }else {
                    out.println("<h3>"+fromAc+"账户余额不足</h3>");
                }
            }else {
                out.println("<h3>"+toAc+"账户不存在</h3>");
            }
        }else {
            out.println("<h3>"+fromAc+"账户不存在</h3>");
        }
    }
}

创建过滤器
注解中的值是用于指定过滤哪一些servlet, 并且执行事务.


@WebFilter("/*")
public class TransactionFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        try {
            System.out.println("-------------------请求执行---------------");
            DBUtils.beginTransaction();//开启
            filterChain.doFilter(servletRequest, servletResponse);
            DBUtils.commit();// 提交事务
            System.out.println("------------------给出响应---------------");
        } catch (Exception e) {
            DBUtils.rollback();//回滚事务
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {

    }
}

配置Tomcat

点击这个地方
在这里插入图片描述
按照顺序选择这两个
1.+
2.local

在这里插入图片描述
1.选择版本
2.自动生成项目在这里插入图片描述
1.访问路径,建议为如图
2.点击Apply ok
在这里插入图片描述
然后启动: 在表单操作进行提交 控台返回结果
之后再查看数据库的数据


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进