用SpringBoot+mysql+html实现ATM 系统总结与扩展

这里写目录标题

  • ATM 系统总结与扩展
    • 项目概述
    • 主要功能模块
      • 1. 用户注册
      • 2. 用户登录
      • 3. 账户查询
      • 4. 存款与取款
      • 5. 转账
      • 6. 修改密码
      • 7. 销户
    • 系统改进建议
      • 功能扩展
      • 技术优化
    • 完整代码实现
      • 数据库表设计
      • 后端代码(Spring Boot 示例)
        • 1. Account 实体类
        • 2. AccountRepository 接口
        • 3. AccountController 类
      • 前端代码(HTML + JavaScript 示例)
    • 实际开发与部署步骤
      • **1. 开发环境搭建**
      • 2. 后端开发流程
      • 3. WAR 包打包与部署
        • 修改项目结构
        • 配置 IDEA2022 的部署
        • 打包并运行
      • 4. 部署到服务器
      • 5. 测试与优化
  • 用原生Java实现的测试demo
    • 一 创建一个Account类
    • 二 用链表实现基本的用户注册登录,存取款,销户操作
    • 总结

ATM 系统总结与扩展

项目概述

本项目是一个基于 Java 的模拟 ATM 系统,主要功能包括用户注册、登录、账户查询、存款、取款、转账、修改密码以及销户操作。系统采用控制台交互方式,通过链表(ArrayList)实现对多个用户账户的管理。

主要功能模块

1. 用户注册

  • 用户输入姓名、密码(需验证两次),并设置单次转账/提现额度。
  • 系统自动生成随机且唯一的银行卡号。
  • 默认账户余额为 0。

2. 用户登录

  • 用户通过银行卡号和密码登录。
  • 登录成功后进入操作界面,可选择执行各种账户相关操作。

3. 账户查询

  • 显示当前登录用户的账户信息,包括:
    • 银行卡号
    • 用户名
    • 账户余额
    • 单次转账限额

4. 存款与取款

  • 存款:用户输入金额后更新账户余额。
  • 取款:用户输入金额,需验证账户余额和单次限额。

5. 转账

  • 用户输入目标银行卡号和转账金额。
  • 验证目标账户存在性及余额后完成转账操作。

6. 修改密码

  • 用户输入旧密码验证成功后,可设置新密码。

7. 销户

  • 确认销户操作,需保证账户余额为 0,成功后删除账户。

系统改进建议

功能扩展

  • 增加数据库支持,使用 MySQL 存储账户数据,实现数据持久化。
  • 增加前端表单交互,通过 HTTP 接口提交数据。
  • 提供用户操作日志,记录存取款、转账等操作。

技术优化

  • 数据安全:对用户密码进行加密存储。
  • 异常处理:增加输入验证和异常捕获,提升系统健壮性。
  • 多线程支持:实现多用户并发操作。

完整代码实现

以下是通过 Java 实现的一个包含 MySQL 增删改查操作和前端表单交互的示例。

数据库表设计

CREATE TABLE account (
    id INT AUTO_INCREMENT PRIMARY KEY,
    card_id VARCHAR(20) NOT NULL UNIQUE,
    user_name VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL,
    balance DOUBLE DEFAULT 0,
    quota_money DOUBLE NOT NULL
);

后端代码(Spring Boot 示例)

1. Account 实体类
@Entity
@Table(name = "account")
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "card_id", unique = true, nullable = false)
    private String cardId;

    @Column(name = "user_name", nullable = false)
    private String userName;

    @Column(name = "password", nullable = false)
    private String password;

    private Double balance = 0.0;

    @Column(name = "quota_money", nullable = false)
    private Double quotaMoney;

    // Getters and Setters
}
2. AccountRepository 接口
@Repository
public interface AccountRepository extends JpaRepository<Account, Integer> {
    Optional<Account> findByCardId(String cardId);
}
3. AccountController 类
@RestController
@RequestMapping("/api/account")
public class AccountController {

    @Autowired
    private AccountRepository accountRepository;

