其他分享
首页 > 其他分享> > 手写tomcat(四)-WEB服务器测试-网银转账系统

手写tomcat(四)-WEB服务器测试-网银转账系统

作者:互联网

1.引言

在前几章我们已经设计并完成了 WEB 服务器的研发,接下来我们开发一个简单的网银转账系统对 WEB 服务器进行测试。 以下我们的开发角色都是 WebApp 的开发人员。 我们给该 Web 应用起名为bank。

2.mytomcat【准备工作】

大家是否还记得在 WEB 服务器开发阶段,有这样一段代码是写死的,如下图所示:
在这里插入图片描述
看上图中的 BootStrap 类,该类是 WEB 服务器开发人员开发,在服务器启动阶段解析每个 WebApp的 web.xml 文件,程序中我们将 WebApp 的名字固定写入,显然设计不够合理,这里我们就不再解决了,大家可以想一想怎么解决这个问题。不过我们要新建一个 WebApp,并且起名为 bank,所以我们需要在字符串数组中添加新的 WebApp,如下图所示:

//解析服务中包含的web.xml配置文件
String[] webAppNames = {"oa","bank"};

接下来 WebApp 开发人员开始进行准备工作,创建一个符合规范的 WebApp 的目录结构,并编写
合法的 web.xml 文件,如下图所示:
在这里插入图片描述
接下来我们简单的设计一下该系统的功能,该系统主要功能是完成银行账户转账,但是转账之前必须先进行开户操作,所以该系统一共两个功能,

第一:开户功能,
第二:转账功能。

这两个功能其实用户群不同,开户功能实际上是银行业务员使用的。转账功能是银行账户持有者使用的。 我们这里就不再分系统角色了。只要简单的实现这两个功能即可。

完成以上功能,先进行数据库的设计,我们这里就使用学过的 MySQL 数据吧,数据库设计一张表即可,该表叫做账户表 t_act,该账户表中存储银行账户信息,该表的字段简单设计包括:唯一标识(id)、账号(actno)、余额(balance),数据库账户表建表语句如下图所示:

DROP TABLE IF EXISTS t_act;

CREATE TABLE t_act (
	id INT (10) PRIMARY KEY auto_increment,
	actno VARCHAR (32) NOT NULL UNIQUE,
	balance DOUBLE (7, 2)
)

创建表完成之后,将连接数据库的 MySQL 驱动 jar 包配置到环境变量当中,如下图所示:
在这里插入图片描述

2.mytomcat【实现开户】

2.1 准备开户页面

<html>
	<head>
		<title>银行帐户-开户</title>
		<meta content="text/html;charset=utf-8"/>
	</head>
	<body>
		<form name="actOpenForm" action="/bank/act/open" method="get">
			银行帐户:
				<input type="text" name="actno"/>
				<br><br>
			开户金额:
				<input type="text" name="balance"/>
				<br><br>
				<input type="submit" value="确认开户"/>
				<input type="reset" value="重置"/>
		</form>
	</body>
</html>

在这里插入图片描述
启动 服务器,打开浏览器输入以下 URL,发送请求,访问结果如下图所示:
在这里插入图片描述

2.2 编辑配置文件 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
    <servlet>
        <servlet-name>actOpenServlet</servlet-name>
        <servlet-class>org.bruceliu.bank.servlet.ActOpenServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>actOpenServlet</servlet-name>
        <url-pattern>/act/open</url-pattern>
    </servlet-mapping>
</web-app>

在这里插入图片描述

2.3 编写 ActOpenServlet 实现开户功能

