《Java手写系列》

编程入门 行业动态 更新时间:2024-10-11 21:21:28

《Java手写<a href=https://www.elefans.com/category/jswz/34/1770787.html style=系列》"/>

《Java手写系列》

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 {@Overridepublic 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 blocke.printStackTrace();}finally{//关闭资源if(ps != null){try {ps.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(conn != null){try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.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 {@Overridepublic 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 blocke.printStackTrace();}finally{//关闭资源if(ps != null){try {ps.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(conn != null){try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.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 {@Overridepublic 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();//提交事务connmit();} 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 blocke.printStackTrace();}}if(conn != null){try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.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>");}}}

更多推荐

《Java手写系列》

本文发布于:2024-03-09 20:17:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726018.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:系列   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!