    @PostMapping("/register")
    public ResponseEntity<String> register(@RequestBody Account account) {
        if (accountRepository.findByCardId(account.getCardId()).isPresent()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Card ID already exists!");
        }
        account.setPassword(BCrypt.hashpw(account.getPassword(), BCrypt.gensalt()));
        accountRepository.save(account);
        return ResponseEntity.ok("Account registered successfully!");
    }

    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestParam String cardId, @RequestParam String password) {
        Optional<Account> accountOpt = accountRepository.findByCardId(cardId);
        if (accountOpt.isEmpty() || !BCrypt.checkpw(password, accountOpt.get().getPassword())) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
        }
        return ResponseEntity.ok("Login successful!");
    }

    @PutMapping("/deposit")
    public ResponseEntity<String> deposit(@RequestParam String cardId, @RequestParam Double amount) {
        Optional<Account> accountOpt = accountRepository.findByCardId(cardId);
        if (accountOpt.isEmpty()) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Account not found");
        }
        Account account = accountOpt.get();
        account.setBalance(account.getBalance() + amount);
        accountRepository.save(account);
        return ResponseEntity.ok("Deposit successful. New balance: " + account.getBalance());
    }
}

前端代码(HTML + JavaScript 示例)

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ATM Systemtitle>
head>
<body>
    <h1>ATM Systemh1>

    <h2>Registerh2>
    <form id="registerForm">
        <input type="text" id="userName" placeholder="User Name" required>
        <input type="password" id="password" placeholder="Password" required>
        <input type="number" id="quotaMoney" placeholder="Quota Money" required>
        <button type="submit">Registerbutton>
    form>

    <script>
        document.getElementById('registerForm').addEventListener('submit', async (e) => {
            e.preventDefault();

            const response = await fetch('/api/account/register', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    userName: document.getElementById('userName').value,
                    password: document.getElementById('password').value,
                    quotaMoney: parseFloat(document.getElementById('quotaMoney').value)
                })
            });

            const result = await response.text();
            alert(result);
        });
    script>
body>
html>

实际开发与部署步骤

1. 开发环境搭建

  • 后端

    1. 安装 JDK(建议使用 JDK 17 或更高版本)。
    2. 配置 Maven 或 Gradle 作为项目管理工具。
    3. 引入 Spring Boot 依赖,包括 Web 和 JPA。
    4. 安装 MySQL 数据库,创建相应的数据库和表。
  • 前端

    1. 使用简单的 HTML + JavaScript 实现表单交互。
    2. 如需增强体验,可使用 Vue.js 或 React 等框架。

2. 后端开发流程

  1. 创建 Spring Boot 项目,定义实体类(如 Account)。
  2. 配置数据库连接信息(application.propertiesapplication.yml):
    spring.datasource.url=jdbc:mysql://localhost:3306/atm_system
    spring.datasource.username=root
    spring.datasource.password=yourpassword
    spring.jpa.hibernate.ddl-auto=update
    
  3. 编写业务逻辑和控制器,处理前端请求。

3. WAR 包打包与部署

修改项目结构
  • pom.xml 中将打包类型改为 WAR:
    <packaging>warpackaging>
    
  • 修改主启动类,继承 SpringBootServletInitializer
    @SpringBootApplication
    public class AtmSystemApplication extends SpringBootServletInitializer {
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            return builder.sources(AtmSystemApplication.class);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(AtmSystemApplication.class, args);
        }
    }
    
配置 IDEA2022 的部署
  1. 打开 Run/Debug Configurations
  2. 新建配置,选择 Tomcat Server > Local
  3. Deployment 选项卡中,添加生成的 WAR 包。
  4. 配置服务器端口并启动服务。
打包并运行
  • 使用 Maven 打包命令生成 WAR 文件:
    mvn clean package
    
  • 将生成的 WAR 文件部署到 Tomcat 或其他 Servlet 容器中。

4. 部署到服务器

  1. 安装 Java 环境和 MySQL。
  2. 将 WAR 包上传到服务器中的 Tomcat 部署目录(webapps)。
  3. 启动 Tomcat,访问服务:
    http://<server_ip>:<port>/<context_path>
    

