银行管理系统java mysql8.转账、存钱、取钱、查询账户、开户、登录、自动生成密码账户等功能
文章目录
-
- 银行管理系统java mysql8.转账、存钱、取钱、查询账户、开户、登录、自动生成密码账户等功能
- dbcp.properties
- 工具类
- 随机生成卡号和密码
- Dao层
- entity实体
- exception自定义异常
- service层
- test测试
- view视图层
在sql在客户客户端atm在数据库中创建了两个表
account表 用户信息表,用户密码通过MD5Util加密
re_account记录操作
项目结构
dbcp.properties
#配置驱动类 driverClassName=com.mysql.cj.jdbc.Driver #配置连接字符串 url=jdbc:mysql://localhost:3308/atm?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai ##用户名登录数据库 username=root #登录数据库密码 password=root #最大活动连接数设为0为没有限制 maxActive=50 #最大空闲连接数,设置为0为没有限制 maxIdle=20 #最大等待毫秒数,设置为-1为没有限制 maxWait=60000 #配置文件的键不能随意写成其他名称,因为源代码中有相应的信息
工具类
ConnUtil连接数据库
public class ConnUtil {
////每个线程使用自己的ThreadLocal对象 private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); ///数据源对象 private static DataSource ds; ///私有结构方法,外部不能new private ConnUtil() {
} static {
///加载数据源ds对象 InputStream is = ConnUtil.class.getResourceAsStream("/dbcp.properties");
Properties properties = new Properties();
try {
properties.load(is);
ConnUtil.ds = BasicDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConn() throws SQLException {
//从threadLocal中取出
Connection conn = threadLocal.get();
if (conn == null || conn.isClosed()) {
//创建数据库连接
conn = ds.getConnection();
threadLocal.set(conn);//将连接放入当前线程
}
return conn;
}
public static void closeConn() {
Connection conn = threadLocal.get();
try {
if (conn != null && !conn.isClosed()) {
try {
conn.close();//在使用DBCP时,释放连接对象
} catch (SQLException throwables) {
throwables.printStackTrace();
}
threadLocal.set(null);//清空当前线程中的连接
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
加密工具类MD5Util
package com.demo.util; /******************************************************************************* * * * MD5数据加密类 */ 加密工具类MD5Util public class MD5Util { public static void main(String[] args) { String md5 = getMd5Str("zs"); System.out.println(md5); } private static MD5Util md5Util = new MD5Util(); public static String getMd5Str(String str){ return md5Util.getMD5ofStr(str); } // RFC1321中定义的标准4*4矩阵的常量定义。 static final int S11 = 9,S12 = 12,S13 = 17, S14 = 22; static final int S21 = 5,S22 = 9, S23 = 14, S24 = 20; static final int S31 = 4,S32 = 11,S33 = 16, S34 = 23; static final int S41 = 4 ,S42 = 10,S43 = 15, S44 = 21; // 按RFC1321标准定义不可变byte型数组PADDING static final byte[] PADDING = { -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // MD5计算过程中的3组核心数据,采用数组形式存放 private long[] state = new long[4]; // 计算状态(分别对应a b c d) private byte[] buffer = new byte[64]; // 分配64个字节私有缓冲区 private long[] count = new long[2]; // 位个数 // 最新一次计算结果的16进制ASCII字符串表示,代表了16个字符串形式的MD5值 public String resultStr; // 最新一次计算结果的2进制数组表示,一共16个字节,代表了128bit形式的MD5值 public byte[] digest = new byte[16]; // MD5_Encoding类提供的主要的接口函数getMD5ofStr,用来进行数据加密变换。调用其可对任意字符串进行加密运算,并以字符串形式返回加密结果。 public String getMD5ofStr(String in) { md5Init(); // 初始化 md5Update(in.getBytes(), in.length());// 调用MD5的主计算过程 md5Final(); // 输出结果到digest数组中 for (int i = 0; i < 16; i++) { resultStr += byteToHEX(digest[i]); // 将digest数组中的每个byte型数据转为16进制形式的字符串 } return resultStr; } // 标准的构造函数,调用md5Init函数进行初始化工作 private MD5Util() { md5Init(); return; } // md5初始化函数.初始化核心变量. private void md5Init() { state[0] = 0x67452301L; // 定义state为RFC1321中定义的标准幻数 state[1] = 0xefcdab89L; // 定义state为RFC1321中定义的标准幻数 state[2] = 0x98badcfeL; // 定义state为RFC1321中定义的标准幻数 state[3] = 0x10325476L; // 定义state为RFC1321中定义的标准幻数 count[0] = count[1] =0L; // 初始化为0 resultStr = "";// 初始化resultStr字符串为空 for(int i=0;i<16;i++) digest[i]=0;//初始化digest数组元素为0 return; } //定义F G H I 为4个基数 ,即为4个基本的MD5函数,进行简单的位运算 private long F(long x, long y, long z) { return (x & y) | ((~x) & z); } private long G(long x, long y, long z) { return (x & z) | (y & (~z)); } private long H(long x, long y, long z) { return x ^ y ^ z; } private long I(long x, long y, long z) { return y ^ (x | (~z)); } // FF,GG,HH和II调用F,G,H,I函数进行进一步变换 private long FF(long a, long b, long c, long d, long x, long s, long ac) { a += F(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s)); //这里long型数据右移时使用无符号右移运算符>>> a += b; return a; } private long GG(long a, long b, long c, long d, long x, long s, long ac) { a += G(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s)); //这里long型数据右移时使用无符号右移运算符>>> a += b; return a; } private long HH(long a, long b, long c, long d, long x, long s, long ac) { a += H(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s));//这里long型数据右移时使用无符号右移运算符>>> a += b; return a; } private long II(long a, long b, long c, long d, long x, long s, long ac) { a += I(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s));//这里long型数据右移时使用无符号右移运算符>>> a += b; return a; } // MD5的主计算过程,input是需要变换的二进制字节串,inputlen是长度 private void md5Update(byte[] input, int inputLen) { int i=0, index, partLen; byte[] block = new byte[64]; // 分配64个字节缓冲区 //根据count计算index值。这里long型数据右移时使用无符号右移运算符>>> index = (int) (count[0] >>> 3) & 0x3F; if ((count[0] += (inputLen << 3)) < (inputLen << 3)) count[1]++; count[1] += (inputLen >>> 29); //这里int型数据右移时使用无符号右移运算符>>> partLen = 64 - index; //计算partLen值 if (inputLen >= partLen) { md5Memcpy(buffer, input, index, 0, partLen); md5Transform(buffer); for (i = partLen; i + 63 < inputLen; i += 64) { md5Memcpy(block, input, 0, i, 64); md5Transform(block); } index = 0; } else i = 0; md5Memcpy(buffer, input, index, i, inputLen - i); } // 整理和填写输出结果,结果放到数组digest中。 private void md5Final() { byte[] bits = new byte[8]; int index, padLen; Encode(bits, count, 8); index = (int) (count[0] >>> 3) & 0x3f; //这里long型数据右移时使用无符号右移运算符>>> padLen = (index < 56) ? (56 - index) : (120 - index); md5Update(PADDING, padLen); md5Update(bits, 8); Encode(digest, state, 16); } // byte数组的块拷贝函数,将input数组中的起始位置为inpos,长度len的数据拷贝到output数组起始位置outpos处。 private void md5Memcpy(byte[] output, byte[] input, int outpos, int inpos, int len) { int i; for (i = 0; i < len; i++) output[outpos + i] = input[inpos + i]; } // MD5核心变换计算程序,由md5Update函数调用,block是分块的原始字节数组 private void md5Transform(byte block[]) { long a = state[0], b = state[1], c = state[2], d = state[3]; long[] x = new long[16]; Decode(x, block, 64); // 进行4级级联运算 // 第1级 a = FF(a, b, c, d, x[0], S11, 0xd76aa478L); /* 1 */ d = FF(d, a, b, c, x[1], S12, 0xe8c7b756L); /* 2 */ c = FF(c, d, a, b, x[2], S13, 0x242070dbL); /* 3 */ b = FF(b, c, d, a, x[3], S14, 0xc1bdceeeL); /* 4 */ a = FF(a, b, c, d, x[4], S11, 0xf57c0fafL); /* 5 */ d = FF(d, a, b, c, x[5], S12, 0x4787c62aL); /* 6 */ c = FF(c, d, a, b, x[6], S13, 0xa8304613L); /* 7 */ b = FF(b, c, d, a, x[7], S14, 0xfd469501L)