1. 项目需求
中国移动,中国联通,中国电信是国内3大通信运营商,每个运营商都提供了不同的品牌套餐来应对不同的用户群,比如北京移动主要有全球通,神州行,动感地带等3大品牌套餐,每种套餐的内容和费用不同,嗖嗖移动是一个假定的通信运营商,提供了话痨套餐,网虫套餐,超人套餐,
菜单级别 | 功能 | 描述 |
---|---|---|
主菜单 | 用户登录 | 输入正确的手机号码和密码进入二级菜单列表 |
主菜单 | 用户注册 | 录入信息并开卡,用户输入的信息包括:选择卡号,选择套餐类型,输入用户名和密码,预存话费金额(预存话费金额必须满足以支付所选套餐的一个月的费用) |
主菜单 | 使用嗖嗖 | 输入正确的手机号码和密码之后,随机进入本号码所属套餐可以支持的一个场景,消费套餐余量或者话费余额,并记录消费信息.当话费余额不足时,抛出异常提醒用户充值 |
主菜单 | 话费充值 | 输入正确的用户名和密码之后,可为该卡号充值 |
主菜单 | 资费说明 | 提供各品牌套餐所包含的通话时长,上网流量,短信条数,月费用等 |
主菜单 | 退出系统 | 提出本系统 |
二级菜单 | 本月账单查询 | 可查询该卡号的套餐费用,实际消费金额,账户余额 |
二级菜单 | 套餐余量查询 | 可查询该卡号的套餐余量 |
二级菜单 | 打印消费详情 | 输入正确的卡号和密码后,可打印当前卡号用户的消费详单, 使用输出流把用户信息输出到文件 |
二级菜单 | 套餐变更 | 可变更为其他套餐类型,变更后话费余额需减去变更后的套餐费用,余额不足时需要给出信息提示,套餐变更后重新统计卡中实际消费数据以及当月消费金额 |
二级菜单 | 办理退网 | 输入正确的卡号和密码后,可以从已注册的号码列表中删除本号码,并退出系统 |
2. 项目使用的技术
-
面向对象的思想
-
封装,继承,多态,接口的使用
-
异常处理的合理使用
-
集合框架的使用
-
I/O 操作实现对文件的写
-
MySQL数据
-
JDBC操作数据库
3.1 实体类和接口
Card(电话号码类)
cardNumber 卡号
status 状态
MoboleCard(嗖嗖移动卡类)
cardNumber 卡号
username 用户名
password 密码
serPackage 所属套餐
money 账户余额
status 状态
monthlyConsumptionRecords(月消费记录类)
cardNumber 卡号
consumAmount 当月消费金额
realTalkTime 当月实际通话时长
realSMSCount 当月实际发送短信条数
realFlow 当月实际上网流量
consumeDate 消费日期
套餐类 SerPackage
talkTime 通话时长
smsCount 短信条数
price 套餐月资费
flow 上网流量
type 套餐类型
套餐类型类 SerPackageType
name 套餐名称
ConsumInfo(消费信息类)
cardNumber 卡号
type 消费类型
consumData 消费数据
consumeDate 消费日期
Scene(使用场景类)
type 场景类型
data 场景消费数据
description description
RechargeRecord(充值记录类)
amount 充值金额
rechargeDate 充值日期
cardNumber 卡号
6. 使用嗖嗖
功能分析
1) 模拟嗖嗖用户使用卡的过程,选择该功能后,输入当前卡号,通过验证后,可随机进入如下表的6个场景,要求所进入的场景的服务类型是该卡所属套餐支持的(如网虫套餐只能进入服务类型为"上网"的场景)
序号 服务类型 描述 0 通话 问候客户,谁知其如此难缠,通话90分钟 1 通话 询问妈妈身体状况,本地通话30分钟 2 短信 参与环境保护实施方案问卷调查,发送短信5条 3 短信 同时朋友本人已换手机号码,发送短信50条 4 上网 和女朋友微信视频聊天,使用流量1GB 5 上网 晚上手机在线追剧,一不留神睡着了,使用流量2GB 2) 模拟消费,进入场景之后,将按场景的描述要求消费套餐余量,如果套餐余量不足,则需要按套餐外的费用规则扣费,成功消费后,添加一条消费记录
4,代码展示
4.1,最主要的写这个项目因为要使用到数据库,所以一定要记得导入jar包,mysql.connector的jiar包可以去官网下载,直接在项目中创建一个lib的目录,如何再将jar包复制粘贴进去,然后记得添加为库
4.2类包展示
package com.fs.Dao.userImpl; import com.fs.Dao.cardDao; import com.fs.JDBCUtill.JDBCutill; import com.fs.Model.cardNumber; import com.fs.Model.serPackage; import java.sql.*; import java.time.Instant; import java.util.ArrayList; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class carDaoImpl implements cardDao { //========================================查询套餐内容,方便客户选取========================================================== @Override public ArrayList<serPackage> qury_carPackage() throws SQLException { ArrayList<serPackage> serPackages = new ArrayList<>(); Connection connection = JDBCutill.getConnection(); String sql = "select a.id,talk_time,sms_count,price,flow,name from tb_serpackage as a join tb_serpackage_type as b on a.type = b.id"; PreparedStatement statement = connection.prepareStatement(sql); ResultSet resultSet = statement.executeQuery(); while (resultSet.next()) { int id = resultSet.getInt("id"); int talkTime = resultSet.getInt("talk_time"); int smsCount = resultSet.getInt("sms_count"); double price = resultSet.getDouble("price"); int flow = resultSet.getInt("flow"); String name = resultSet.getString("name"); serPackage serPackage = new serPackage(id,talkTime,smsCount,price,flow,name); serPackages.add(serPackage); System.out.println("ID: " + id + ", 通话时长: " + talkTime + ", 免费短信: " + smsCount + ", 月租: " + price + ", 流量: " + flow + ", 套餐名字: " + name); } resultSet.close(); statement.close(); connection.close(); return serPackages; } //=======================================查询剩余电话号码,当状态为1时不查询,存入列表返回,方便用户选取=========================== @Override public ArrayList<cardNumber> qury_carNumber() throws SQLException { ArrayList<cardNumber> cardNumbers = new ArrayList<>(); Connection connection = JDBCutill.getConnection(); String sql = "select id,cardNumber from tb_card where status = 0"; PreparedStatement statement = connection.prepareStatement(sql); ResultSet resultSet = statement.executeQuery(); while (resultSet.next()){ int id = resultSet.getInt("id"); String number = resultSet.getString("cardNumber"); cardNumber cardNumber = new cardNumber(id,number); cardNumbers.add(cardNumber); System.out.println("ID:"+id+",手机号码:"+number); } resultSet.close(); statement.close(); connection.close(); return cardNumbers; } //====================================充值余额的方法,方便赚用户的钱=========================================== @Override public boolean refill_card(String cardNumber,Double balance) throws SQLException { boolean flag = false; Connection connection = JDBCutill.getConnection(); String sql = "update tb_mobole_card set money = money + ? where card_number = ?"; String sql1 = "insert into tb_recharge_record (amount,recharge_date,card_number) values (?,?,?)"; PreparedStatement statement = connection.prepareStatement(sql); PreparedStatement statement1 = connection.prepareStatement(sql1); statement.setDouble(1,balance); statement.setString(2,cardNumber); statement1.setDouble(1,balance); Timestamp currentTimestamp = Timestamp.from(Instant.now()); statement1.setTimestamp(2, currentTimestamp); statement1.setString(3,cardNumber); int count = statement.executeUpdate(); statement1.executeUpdate(); if (count > 0){ flag = true; } statement1.close(); statement.close(); connection.close(); return flag; } @Override public void month_bill(String number) throws SQLException { Connection connection = JDBCutill.getConnection(); String sql = "select type,consum_data,consume_date from tb_consuminfo where card_number = ?"; PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1,number); ResultSet resultSet = statement.executeQuery(); while (resultSet.next()){ String type = resultSet.getString("type"); int data = resultSet.getInt("consum_data"); Timestamp currentTimestamp = resultSet.getTimestamp("consume_date"); System.out.println("消费类型:"+type+"\t\t消费数据:"+data+"\t消费时间:"+currentTimestamp); } resultSet.close(); statement.close(); connection.close(); } @Override public void surplus_inquiry(String number) throws SQLException { Connection connection = JDBCutill.getConnection(); String sql = "select money,talk_time,sms_count,flow from tb_mobole_card where card_number = ?"; PreparedStatement statement = connection.prepareStatement(sql); statement.setString(1,number); ResultSet resultSet = statement.executeQuery(); if (resultSet.next()){ Double money = resultSet.getDouble("money"); int talk_time = resultSet.getInt("talk_time"); int sms_count = resultSet.getInt("sms_count"); int flow = resultSet.getInt("flow"); System.out.println("【当前号码("+number+")的余额为】"); System.out.println("余钱:"+money+"\t通话时间"+talk_time+"\t短信条数:"+sms_count+"\t流量剩余:"+flow); } resultSet.close(); statement.close(); connection.close(); } }
4.3这个项目采用的是常规的三层架构,上面就是dao层也就是方法层写的方法,每个方法在调用时都可以实现一种功能。
4.4,主界面方法展示,也急速ui层或者是view层
package com.fs.UI; import com.fs.Dao.userImpl.carDaoImpl; import com.fs.Service.userserviceimpl.cardServiceImpl; import com.fs.Service.userserviceimpl.userServiceImpl; import java.io.IOException; import java.sql.SQLException; import java.util.Scanner; public class sousouUI { public static void main(String[] args) throws SQLException, IOException { Scanner in = new Scanner(System.in); firstUI(); } //================================================首要界面,主菜单============================================ public static void firstUI() throws SQLException, IOException { Scanner in = new Scanner(System.in); userServiceImpl userService = new userServiceImpl(); 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,退出系统"); int choise = in.nextInt(); switch (choise){ case 1: System.out.println("请输入您的手机号:"); String number = in.next(); while(true){ System.out.println("请输入您的用户名:"); String userName = in.next(); System.out.println("请输入您的密码:"); String password = in.next(); System.out.println("【温馨提示】"+userService.userLogin(userName, password)); if (userService.userLogin(userName, password).equals("登录成功")){ break; } } secondMenu(number); break; case 2: System.out.println("请输入您的用户名:"); String userName = in.next(); System.out.println("请输入您的密码:"); String password = in.next(); System.out.println(userService.userAdd(userName, password)); firstUI(); break; case 3: System.out.println("请输入您的手机号:"); String user_Card = in.next(); System.out.println(userService.use_sousou(user_Card)); firstUI(); break; case 4: System.out.println("请输入您的电话号码:"); String carNumber = in.next(); System.out.println("请输入您需要充值的金额:"); Double balance = in.nextDouble(); cardServiceImpl cardService = new cardServiceImpl(); System.out.println("【友情提示】"+cardService.refill_card(carNumber, balance)); break; case 5: carDaoImpl carDao = new carDaoImpl(); carDao.qury_carPackage(); firstUI(); break; case 6:break; } } //================================================次级界面,二级菜单============================================ public static void secondMenu(String number) throws SQLException, IOException { Scanner in = new Scanner(System.in); cardServiceImpl cardService = new cardServiceImpl(); userServiceImpl userService = new userServiceImpl(); System.out.println("================选择你需要办理的业务=============="); System.out.println("1,本月账单查询"); System.out.println("2,套餐余量查询"); System.out.println("3,打印消费详情"); System.out.println("4,套餐变更"); System.out.println("5,办理退网"); int choise = in.nextInt(); switch (choise){ case 1: cardService.month_bill(number); secondMenu(number); break; case 2: cardService.Surplus_inquiry(number); secondMenu(number); break; case 3: break; case 4: userService.Package_change(number); secondMenu(number); break; case 5: System.out.println("您确认办理退网吗?输入1则确认退网,输入其他数字则取消退网"); int choise1 = in.nextInt(); if (choise1 == 1){ System.out.println(userService.drawal_Intenet(number)); } firstUI(); break; } } }
4.5,以上基本上就是最主要使用的,其他的就是一些模型的封装,模型就是用户对象或者电话卡对象的创建。
5,个人总结
对于这次的项目,我觉得我最大的问题就是由于个人有点事情所以导致没有多少时间去完成这个项目,本来我还想到了很多很多的想法比如异常日志,还有文件打印,多线程去实现计时扣费功能,文件上传这些功能都没能狗完成,所以下次我还是需要在做项目的时候合理安排好自己的时间去更多的投入到这个项目中,避免发生这次的这种问题,然后还有一点小小的问题就是,我有些地方的代码很乱,可读性很低,比如使用嗖嗖的那里,我虽然思路清晰,但是我写出来的就是很乱,一眼看上去一点都不整齐,看到别人的代码我觉得让我受益匪浅的是,之前老师讲到过魔法数字,我居然没有用到,有很多人用到了看他们的代码看的很舒服,不像我这个还是在123456的数字。所以下次我会更加的去好好的去完成我们的项目,每一次项目都是一次历练。