5. 测试与优化

  • 使用 Postman 或 Swagger UI 测试后端接口。
  • 优化 SQL 查询,避免性能瓶颈。
  • 增加日志记录和异常处理,提升系统可靠性。

用原生Java实现的测试demo

一 创建一个Account类

主要包含银行卡号,用户名,用户密码,账户剩下余额,单次转账提现额度六个变量

public class Account {
	private String cardId;//银行卡号
	private String userName;//用户名
	private String passWord;//用户密码
	private double money;//账户剩下余额
	private double quotaMoney;//单次转账提现额度
	//先生成一个空参构造器
	public Account() {
		super();
	}
	//在定义一个有参构造器
	public Account(String cardId,String userName,String passWord,double money,double quotaMoney) {
		super();
		this.cardId=cardId;
		this.userName=userName;
		this.passWord=passWord;
		this.money=money;
		this.quotaMoney=quotaMoney;
	}
	public String getCardId() {
		return cardId;
	}
	public void setCardId(String cardId) {
		this.cardId = cardId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassWord() {
		return passWord;
	}
	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}
	public double getMoney() {
		return money;
	}
	public void setMoney(double money) {
		this.money = money;
	}
	public double getQuotaMoney() {
		return quotaMoney;
	}
	public void setQuotaMoney(double quotaMoney) {
		this.quotaMoney = quotaMoney;
	}
}

二 用链表实现基本的用户注册登录,存取款,销户操作

import java.util.ArrayList;
import java.util.Scanner;


