一,项目背景
中国移动,中国联通,中国电信是国内3大通信运营商,每个运营商都提供了不同的品牌套餐来应对不同的用户群,比如北京移动主要有全球通,神州行,动感地带等3大品牌套餐,每种套餐的内容和费用不同,嗖嗖移动作为第四款运行商应运而生
二,项目功能介绍
移动大厅项目包括以下核心功能:
新用户注册,本月账单查询,套餐余量查询,打印消费详情,套餐变更,办理退网,话费充值,查看消费记录,查看话费说明等功能.另外,还可以模拟用户通话,上网,发送短信的场景进行相应的扣费并记录消费信息
三.主要功能代码
1,app总体界面
public static void showFirstMenu(){
System.out.println("***** ***********欢迎使用嗖嗖移动业务大厅****************");
System.out.println("1.用户登录\t2.用户注册\t3.使用嗖嗖\t4.话费充值\t5.资费说明\t6.退出系统");
System.out.println("请选择:");
switch (scanner.nextInt()){
case 1:
moboleCard=SosoServies.login();
if (moboleCard!=null){
showSecondMenu();
}else {
showFirstMenu();
}
break;
case 2:
SosoServies.register();
showFirstMenu();
break;
case 3:
SosoServies.useSoso();
showFirstMenu();
break;
case 4:
SosoServies.recharge();
showFirstMenu();
break;
case 5:
SosoServies.showSerPackage();
showFirstMenu();
break;
case 6:
System.exit(1);
default:
System.out.println("没有此选项,请重新输入");
showFirstMenu();
}
}
2.二级页面
public static void showSecondMenu(){
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("请选择(输入1~5选择功能,其他键返回上一级):");
switch (scanner.nextInt()){
case 1:
SosoServies.showMonthlyConsumption(moboleCard);
showSecondMenu();
break;
case 2:
SosoServies.showSerPackageMargin(moboleCard);
showSecondMenu();
break;
case 3:
SosoServies.showConsumInfo(moboleCard);
showSecondMenu();
break;
case 4:
SosoServies.updateSerPackage(moboleCard);
showSecondMenu();
break;
case 5:
SosoServies.outMoboleCard(moboleCard);
showFirstMenu();
break;
default:
showFirstMenu();
}
}
3.连接数据库并查询数据
public List<MoboleCard> queryAll() {
Connection conn = null;
try {
conn = JDBCUtil.getConnection();
QueryRunner queryRunner=new QueryRunner();
String sql ="select id,card_number cardNumber,username,password,ser_package serPackage,money,status from tb_mobole_card";
return queryRunner.query(conn,sql,new BeanListHandler<MoboleCard>(MoboleCard.class));
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtil.close(conn);
}
return null;
}
登录后直接进入二级菜单
4.登录功能
public static MoboleCard login() {
System.out.println("请输入卡号");
String cardNumber = scanner.next();
System.out.println("请输入密码");
String password = scanner.next();
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
MoboleCard moboleCard = moboleCardDao.queryByCardNumber(cardNumber);
if (moboleCard == null) {
System.out.println("请输入正确的卡号");
} else {
if (!moboleCard.getPassword().equals(password)) {
System.out.println("请输入正确的密码");
} else if (moboleCard.getStatus() == SystemConstant.MOBOLE_STATUS_FREEZE) {
System.out.println("该号码已被冻结,请联系管理员");
} else {
return moboleCard;
}
}
return null;
}
5.注册功能
public static void register() {
System.out.println("*****可选择的卡号*****");
CradDao cradDao = new CradDaoImpl();
List<Crad> crads = cradDao.queryAll();
List<Crad> canUsedCrads = new ArrayList<>();
crads.stream().filter(crad -> crad.getStatus() == SystemConstant.CRAD_NO_USED).forEach(crad -> canUsedCrads.add(crad));
for (int i = 0; i < canUsedCrads.size(); i++) {
System.out.print(i + 1 + "." + canUsedCrads.get(i).getCardNumber() + "\t");
if ((i + 1) % 3 == 0) {
System.out.println();
}
}
System.out.println();
System.out.println("请选择您的卡号:");
Crad crad = canUsedCrads.get(scanner.nextInt() - 1);
SerPackageTypeDao serPackageTypeDao = new SerPackageTypeDaoImpl();
List<SerPackageType> serPackageTypes = serPackageTypeDao.queryAll();
for (int i = 0; i < serPackageTypes.size(); i++) {
System.out.print((i + 1) + "." + serPackageTypes.get(i).getName() + "\t");
}
System.out.println();
System.out.println("请选择套餐");
SerPackageType serPackageType = serPackageTypes.get(scanner.nextInt() - 1);
System.out.println("请输入姓名");
String username = scanner.next();
System.out.println("请输入密码");
String password = scanner.next();
System.out.println("请输入预存话费金额");
Double money = scanner.nextDouble();
SerPackageDao serPackageDao = new SerPackageDaoImpl();
SerPackage serPackage = serPackageDao.queryByType(serPackageType.getId());
Double price = serPackage.getPrice();
while (money < price) {
System.out.println("您预存话费不足以支付本月套餐资费,请重新输入!");
System.out.println("请输入预存话费金额");
money = scanner.nextDouble();
}
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
MoboleCard moboleCard = new MoboleCard(crad.getCardNumber(), username, password, serPackageType.getId(), money - price, SystemConstant.MOBOLE_STATUS_NORMAL);
System.out.println("注册成功!卡号:" + moboleCard.getCardNumber() + ",用户名:" + moboleCard.getUsername() + ",当前余额:" + moboleCard.getMoney());
System.out.println(serPackageType.getName() + "通话时长:" + serPackage.getTalkTime() + "分钟/月");
moboleCardDao.insert(moboleCard);
RechargeRecord rechargeRecord = new RechargeRecord(money, new Date(), moboleCard.getCardNumber());
RechargeRecordDao rechargeRecordDao = new RechargeRecordDaoImpl();
rechargeRecordDao.insert(rechargeRecord);
crad.setStatus(SystemConstant.CRAD_USED);
cradDao.updateByID(crad);
}
6.使用搜搜(模拟用户消费场景)
public static void useSoso() {
System.out.println("请输入手机卡号:");
String cardNumber = scanner.next();
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
MoboleCard moboleCard = moboleCardDao.queryByCardNumber(cardNumber);
if (moboleCard == null) {
System.out.println("请输入正确的卡号");
} else if (moboleCard.getStatus() == SystemConstant.MOBOLE_STATUS_FREEZE) {
System.out.println("该号码已被冻结,请联系管理员");
} else if (moboleCard.getMoney() < 0) {
moboleCard.setStatus(SystemConstant.MOBOLE_STATUS_FREEZE);
moboleCardDao.updateByID(moboleCard);
System.out.println("[友情提示]:您的余额不足,请充值后使用.");
} else {
int serPackageType = moboleCard.getSerPackage();
SerPackageDao serPackageDao = new SerPackageDaoImpl();
SerPackage serPackage = serPackageDao.queryByType(serPackageType);
SceneDao sceneDao = new SceneDaoImpl();
List<Scene> scenes = new ArrayList<>();
int talkTime = 0;
int smsCount = 0;
int flow = 0;
int flowPackageData=0;
if (serPackage.getTalkTime() > 0) {
List<Scene> talk = sceneDao.queryByType("通话");
for (Scene s : talk) {
scenes.add(s);
}
talkTime = serPackage.getTalkTime();
}
if (serPackage.getSmsCount() > 0) {
List<Scene> sms = sceneDao.queryByType("短信");
for (Scene s : sms) {
scenes.add(s);
}
smsCount = serPackage.getSmsCount();
}
if (serPackage.getFlow()+flowPackageData > 0) {
List<Scene> flows = sceneDao.queryByType("上网");
for (Scene s : flows) {
scenes.add(s);
}
flow = serPackage.getFlow();
}
int random = (int) (Math.random() * scenes.size());
Scene scene = scenes.get(random);
System.out.println(scene.getDescription());
String sceneType = scene.getType();
Integer data = scene.getData();
int talkTimeUsed = 0;
int smsCountUsed = 0;
int flowUsed = 0;
double consumAmount = 0.0;
MonthlyConsumptionRecords monthlyConsumptionRecords = new MonthlyConsumptionRecords(cardNumber, consumAmount, talkTimeUsed, smsCountUsed, flowUsed, new Date());
MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
MonthlyConsumptionRecords mcr = monthlyConsumptionRecordsDao.queryByCardNumber(cardNumber, new Date());
if (mcr == null) {
monthlyConsumptionRecordsDao.insert(monthlyConsumptionRecords);
mcr = monthlyConsumptionRecordsDao.queryByCardNumber(cardNumber, new Date());
}
talkTimeUsed = mcr.getRealTalkTime();
smsCountUsed = mcr.getRealSMSCount();
flowUsed = mcr.getRealFlow();
consumAmount = mcr.getConsumAmount();
if (sceneType.equals("通话")) {
talkTimeUsed += data;
double talkConsumAmount=0;
if (talkTimeUsed > talkTime) {
if(talkTimeUsed-talkTime<data){
talkConsumAmount = (talkTimeUsed-talkTime) * 0.2;
}else {
talkConsumAmount = data * 0.2;
}
moboleCard.setMoney(moboleCard.getMoney() - talkConsumAmount);
consumAmount += talkConsumAmount;
}
}else if (sceneType.equals("短信")) {
smsCountUsed += data;
double smsConsumAmount =0;
if (smsCountUsed > smsCount) {
if(smsCountUsed-smsCount<data){
smsConsumAmount = (smsCountUsed-smsCount) * 0.2;
}else {
smsConsumAmount = data * 0.1;
}
moboleCard.setMoney(moboleCard.getMoney() - smsConsumAmount);
consumAmount += smsConsumAmount;
}
}else if (sceneType.equals("上网")) {
flowUsed += data;
double flowconsumAmount =0;
if (flowUsed > (flow+flowPackageData)) {
if(flow+flowPackageData-flowUsed>data){
flowconsumAmount = (flow+flowPackageData-flowUsed) * 0.1;
}else {
flowconsumAmount = data * 0.1;
}
moboleCard.setMoney(moboleCard.getMoney() - flowconsumAmount);
consumAmount += flowconsumAmount;
}
}
moboleCardDao.updateByCardNumber(moboleCard, cardNumber);
ConsumInfo consumInfo = new ConsumInfo(cardNumber, sceneType, data, new Date());
ConsumInfoDao consumInfoDao = new ConsumInfoDaoImpl();
consumInfoDao.insert(consumInfo);
monthlyConsumptionRecords.setRealTalkTime(talkTimeUsed);
monthlyConsumptionRecords.setRealSMSCount(smsCountUsed);
monthlyConsumptionRecords.setRealFlow(flowUsed);
monthlyConsumptionRecords.setConsumAmount(consumAmount);
monthlyConsumptionRecordsDao.updateByCardNumber(cardNumber, monthlyConsumptionRecords);
}
}
7.话费充值
public static void recharge() {
System.out.println("*******话费充值*******");
System.out.println("请输入要充值卡号:");
String cardNumber = scanner.next();
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
MoboleCard moboleCard = moboleCardDao.queryByCardNumber(cardNumber);
if (moboleCard == null) {
System.out.println("请输入正确的卡号");
} else {
System.out.println("请输入充值金额");
double amount = scanner.nextDouble();
RechargeRecord rechargeRecord = new RechargeRecord(amount, new Date(), cardNumber);
RechargeRecordDao rechargeRecordDao = new RechargeRecordDaoImpl();
rechargeRecordDao.insert(rechargeRecord);
moboleCard.setMoney(moboleCard.getMoney() + amount);
moboleCardDao.updateByID(moboleCard);
System.out.println("[友情提示] :充值成功,卡上余额:" + moboleCard.getMoney());
}
}
8.资费说明
public static void showSerPackage() {
SerPackageDao serPackageDao = new SerPackageDaoImpl();
SerPackageTypeDao serPackageTypeDao = new SerPackageTypeDaoImpl();
List<SerPackageType> serPackageTypes = serPackageTypeDao.queryAll();
System.out.println("序号\t套餐名称\t通话时长(分/月)\t短信条数(条/月)\t上网流 量(GB/月)");
for (SerPackageType serPackageType : serPackageTypes) {
SerPackage serPackage = serPackageDao.queryByType(serPackageType.getId());
int flow = serPackage.getFlow() / 1024;
System.out.println(serPackage.getId()
+ "\t" + serPackageType.getName()
+ "\t" + serPackage.getTalkTime()
+ "\t\t\t\t" + serPackage.getSmsCount()
+ "\t\t\t\t" + flow);
}
}
9.本月账单查询
public static void showMonthlyConsumption(MoboleCard moboleCard) {
System.out.println("********本月账单查询********");
System.out.println("您的卡号:"+moboleCard.getCardNumber()+",当月账单:");
MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
MonthlyConsumptionRecords monthlyConsumptionRecords = monthlyConsumptionRecordsDao.queryByCardNumber(moboleCard.getCardNumber(),new Date());
SerPackageDao serPackageDao=new SerPackageDaoImpl();
SerPackage serPackage = serPackageDao.queryByType(moboleCard.getSerPackage());
double price= serPackage.getPrice();
System.out.println("套餐资费:"+price+"元");
double consumAmount= 0;
if (monthlyConsumptionRecords==null){
consumAmount=0;
}else {
consumAmount= monthlyConsumptionRecords.getConsumAmount();
}
System.out.println("合计:"+(price+consumAmount)+"元");
System.out.println("账户余额:"+moboleCard.getMoney()+"元");
}
10.套餐余量查询
public static void showSerPackageMargin(MoboleCard moboleCard){
MoboleCardDao moboleCardDao=new MoboleCardDaoImpl();
//查询套餐
SerPackageDao serPackageDao=new SerPackageDaoImpl();
SerPackage serPackage = serPackageDao.queryByType(moboleCard.getSerPackage());
//插入数据
MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
MonthlyConsumptionRecords monthlyConsumptionRecords = monthlyConsumptionRecordsDao.queryByCardNumber(moboleCard.getCardNumber(),new Date());
//计算余量
int talkTime = serPackage.getTalkTime();
int smsCount = serPackage.getSmsCount();
int flow = serPackage.getFlow();
if(monthlyConsumptionRecords != null){
talkTime = talkTime - monthlyConsumptionRecords.getRealTalkTime() > 0?talkTime - monthlyConsumptionRecords.getRealTalkTime():0;
smsCount = smsCount - monthlyConsumptionRecords.getRealSMSCount() > 0?smsCount - monthlyConsumptionRecords.getRealSMSCount():0;
flow = flow - monthlyConsumptionRecords.getRealFlow() >0 ?flow - monthlyConsumptionRecords.getRealFlow():0 ;
}
//输出
System.out.println("************套餐余量查询************");
System.out.println("您的卡号是"+moboleCard.getCardNumber()+",套餐内剩余:");
System.out.println("通话时长:"+talkTime+"分钟");
System.out.println("短信条数:"+smsCount+"条");
System.out.println("上网流量:"+flow/1024+"GB");
}
11.打印消费详单
public static void showConsumInfo(MoboleCard moboleCard){
ConsumInfoDao consumInfoDao=new ConsumInfoDaoImpl();
System.out.println("请输入本年需要查询的月份(1-12):");
int month=scanner.nextInt();
if (month<1||month>12){
System.out.println("没有这个月份,请重新输入");
}else {
Date date = new Date();
date.setMonth(month - 1);
List<ConsumInfo> consumInfos = consumInfoDao.queryByConsumeDate(moboleCard.getCardNumber(), date);
if (consumInfos.isEmpty()) {
System.out.println("[友情提示] :对不起,不存在本卡号" + (date.getMonth() + 1) + "月消费记录");
} else {
System.out.println("序号\t类型\t数据\t日期");
for (ConsumInfo consumInfo : consumInfos) {
System.out.println(consumInfo.getId() + "\t" + consumInfo.getType() +
"\t" + consumInfo.getConsumData() + "\t" + consumInfo.getConsumeDate());
}
}
}
}
12.套餐变更
public static void updateSerPackage(MoboleCard moboleCard){
SerPackageDao serPackageDao =new SerPackageDaoImpl();
SerPackageTypeDao serPackageTypeDao=new SerPackageTypeDaoImpl();
List<SerPackageType> serPackageTypes = serPackageTypeDao.queryAll();
SerPackage oldSerPackage = serPackageDao.queryByType(moboleCard.getSerPackage());
System.out.println("*****套餐变更******");
int i=1;
for (SerPackageType serPackageType:serPackageTypes) {
System.out.print(i+"."+serPackageType.getName()+"\t");
i++;
}
System.out.println();
System.out.println("请选择(序号):");
int no=scanner.nextInt()-1;
if (no> serPackageTypes.size()||no<0){
System.out.println("[友情提示] :没有此套餐,请重新输入");
}else {
SerPackageType serPackageType=serPackageTypes.get(no);
int id=serPackageType.getId();
SerPackage newSerPackage = serPackageDao.queryByType(id);
double price=newSerPackage.getPrice()-oldSerPackage.getPrice();
if(id==moboleCard.getSerPackage()){
System.out.println("[友情提示] : 您已经是"+moboleCard.getSerPackage()+"的用户,无需更换!");
}else if (price>moboleCard.getMoney()){
System.out.println("[友情提示] : 对不起,您的余额不足以支付新套餐本月资费,请充值后办理变更套餐业务!");
}else {
System.out.println("[友情提示] :更换套餐成功!" + serPackageType.getName() + ":通话时长:"
+ newSerPackage.getTalkTime() + "分钟/月,短信条数:" + newSerPackage.getSmsCount()
+ "条/月,上网流量:" + newSerPackage.getFlow() / 1024 + "GB/月,月租:"
+ newSerPackage.getPrice() + "元/月");
moboleCard.setSerPackage(no+1);
moboleCard.setMoney(moboleCard.getMoney()-price);
MoboleCardDao moboleCardDao=new MoboleCardDaoImpl();
moboleCardDao.updateByCardNumber(moboleCard,moboleCard.getCardNumber());
}
}
}
13.办理退网
public static void outMoboleCard(MoboleCard moboleCard){
if(moboleCard.getMoney()<0){
System.out.println("你有欠款"+moboleCard.getMoney()+",请充值后再退网");
}else {
MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
moboleCardDao.deleteById(moboleCard.getId());
CradDao cradDao = new CradDaoImpl();
cradDao.updateByCardNumber(moboleCard.getCardNumber());
MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
monthlyConsumptionRecordsDao.deleteByCardNumber(moboleCard.getCardNumber());
RechargeRecordDao rechargeRecordDao = new RechargeRecordDaoImpl();
rechargeRecordDao.deleteByCardNumber(moboleCard.getCardNumber());
ConsumInfoDao consumInfoDao = new ConsumInfoDaoImpl();
consumInfoDao.deleteByCardNumber(moboleCard.getCardNumber());
System.out.println("[友情提示] :卡号" + moboleCard.getCardNumber() + "办理退网成功! ");
}
}
三,遇到的问题
由于对jdbc操作不熟练,在连接数据库与idea时经常出现空指针异常,经过多次实现连接已经解决.
四,获得的收获
通过这次项目实践,我融会贯通了之前一段时间所学习的所有知识,
1. 面向对象编程(OOP):理解了类和对象的概念,掌握了封装、继承和多态的基本原理,能够设计和实现简单的面向对象程序。
2. 异常处理:学会了捕获和处理异常的机制,了解了常见的异常类型及其处理方式,能够编写更健壮的代码。
3. 常用类: 熟悉了Java中常用的类,如String、Math、System、Date等,能够在实际开发中合理使用这些类。
4. 多线程:了解了线程的创建与管理,掌握了通过实现Runnable接口和继承Thread类创建线程,并能使用synchronized关键字来处理线程间的同步问题。
5.集合:理解了Java集合的各种接口和类,包括List、Set、Map等,能够使用集合类存储和操作对象。
6.网络编程:理解了Socket编程的基本原理,能够使用Java实现简单的客户端和服务器通信。
7. 反射:学习了反射机制,能够在运行时动态访问类的属性和方法,理解其在框架和库中的应用场景。
8. 数据库与JDBC: 掌握了通过JDBC连接MySQL数据库的方法,能够进行基本的增删改查(CRUD)操作。
提升了问题解决能力和编程能力,能够更好地应对实际项目中的挑战和问题。