嗖嗖移动业务大厅
1.项目概述
在数字化时代,通信服务的个性化需求日益增长。嗖嗖移动业务大厅项目应运而生,旨在为用户提供一个模拟的、全面的通信服务体验。本项目通过Java技术栈实现,涵盖了用户注册、登录、套餐选择、消费模拟、账单查询等一系列功能。
2.需求分析
用户需求是产品设计的出发点。嗖嗖移动业务大厅项目的核心需求包括:
用户身份验证:安全的用户登录和注册机制。
套餐管理:灵活的套餐选择与变更功能。
消费模拟:模拟用户通话、短信、上网等行为,并进行相应的扣费。
账单和余量查询:方便用户随时查询自己的消费情况和套餐余量。
充值与退网:提供便捷的话费充值和退网服务。
技术选型
Java语言的跨平台性、面向对象特性以及强大的生态系统使其成为本项目的首选。MySQL数据库用于数据持久化,JDBC作为数据库访问技术,确保了数据操作的灵活性和高效性。
3.系统设计
系统设计采用分层架构,明确划分了表示层、业务逻辑层和数据访问层。面向对象的设计方法贯穿始终,通过类图和流程图清晰地展现了系统结构。
4.流程图
5.核心功能实现
核心功能的实现是项目成功的关键。以下是部分核心功能的实现细节:
5.1用户注册与登录
用户注册时,系统验证预存话费是否满足套餐要求,并创建用户对象。登录时,系统通过卡号和密码进行身份验证。
代码展示
public void login() throws SQLException {
System.out.println("请输入手机卡号:");
card_number=scanner.next();
System.out.println("请输入密码:");
password=scanner.next();
List<MoboleCard> login = service.login(card_number, password);
if (login.size()==0){
System.out.println("[友情提示]:卡号或密码错误");
}
else if (login.get(0).getStatus()==1){
System.out.println("[友情提示]:该卡号已被禁用");
}else {
secondarymenu();
}
}
public void register() throws SQLException {
System.out.println("*******可选择的卡号*******");
List<Card> list = service.register();
for (int i=0;i<list.size();i++) {
System.out.print(i+1+","+list.get(i).getCardNumber()+"\t");
if (i==2){
System.out.println("");
}
}
System.out.println("");
System.out.println("请选择您的卡号:");
int cardnumber=scanner.nextInt()-1;
if (cardnumber<=list.size()) {
System.out.println("1,话痨套餐;\t2,网虫套餐\t3,超人套餐\t\t请选择套餐");
int type = scanner.nextInt();
System.out.println("请输入姓名:");
String name = scanner.next();
System.out.println("请输入密码:");
String password1 = scanner.next();
Double monty = 0.0;
System.out.println("请输入预存话费:");
if (type == 1) {
monty = scanner.nextDouble() - 58;
while (monty < 0) {
System.out.println("请输入预存话费:");
monty = scanner.nextDouble() - 58;
}
} else if (type == 2) {
monty = scanner.nextDouble() - 68;
while (monty < 0) {
System.out.println("请输入预存话费:");
monty = scanner.nextDouble() - 68;
}
} else if (type == 3) {
monty = scanner.nextDouble() - 78;
while (monty < 0) {
System.out.println("请输入预存话费:");
monty = scanner.nextDouble() - 78;
}
}
MoboleCard moboleCard = new MoboleCard(list.get(cardnumber).getCardNumber(), name, password1, type, monty, 0);
int registermobole = service.registermobole(moboleCard);
System.out.println(registermobole > 0 ? "注册成功" : "注册失败");
System.out.println("卡号:" + list.get(cardnumber).getCardNumber() + ",用户名:" + name + ",当前余额" + monty);
}else {
System.out.println("输入错误!");
}
}
5.2套餐变更
用户选择新套餐后,系统检查账户余额,确保有足够的资金进行套餐变更,并更新用户套餐信息。
代码展示:
public void change() throws SQLException {
System.out.println("*****套餐变更*****");
List<MoboleCard> login = service.login(card_number, password);
List<SerPackageType> serpackagetype = service.selectserpackagetype();
if (serpackagetype.size() != 0) {
for (SerPackageType ser : serpackagetype) {
System.out.print(ser.getId() + "," + ser.getName() + "\t");
}
System.out.println("请选择:");
int number = scanner.nextInt();
if (number > serpackagetype.size() || number < 0) {
System.out.println("输入错误!");
secondarymenu();
} else if (login.get(0).getSer_package() == number) {
System.out.println("[友情提示]:您已经是该套餐用户,无需更换");
} else if (login.get(0).getSer_package() != number && number == 1 && login.get(0).getMoney() < 58) {
System.out.println("[友情提示]:您的余额不足以支付新套餐本月的咨费,请充值后办理变更业务!");
} else if (login.get(0).getSer_package() != number && number == 2 && login.get(0).getMoney() < 68) {
System.out.println("[友情提示]:您的余额不足以支付新套餐本月的咨费,请充值后办理变更业务!");
} else if (login.get(0).getSer_package() != number && number == 3 && login.get(0).getMoney() < 78) {
System.out.println("[友情提示]:您的余额不足以支付新套餐本月的咨费,请充值后办理变更业务!");
} else {
int change = service.change(number, card_number);
System.out.print(change > 0 ? "更换套餐成功!" : "更换套餐失败!");
if (number == 1) {
System.out.println("话痨套餐:通话时长:600分钟/月,短信条数:100条/月,上网流量:0GB/月,月租:58元/月");
double balance = 58;
service.changebalance(balance, card_number);
} else if (number == 2) {
System.out.println("网虫套餐:通话时长:0分钟/月,短信条数:0条/月,上网流量:20GB/月,月租:68元/月");
double balance = 68;
service.changebalance(balance, card_number);
} else if (number == 3) {
System.out.println("超人套餐:通话时长:300分钟/月,短信条数:50条/月,上网流量:10GB/月,月租:78元/月");
double balance = 78;
service.changebalance(balance, card_number);
}
}
}else {
System.out.println("没有套8餐可供选择!");
}
}
5.3账单查询
系统根据用户的消费记录和套餐信息,计算并展示用户的总费用和账户余额。
代码展示:
public void billinquiry() throws SQLException {
List<MoboleCard> login = service.login(card_number, password);
SerPackage selectserpackage = service.selectserpackage(login.get(0).getSer_package());
for (MoboleCard mob : login) {
System.out.println("*****本月账单查询*****");
System.out.println("您的卡号:"+mob.getCard_number()+",当月账单:");
if (selectserpackage==null){
System.out.println("未选择套餐:");
}else {
System.out.println("套餐咨费:"+selectserpackage.getPrice());
}
System.out.println("账户余额:"+mob.getMoney());
}
}
5.4消费模拟
用户选择模拟消费的场景,系统根据用户套餐类型和场景描述,计算消费的时长、条数或流量,并更新用户的套餐余量和账户余额。
代码展示:
public void use() throws SQLException {
// 使用嗖嗖, 1. 套餐余量 >= 消费的数量 只需要把套餐余量 - 消费数量
// 2. 套餐余量 < 消费的数量 超出部分使用额外扣费
// 2.1 卡的余额支付额外扣费: 正常消费
// 2.2 卡的余额无法满足额外扣费: 只能消费余额最大可消费的数量
/*
1. 输入卡号,查询卡,做验证,卡号存在(在moboleCard表存在),状态可用
2. 查询所有的场景, 随机选择一个场景
3. 根据卡的套餐类型 查询办理的套餐,得到套餐的免费使用数量
4. 根据卡号,当月日期 查询这张表的当月消费记录,
第一种情况: 有记录, 表示这张卡当月已经开始消费
第二种情况: 无记录: 表示该卡当月未消费, 需要添加该卡当月消费记录: 0 0 0
5. 计算套餐余量 = 套餐免费使用量 - 当月消费数量 第一种情况: >0: 有剩余量 套餐余量 = 差 第二种情况: <=0: 套餐余量 = 0
计算最大消费数量 : 第一种情况: 等于场景消费数量 第二种情况: 卡最大消费数量
卡最大消费数量 = 套餐余量 + 余额消费数量
6. 往消费记录表添加一条消费记录, 修改月消费记录表: 修改卡的余额
7.打印
*/
// 1. 输入卡号,查询卡,做验证,卡号存在(在moboleCard表存在),状态可用
System.out.println("请输入手机卡号:");
String cardnumber=scanner.next();
List<MoboleCard> select = service.select(cardnumber);
if (select.size()>0&&select.get(0).getStatus()==0&&select.get(0).getMoney()>0) {
int ser_package = select.get(0).getSer_package();
SerPackage serpackage = service.selectserpackage(ser_package);
// System.out.println(serpackage);
System.out.println("序号\t\t操作\t\t(分钟/条数/MB)\t\t具体操作");
List<Scene> scene = service.selectscene();
for (Scene scene1 : scene) {
System.out.println(scene1.getId() + "\t\t" + scene1.getType() + "\t\t\t" + scene1.getData() + "\t\t\t\t" + scene1.getDescription());
}
System.out.println("");
List<MonthlyConsumptionRecords> records = service.checkremaining(cardnumber);
if (records.size()>0) {
System.out.println("请选择您想要进行的操作");
int number = scanner.nextInt();
while (number > scene.size() || number <= 0) {
System.out.println("输入错误!请重新输入!");
number = scanner.nextInt();
}
//消费类型
String type = scene.get(number - 1).getType();
//实际消费数量
int costCount = scene.get(number - 1).getData();
//实际消费金额
double cost = 0.0;
//套餐的余量
int freeCount = 0;
int max = 0; //最大消费数量
double price = 0;//计费
String errorInfo = "";
service.inserttb_consuminfo(cardnumber, type, costCount);
switch (type) {
case "通话":
freeCount = serpackage.getTalk_time() - records.get(0).getReal_talk_time();
if (freeCount>0){
freeCount=freeCount-costCount;
if (freeCount<0){
price = (0 - freeCount) * 0.2;
}
}else if (freeCount<=0){
price=costCount*0.2;
}
int i = service.updatereal_talk_time(price, costCount, cardnumber);
break;
case "短信":
freeCount = serpackage.getTalk_time() - records.get(0).getReal_talk_time();
if (freeCount>0){
freeCount=freeCount-costCount;
if (freeCount<0){
price = (0 - freeCount) * 0.1;
}
}else if (freeCount<=0){
price=costCount*0.1;
}
int i1 = service.updatereal_SMS_count(price, costCount, cardnumber);
break;
case "上网":
freeCount = serpackage.getTalk_time() - records.get(0).getReal_talk_time();
if (freeCount>0){
freeCount=freeCount-costCount;
if (freeCount<0){
price = (0 - freeCount) * 0.1;
}
}else if (freeCount<=0){
price=costCount*0.1;
}
int i2 = service.updatereal_flow(price, costCount, cardnumber);
break;
case "听音乐":
freeCount = serpackage.getTalk_time() - records.get(0).getReal_talk_time();
if (freeCount>0){
freeCount=freeCount-costCount;
if (freeCount<0){
price = (0 - freeCount) * 0.1;
}
}else if (freeCount<=0){
price=costCount*0.1;
}
openExe1();
int i3 = service.updatereal_flow(price, costCount, cardnumber);
break;
}
System.out.println(scene.get(number - 1).getDescription());
int i = service.updatetb_mobole_card(price,cardnumber);
List<MoboleCard> select1 = service.select(cardnumber);
if (select1.get(0).getMoney() < 0&&select1.get(0).getMoney() > -100) {
System.out.println("您已经欠费!请及时充值!");
}
if (select1.get(0).getMoney() < -100){
System.out.println("您欠的钱太多了,即将禁用您的号码!");
int updatestatus = service.updatestatus(cardnumber);
int updatecard = service.updatecard(cardnumber);
}
}
}
else if(select.size()==0){
System.out.println("卡号尚未注册!");
}else if (select.get(0).getMoney()<0){
System.out.println("您的号码已经欠费!请充值后使用");
}
else{
System.out.println("卡号被禁用了!");
}
}
6.异常处理
系统的健壮性在很大程度上取决于异常处理的能力。系统需要妥善处理用户输入错误、账户余额不足、数据库操作失败等异常情况。
/**
* 状态不可用异常
*/
public class StatusDisableException extends Exception {
public StatusDisableException() {
}
public StatusDisableException(String message) {
super(message);
}
public StatusDisableException(String message, Throwable cause) {
super(message, cause);
}
public StatusDisableException(Throwable cause) {
super(cause);
}
public StatusDisableException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
/**
* 卡号或者密码不存在的异常
*/
public class CardOrPasswordNotExitException extends Exception {
public CardOrPasswordNotExitException() {
}
public CardOrPasswordNotExitException(String message) {
super(message);
}
public CardOrPasswordNotExitException(String message, Throwable cause) {
super(message, cause);
}
public CardOrPasswordNotExitException(Throwable cause) {
super(cause);
}
public CardOrPasswordNotExitException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
7.安全性考虑
安全性是在线系统不可或缺的一部分。本项目采取了以下措施来确保系统的安全性:
使用HTTPS协议加密数据传输。
对用户密码进行加密存储。
实施输入验证以防止SQL注入攻击。
定期进行安全审计和漏洞扫描。
用户界面设计
用户界面的直观性和易用性对于提升用户体验至关重要。本项目使用JavaFX构建图形用户界面,提供了清晰的导航和反馈。
8.测试策略
全面的测试策略确保了系统的质量和可靠性。测试包括单元测试、集成测试、性能测试和用户测试。
9.未来发展方向
随着技术的不断进步,嗖嗖移动业务大厅项目将继续发展,增加个性化推荐、智能客服、多平台支持和数据分析等功能。
10.总结
嗖嗖移动业务大厅项目是一个综合性的通信服务模拟平台,它不仅展示了Java技术栈的强大能力,也为用户提供了一个安全、便捷、个性化的服务体验。随着项目的不断迭代和优化,我们期待为用户提供更加卓越的服务。