1. 项目需求
中国移动,中国联通,中国电信是国内3大通信运营商,每个运营商都提供了不同的品牌套餐来应对不同的用户群,比如北京移动主要有全球通,神州行,动感地带等3大品牌套餐,每种套餐的内容和费用不同,嗖嗖移动是一个假定的通信运营商,提供了话痨套餐,网虫套餐,超人套餐,各种套餐所包含的服务内容及费用如下表:
品牌套餐 | 话痨套餐 | 网虫套餐 | 超人套餐 |
---|---|---|---|
通话时长(分钟) | 600 | 0 | 300 |
上网流量 | 0 | 20 | 10 |
短信条数(条) | 100 | 0 | 50 |
费用(元/月) | 58 | 68 | 78 |
如实际使用中超出套餐内包含的通话时长,短信条数和上网流量,则按一下规则计费:
-
超出的通话: 0.2元/分
-
超出的短信:0.1元/条
-
超出的上网流量:0.1元/MB
本任务实现的"嗖嗖移动业务大厅"提供了嗖嗖移动用户的常用功能,包括新用户注册,本月账单查询,套餐余量查询,打印消费详情,套餐变更,办理退网,话费充值,查看消费记录,查看话费说明等功能.另外,还可以模拟用户通话,上网,发送短信的场景进行相应的扣费并记录消费信息.各功能介绍如下表:
菜单级别 | 功能 | 描述 |
---|---|---|
主菜单 | 用户登录 | 输入正确的手机号码和密码进入二级菜单列表 |
主菜单 | 用户注册 | 录入信息并开卡,用户输入的信息包括:选择卡号,选择套餐类型,输入用户名和密码,预存话费金额(预存话费金额必须满足以支付所选套餐的一个月的费用) |
主菜单 | 使用嗖嗖 | 输入正确的手机号码和密码之后,随机进入本号码所属套餐可以支持的一个场景,消费套餐余量或者话费余额,并记录消费信息.当话费余额不足时,抛出异常提醒用户充值 |
主菜单 | 话费充值 | 输入正确的用户名和密码之后,可为该卡号充值 |
主菜单 | 资费说明 | 提供各品牌套餐所包含的通话时长,上网流量,短信条数,月费用等 |
主菜单 | 退出系统 | 提出本系统 |
二级菜单 | 本月账单查询 | 可查询该卡号的套餐费用,实际消费金额,账户余额 |
二级菜单 | 套餐余量查询 | 可查询该卡号的套餐余量 |
二级菜单 | 打印消费详情 | 输入正确的卡号和密码后,可打印当前卡号用户的消费详单, 使用输出流把用户信息输出到文件 |
二级菜单 | 套餐变更 | 可变更为其他套餐类型,变更后话费余额需减去变更后的套餐费用,余额不足时需要给出信息提示,套餐变更后重新统计卡中实际消费数据以及当月消费金额 |
二级菜单 | 办理退网 | 输入正确的卡号和密码后,可以从已注册的号码列表中删除本号码,并退出系统 |
2. 项目使用的技术
-
面向对象的思想
-
封装,继承,多态,接口的使用
-
异常处理的合理使用
-
集合框架的使用
-
I/O 操作实现对文件的写
-
MySQL数据
-
JDBC操作数据库
3.项目需求分析
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 卡号
以电话号码类为例,其他以此类推(因篇幅原因,只提取重要代码,如需全部代码请私信):
import java.util.List;
public interface BaseDao<T> {
T queryById(Integer id);
int insert(T record);
int deleteById(Integer id);
int update(T record);
List<T> queryAll();
}
import com.fs.soso.pojo.Card;
public interface CardDao extends BaseDao<Card> {
}
import java.util.List;
public class CardDaoImpl implements CardDao {
@Override
public Card queryById(Integer id) {
return null;
}
@Override
public int insert(Card record) {
return 0;
}
@Override
public int deleteById(Integer id) {
return 0;
}
@Override
public int update(Card record) {
String sql="UPDATE tb_card SET cardNumber=?,STATUS=? WHERE id = ? ";
return JDBCUtil.executeUpdate(sql,record.getCardNumber(),record.getStatus()
,record.getId());
}
@Override
public List<Card> queryAll() {
String sql ="SELECT * FROM tb_card WHERE STATUS = 0";
return JDBCUtil.executeQuery(sql,Card.class);
}
}
3.2 各功能实现及效果图
1. 菜单显示页面,以及登录
private void doLogin() {
/**
* 1. 用户输入卡号以及密码
* 2. 使用jdbc发送select语句到数据库表根据卡号,密码查询
* 3. 如果记录存在, 判断是否是禁用状态, 如果禁用状态, 返回错误信息 "该卡号已被禁用!"
* 4. 如果记录不存在, 返回错误信息 "卡号或者密码错误"
* 5. 如果记录存在,可用状态, 登录成功, 进入到二级菜单
*/
System.out.println("\n登录界面");
System.out.print("请输入卡号:");
String cardNumber = input.next();
System.out.print("请输入密码:");
String password = input.next();
//2.使用dao对象.调用对应的方法
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
try {
//存储当前登录的卡号信息
currentLoginCard = moboleCardDao.login(cardNumber, password);
//登录成功,进入到二级菜单
showSecondMenu();
} catch (CardOrPasswordNotExitException | StatusDisableException e) {
//登录失败
System.out.println("【友情提示:】" + e.getMessage());
//返回一级菜单
showFirstMenu();
}
}
2. 用户注册
实现步骤:1. 查询所有可选的卡号, 并显示 2. 用户选择卡号 3. 查询所有的套餐类型,并展示,用户选择套餐 4. 用户输入姓名,密码, 以及预存的金额 5. 根据套餐类型查询对应用户选择的套餐, 并判断用户预存金额是否满足支付 6. 如果不满足, 请重新输入预存金额 7. 如果满足, 可以办理 8. 往tb_mobole_card表添加一条记录 9. 往tb_recharge_record表添加一条充值记录 10. 修改tb_card对应cardNumber的卡的状态 11. 办理成功,打印卡信息以及套餐信息
//1. 查询所有可选的卡号, 并显示
CardDao cardDao = new CardDaoImpl();
List<Card> cards = cardDao.queryAll();
System.out.println("\n********可选的卡号********");
for (int i = 0; i < cards.size(); i++) {
System.out.print((i + 1) + "." + cards.get(i).getCardNumber() + "\t");
//每三个一行
if ((i + 1) % 3 == 0) {
System.out.println();
}
}
//2. 用户选择卡号
System.out.print("\n请选择卡号(输入序号):");
int cardIndex = input.nextInt();
//已选的卡号
String cardNumber = cards.get(cardIndex - 1).getCardNumber();
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
MoboleCard moboleCard = new MoboleCard();
moboleCard.setCardNumber(cardNumber);
moboleCard.setUsername(name);
moboleCard.setPassword(password);
moboleCard.setSerPackage(type);
moboleCard.setMoney(cost);
moboleCardDao.insert(moboleCard);
3. 本月账单查询
private void queryCurrentMonthBill() {
String cardNumber = currentLoginCard.getCardNumber();
//1.根据登录的卡的套餐类型查询套餐月租
SerpackageDao serpackageDao = new SerpackageDaoImpl();
Serpackage serpackage = serpackageDao.queryByType(currentLoginCard.getSerPackage());
//2.根据登录的卡的卡号以及本月日期 查询月账单信息
MonthlyConsumptionRecordsDao mcrDao = new MonthlyConsumptionRecordsDaoOImpl();
MonthlyConsumptionRecords mcRecords = mcrDao.queryByCardNumberAndDate(cardNumber, DateUtil.getCurrentMonthFirstDay());
double cost = 0;
if(mcRecords != null){
cost = mcRecords.getConsumAmount();
}
//3.打印
double price = serpackage.getPrice();
System.out.println("\n****本月账单****");
System.out.println("您的卡号:"+cardNumber+",当月账单:");
System.out.println("套餐资费:"+price+"元");
System.out.println("合计:"+(price+cost)+"元");
System.out.println("账户余额:"+currentLoginCard.getMoney()+"元");
//返回到二级菜单
showSecondMenu();
4. 办理退网
private void quitNetWork() {
//直接修改卡的状态
System.out.println("\n*****办理退网*****");
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
currentLoginCard.setStatus(1);
moboleCardDao.update(currentLoginCard);
System.out.println("【友情提示】:卡号"+currentLoginCard.getCardNumber()+"办理退网成功!");
System.out.println("感谢使用");
//返回一级菜单, 设置currentLoginCard为null
currentLoginCard = null;
showFirstMenu();
}
5.套餐变更
//查询用户所选套餐的详情
SerpackageDao serpackageDao = new SerpackageDaoImpl();
Serpackage serpackage = serpackageDao.queryByType(serpackageType.getId());
//判断卡上余额是否满足支付套餐的月租
if(currentLoginCard.getMoney() >= serpackage.getPrice() ){
//可以办理
currentLoginCard.setSerPackage(serpackageType.getId());
currentLoginCard.setMoney(currentLoginCard.getMoney() - serpackage.getPrice());
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
moboleCardDao.update(currentLoginCard);
System.out.println("【友情提示】:更换套餐成功!"+serpackageType.getName()+":通话时长:"
+serpackage.getTalkTime()+"分钟/月,短信条数:"+serpackage.getSmsCount()+"条/月" +
",上网流量:"+serpackage.getFlow()/1024+"GB/月");
6. 话费充值
System.out.println("\n话费充值界面");
System.out.println("请输入手机卡号:");
String cardNumber = input.next();
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
MoboleCard moboleCard = moboleCardDao.queryByCardNumber(cardNumber);
if (moboleCard == null){
System.out.println("【友情提示】:该卡号" + cardNumber + "不存在");
}else if(moboleCard.getStatus() ==1){
System.out.println("【友情提示】:该卡号"+ cardNumber + "已被禁用");
}else {
System.out.println("您需要充值的金额是:");
int price = input.nextInt();
double money = moboleCard.getMoney() + price;
System.out.println("您现在的话费余额为"+money);
System.out.println("");
7.查看资费说明
System.out.println("\n资费说明");
SerpackageDao serpackageDao = new SerpackageDaoImpl();
SerpackageTypeDao serpackageTypeDao = new SerpackageTypeDaoImpl();
List<Serpackage> serpackages = serpackageDao.queryAll();
//登录后才能使用,不然会报空指针异常,因为是一级菜单,不需要登录就能查看
Serpackage serpackage = serpackageDao.queryByType(currentLoginCard.getId());
SerpackageType serpackageType = serpackageTypeDao.queryById(currentLoginCard.getId());
System.out.println("**********套餐说明**********");
System.out.println("序号\t套餐名称\t通话时长(分/月)\t短信条数(条/月)\t上网流量(GB/月)");
System.out.println(serpackages.getId()+"\t"+serpackageType.getName()+"\t"+serpackage.getTalkTime()+"\t"+serpackage.getSmsCount()+"\t"+serpackage.getFlow());
4.项目展望与总结
嗖嗖移动大厅项目作为Java部分的总结训练,涉及内容广泛,设计全面。由于功能较多,项目初期实现起来具有一定难度。关键在于理清所需的类及其属性和方法,这对项目的成功至关重要。
该项目不仅锻炼了编程技能,还加深了对Java面向对象编程的理解,对从事Java开发的程序员来说是一个很好的实践机会