public class Test01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrayList<Account> accounts=new ArrayList<>();
		System.out.println("=============ATM系统================");
		System.out.println("请输入您要办的业务:");
		System.out.println("1.登录");
		System.out.println("2.注册");
		Scanner sc=new Scanner(System.in);
		int command=sc.nextInt();
		switch (command) {
		case 1:
			login(accounts,sc);
			break;
		case 2:
			register(accounts,sc);
			break;
		default:
			break;
		}
	}

	public static void register(ArrayList<Account> accounts, Scanner sc) {
		// TODO Auto-generated method stub
		System.out.println("===========系统开户操作================");
		//1. 创建一个账户对象,用于后期封装账户信息;
		Account acc_ount=new Account();
		//2. 向对象中补充一些属性特征,比如说姓名,密码(至少两次输入正确,不行一直循环),账号随机生成
		//2.1用户自己输入姓名
		System.out.println("请您输入该账号姓名:");
		String name=sc.next();
		//2.2用户自己输入账户密码
		System.out.println("请您输入账号密码:");
		System.out.println("请您输入第一遍密码:");
		String passWord=sc.next();
		while (true) {
			System.out.println("请您输入第二遍密码");
			String okpassWord=sc.next();
			if (passWord.equals(okpassWord)) {
				System.out.println("密码验证成功");
				break;
			} else {
				System.out.println("密码输入错误,再来一次");
			}
		}
		//2.3系统随机生成一个银行卡号
		System.out.println("系统正在生成一个银行卡号");
		String cardId=getRandomCardById(accounts);
		
		//2.4请您输入单次转账额度
		System.out.println("请输入单次转账限额:");
		double quotoMoney=sc.nextDouble();
		//3 
		double money=0;
		Account account=new Account(cardId,name,passWord,money,quotoMoney);
		accounts.add(acc_ount);
		System.out.println("恭喜您"+acc_ount.getUserName()+"先生、女士"+"账户"+acc_ount.getCardId()+"开户成功");
	}

	public static String getRandomCardById(ArrayList<Account> accounts) {
		// TODO Auto-generated method stub
		while (true) {
			String s="";
			for (int i = 0; i < 8; i++) {
				int t=(int)(Math.random()*10);
				s=t+s;
				//
			}
			Account accountByCardId=getAccountCardById(s,accounts);
			if (accountByCardId==null) {
				return s;
				
			}
			
		}
	}

	public static Account getAccountCardById(String s, ArrayList<Account> accounts) {
		// TODO Auto-generated method stub
		for (int i = 0; i < accounts.size(); i++) {
			Account tf=accounts.get(i);
			if (tf.getCardId().equals(s)) {
				return tf;
			}
			
		}
		return null;
	}

	public static void login(ArrayList<Account> accounts, Scanner sc) {
		// TODO Auto-generated method stub
		System.out.println("=====================================");
		if(accounts.size()==0) {
			System.out.println("对不起,当前系统中,无任何账号,请先开户,再来登录~~");
			return;
		}
		while(true) {
			System.out.println("请您输入登录卡号");
			String t=sc.next();
			//根据卡号,查询有无账号
			Account account=getAccountCardById(t, accounts);
			if(account!=null) {
				//让用户输入密码
				while(true) {
					System.out.println("请您输入登录密码:");
					String passWord=sc.next();
					if(account.getPassWord().equals(passWord)) {
						//登录成功了
						System.out.println("恭喜您"+account.getUserName()+"先生/女士进入系统,您的卡号是"
								+account.getCardId());
						//查询,存款,取款
						showUserCommand(account,sc,accounts);
						return;
						
					}else {
						System.out.println("对不起,您输入的密码有误");
					}
				}
			}else {
				System.out.println("对不起,系统中不存在该账户卡号");
			}
		}
		
	}

	public static void showUserCommand(Account account, Scanner sc, ArrayList<Account> accounts) {
		// 登录成功之后的操作页
		while (true) {
			System.out.println("=============用户操作页================");
			System.out.println("1.查询账号");
			System.out.println("2.存款");
			System.out.println("3.取款 ");
			System.out.println("4.转账");
			System.out.println("5.修改密码");
			System.out.println("6.退出");
			System.out.println("7.注销账号");
			int enter=sc.nextInt();
			switch (enter) {
			case 1:
				System.out.println();
				 //查询账户(展示当前登录的账户信息)
                showAccount(account);
				break;
			case 2:
				//存款
				depositMoney(account,sc);
				break;
			case 3:
				//取款
				drawMoney(account,sc);
				break;
			case 4:
				//转账
				transferMoney(sc,account,accounts);
				break;
			case 5:
				//修改密码
				updatePassWord(sc,account);
				break;
			case 6:
				//退出账号
				System.out.println("退出成功,欢迎下次光临");
				return;
				
			case 7:
				//注销账号
                //从当前集合中删除账户对象,销毁就完成了
                if (  deleteAccount(account,sc,accounts)){
                    //销户成功
                    return;
                }else {
                    //还是在操作页
                    break;
                }
			
			default:
				System.out.println("您输入的信息有错误!");
				break;
			}
			
		}
		
	}
	public static void showAccount(Account account) {
		// TODO Auto-generated method stub
		System.out.println("当前账户信息如下图所示:");
		System.out.println("账户账号:"+account.getCardId());
		System.out.println("账户密码:"+account.getPassWord());
		System.out.println("账户余额:"+account.getMoney());
		System.out.println("单次转账限额"+account.getQuotaMoney());
		
	}
	public static void depositMoney(Account account, Scanner sc) {
		// TODO Auto-generated method stub
		System.out.println("============用户存钱操作==============");
		System.out.println("请输入存钱金额:");
		double money=sc.nextDouble();
		account.setMoney(money+account.getMoney());
		System.out.println("恭喜您,存钱成功,当前账户信息如下图所示:");
		showAccount(account);
	}
	public static void drawMoney(Account acc, Scanner sc) {
		 
        System.out.println("=====================用户取钱操作==================");
        if (acc.getMoney()<100){
            System.out.println("对不起,当前账户中不足100元,不能取钱");
            return;
        }
        while (true) {
            System.out.println("请输入取款金额:");
            double Money = sc.nextDouble();
            //判断金额是否满足要求
            if(Money>acc.getQuotaMoney()){
                System.out.println("对不起,您当前取款金额超过每次限额,每次最多可取:"+acc.getQuotaMoney());
            }else {
                if(Money>acc.getMoney()){
                    System.out.println("余额不足");
                }else {
                    System.out.println("恭喜您,取钱"+Money+"元,成功!");
                    acc.setMoney(acc.getMoney()-Money);
                    showAccount(acc);
                    return;
                }
            }
        }
    }
	public static void transferMoney(Scanner sc, Account account, ArrayList<Account> accounts) {
		// 给另一个账户转账的操作
		System.out.println("================用户转账操作==================");
		if(accounts.size()<2) {
			System.out.println("当前系统中,不足两个账户 ,不能进行转账,请去开户吧");
			return;
		}
		//判断自己账户是否有钱
		if(account.getMoney()==0) {
			System.out.println("余额不足,不允许转账");
		}
		//真正开始转账
		while(true) {
			System.out.println("请您输入对方的银行卡号");
			String  cardId=sc.next();
			if(cardId.equals(account.getCardId())) {
				System.out.println("对不起,您不能给自己转账");
				continue;
			}
			//判断卡号是否存在
			Account accountByCardId=getAccountCardById(cardId, accounts);
			if(accountByCardId==null) {
				System.out.println("对不起,您输入的账号不存在~~~");
			}else {
				String username=accountByCardId.getUserName();
				String tip="*"+username.substring(1);
				System.out.println("请您输入["+tip+"]的姓氏");
				String preName=sc.next();
				//认证姓氏是否输入正确
				if(username.startsWith(preName)) {
					while (true) {
						//认证通过,真正开始转账了
						System.out.println("请您输入金额");
						double money=sc.nextDouble();
						if(money>account.getMoney()) {
							System.out.println("对不起,你的余额不足,最多可以转账"+account.getMoney());
						}else {
							//余额足够,可以转账金额
							account.setMoney(account.getMoney()-money);
							accountByCardId.setMoney(money+accountByCardId.getMoney()+money);
							System.out.println("转账成功!您的账户还剩余"+account.getMoney());
							return;
						}
					}
				}else {
					System.out.println("对不起,您输入的信息有误");
				}
				
			}
		}
		
		
	}
	public static void updatePassWord(Scanner sc, Account account) {
		// TODO Auto-generated method stub
		System.out.println("=================用户修改操作=================");
		while(true) {
			System.out.println("请您输入当前密码:");
			String passWord=sc.next();
			//判断这个密码是否正确
			if(account.getPassWord().equals(passWord)) {
				while (true) {
					System.out.println("请您输入新密码:");
					String newPassWord=sc.next();
					System.out.println("请您再次输入新密码");
					String okNewPassWord=sc.next();
					if(newPassWord.equals(okNewPassWord)) {
						//两次输入正确,可以把新密码塞进去了
						account.setPassWord(newPassWord);
						System.out.println("恭喜您,密码输入成功了");}
						else {
							//密码错误
							System.out.println("您两次输入的密码不一致");
						}
					}
					
				}else {
					//密码错误
					System.out.println("您输入的密码不正确");
				}
			}
		}
	public static boolean deleteAccount(Account account, Scanner sc, ArrayList<Account> accounts) {
		// TODO Auto-generated method stub
		System.out.println("===========销户操作==============");
		System.out.println("您真的要销户嘛?y,确定销户。n,不销户");
		String st=sc.next();
		switch (st) {
		case "y":
			if (account.getMoney()>0) {
				System.out.println("账户里还有钱,不能够销户");
				
			} else {
				accounts.remove(account);
				System.out.println("账号销户完成");
				return true;

			}
			break;

		default:
			System.out.println("当前账户保留");
			break;
		}
		
		return false;
	}

}

总结

本文展示了一个基于 Java 的 ATM 系统的完整实现,从控制台操作到使用数据库和前端表单扩展,涵盖了账户管理的核心功能。同时,详细介绍了开发与部署的具体步骤,包括 WAR 包部署流程,为构建一个实际可用的 ATM 系统提供了全面参考。

你可能感兴趣的:(#,一,SpringBoot,spring,boot,mysql,html)