package org.bruceliu.bank.servlet;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class ActOpenServlet implements Servlet {

	@Override
	public void service(ServletRequest request, ServletResponse response) {
		//-----------从页面获取参数值------------
		String actno = request.getParameterValue("actno");
		double balance = Double.parseDouble(request.getParameterValue("balance"));
		
		//---------------连接数据库-------------
		Connection conn = null;
		PreparedStatement ps = null;
		int count = 0;
		try {
			// 1.加载驱动 放入Mysql驱动类的全路径,让JVM预先加载这个类到内存中
			Class.forName("com.mysql.jdbc.Driver");
			//2.获取数据库的连接对象
			conn= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bankdb?useUnicode=true&characterEncoding=UTF-8&useSSL=true","root","123456");
			//3.定义SQL语句框架
			String sql = "insert into t_act(actno,balance) values(?,?)";
			//4.进行SQL语句预编译
			ps = conn.prepareStatement(sql);
			//5.进行赋值
			ps.setString(1, actno);
			ps.setDouble(2, balance);
			//6.执行SQL语句
			count = ps.executeUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//关闭资源
			if(ps != null){
				try {
					ps.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		//获取响应流对象
		PrintWriter out = response.getWriter();
		if(count == 1){
			out.print("<html>");
			out.print("<head>");
			out.print("<title>银行帐户-开户结果</title>");
			out.print("<meta content='text/html;charset=utf-8'/>");
			out.print("</head>");
			out.print("<body>");
			out.print("<center><font size='35px' color='green'>恭喜您,开户成功!</font></center>");
			out.print("</body>");
			out.print("</html>");
		}else{
			out.print("<html>");
			out.print("<head>");
			out.print("<title>银行帐户-开户结果</title>");
			out.print("<meta content='text/html;charset=utf-8'/>");
			out.print("</head>");
			out.print("<body>");
			out.print("<center><font size='35px' color='red'>对不起,开户失败!</font></center>");
			out.print("</body>");
			out.print("</html>");
			
		}
	}

}


2.4 测试开户功能

启动服务器,打开浏览器访问开户页面,填写表单,点击开户,运行结果如下所示:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
再开立一个账户
在这里插入图片描述

3. mytomcat【实现转账】

3.1 准备转账页面

<html>
	<head>
		<title>银行帐户-转帐</title>
		<meta content="text/html;charset=utf-8"/>
	</head>
	<body>
		<form name="actTransferForm" action="/bank/act/transfer" method="get">
			转出帐号:
				<input type="text" name="actFrom"/>
				<br><br>
			转出金额:
				<input type="text" name="balance"/>
				<br><br>
			转入帐号:
				<input type="text" name="actTo"/>
				<br><br>
				<input type="submit" value="确认转帐"/>
				<input type="reset" value="重置"/>
		</form>
	</body>	
</html>

启动 httpserver,打开浏览器输入 URL,发送请求访问结果如下所示:
在这里插入图片描述

3.2 编辑配置文件 web.xml

 <servlet>
     <servlet-name>actTransferServlet</servlet-name>
     <servlet-class>org.bruceliu.bank.servlet.ActTransferServlet</servlet-class>
 </servlet>
 <servlet-mapping>
     <servlet-name>actTransferServlet</servlet-name>
     <url-pattern>/act/transfer</url-pattern>
 </servlet-mapping>

3.3 编写转账的 ActTransferServlet 类

package org.bruceliu.bank.servlet;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class ActTransferServlet implements Servlet {

	@Override
	public void service(ServletRequest request, ServletResponse response) {
		//------------获取页面请求的参数------------
		String actFrom = request.getParameterValue("actFrom");
		double balance = Double.parseDouble(request.getParameterValue("balance"));
		String actTo = request.getParameterValue("actTo");
		
		//-----------连接数据库---------------
		Connection conn = null;
		PreparedStatement ps = null;
		int count = 0;
		try {
			//1.注册驱动
			// 1.加载驱动 放入Mysql驱动类的全路径,让JVM预先加载这个类到内存中
			Class.forName("com.mysql.jdbc.Driver");
			//2.获取数据库的连接对象
			conn= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bankdb?useUnicode=true&characterEncoding=UTF-8&useSSL=true","root","123456");
			//3.定义SQL语句框架
			String sql_from = "update t_act set balance = balance - ? where actno = ?";
			//4.进行SQL语句的预编译
			ps = conn.prepareStatement(sql_from);
			//5.进行赋值
			ps.setDouble(1, balance);
			ps.setString(2, actFrom);
			//6.执行SQL语句
			count = ps.executeUpdate();
			
			
			String sql_to = "update t_act set balance = balance + ? where actno = ?";
			ps = conn.prepareStatement(sql_to);
			ps.setDouble(1, balance);
			ps.setString(2, actTo);
			count = count + ps.executeUpdate();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//关闭资源
			if(ps != null){
				try {
					ps.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		//获取响应流对象
		PrintWriter out = response.getWriter();
		if(count == 2){
			out.print("<html>");
			out.print("<head>");
			out.print("<title>银行帐户-转帐结果</title>");
			out.print("<meta content='text/html;charset=utf-8'/>");
			out.print("</head>");
			out.print("<body>");
			out.print("<center><font size='35px' color='green'>转帐成功!</font></center>");
			out.print("</body>");
			out.print("</html>");
		}else{
			out.print("<html>");
			out.print("<head>");
			out.print("<title>银行帐户-转帐结果</title>");
			out.print("<meta content='text/html;charset=utf-8'/>");
			out.print("</head>");
			out.print("<body>");
			out.print("<center><font size='35px' color='red'>转帐失败!</font></center>");
			out.print("</body>");
			out.print("</html>");
			
		}
	}

}


3.4 测试转账功能

转账之前的数据:
在这里插入图片描述
启动服务器,打开浏览器,输入 URL,访问转账页面,如下图所示:
在这里插入图片描述
在这里插入图片描述

3.5 mytomcat【事务】

JDBC 事务默认情况下支持的是自动提交,也就是说只要执行任意一条 DML 语句就会提交一次,
这显然是不符合现实的业务逻辑的,因为银行转账是从账户 A 转到账户 B 中,从账户 A 中转出需要执行一条 update 语句,向账户 B 中转入需要执行一条 update 语句,必须这两条 update 同时成功,或者同时失败,两条都成功则最终提交数据,如果转账过程中发生了异常,为了保证数据的安全,回滚操作。 代码如下图所示:

package org.bruceliu.bank.servlet;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class ActTransferServlet implements Servlet {

	@Override
	public void service(ServletRequest request, ServletResponse response) {
		//------------获取页面请求的参数------------
		String actFrom = request.getParameterValue("actFrom");
		double balance = Double.parseDouble(request.getParameterValue("balance"));
		String actTo = request.getParameterValue("actTo");
		
		//-----------连接数据库---------------
		Connection conn = null;
		PreparedStatement ps = null;
		int count = 0;
		try {
			//1.注册驱动
			// 1.加载驱动 放入Mysql驱动类的全路径,让JVM预先加载这个类到内存中
			Class.forName("com.mysql.jdbc.Driver");
			//2.获取数据库的连接对象
			conn= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bankdb?useUnicode=true&characterEncoding=UTF-8&useSSL=true","root","123456");
			//开启事务,关闭自动提交
			conn.setAutoCommit(false);
			//3.定义SQL语句框架
			String sql_from = "update t_act set balance = balance - ? where actno = ?";
			//4.进行SQL语句的预编译
			ps = conn.prepareStatement(sql_from);
			//5.进行赋值
			ps.setDouble(1, balance);
			ps.setString(2, actFrom);
			//6.执行SQL语句
			count = ps.executeUpdate();


			String sql_to = "update t_act set balance = balance + ? where actno = ?";
			ps = conn.prepareStatement(sql_to);
			ps.setDouble(1, balance);
			ps.setString(2, actTo);
			count = count + ps.executeUpdate();

			//提交事务
			conn.commit();
			
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e.printStackTrace();
			}
		}finally{
			//关闭资源
			if(ps != null){
				try {
					ps.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		//获取响应流对象
		PrintWriter out = response.getWriter();
		if(count == 2){
			out.print("<html>");
			out.print("<head>");
			out.print("<title>银行帐户-转帐结果</title>");
			out.print("<meta content='text/html;charset=utf-8'/>");
			out.print("</head>");
			out.print("<body>");
			out.print("<center><font size='35px' color='green'>转帐成功!</font></center>");
			out.print("</body>");
			out.print("</html>");
		}else{
			out.print("<html>");
			out.print("<head>");
			out.print("<title>银行帐户-转帐结果</title>");
			out.print("<meta content='text/html;charset=utf-8'/>");
			out.print("</head>");
			out.print("<body>");
			out.print("<center><font size='35px' color='red'>转帐失败!</font></center>");
			out.print("</body>");
			out.print("</html>");
			
		}
	}

}

bruceliu9527 发布了267 篇原创文章 · 获赞 79 · 访问量 1万+ 私信 关注

标签:WEB,tomcat,ps,网银,sql,print,import,balance,out
来源: https://blog.csdn.net/BruceLiu_code/article/details/104197538