soso移动营业大厅(纯后端+MySQL数据库+JDBC)

一、项目需求

中国移动,中国联通,中国电信是国内3大通信运营商,每个运营商都提供了不同的品牌套餐来应对不同的用户群,比如北京移动主要有全球通,神州行,动感地带等3大品牌套餐,每种套餐的内容和费用不同,嗖嗖移动是一个假定的通信运营商,提供了话痨套餐,网虫套餐,超人套餐,各种套餐所包含的服务内容及费用如下表:

品牌套餐话痨套餐网虫套餐超人套餐
通话时长(分钟)6000300
上网流量02010
短信条数(条)100050
费用(元/月)586878

如实际使用中超出套餐内包含的通话时长,短信条数和上网流量,则按一下规则计费:

  • 超出的通话: 0.2元/分

  • 超出的短信:0.1元/条

  • 超出的上网流量:0.1元/MB

本任务实现的"嗖嗖移动业务大厅"提供了嗖嗖移动用户的常用功能,包括新用户注册,本月账单查询,套餐余量查询,打印消费详情,套餐变更,办理退网,话费充值,查看消费记录,查看话费说明等功能.另外,还可以模拟用户通话,上网,发送短信的场景进行相应的扣费并记录消费信息.各功能介绍如下表:

菜单级别功能描述
主菜单用户登录输入正确的手机号码和密码进入二级菜单列表
主菜单用户注册录入信息并开卡,用户输入的信息包括:选择卡号,选择套餐类型,输入用户名和密码,预存话费金额(预存话费金额必须满足以支付所选套餐的一个月的费用)
主菜单使用嗖嗖输入正确的手机号码和密码之后,随机进入本号码所属套餐可以支持的一个场景,消费套餐余量或者话费余额,并记录消费信息.当话费余额不足时,抛出异常提醒用户充值
主菜单话费充值输入正确的用户名和密码之后,可为该卡号充值
主菜单资费说明提供各品牌套餐所包含的通话时长,上网流量,短信条数,月费用等
主菜单退出系统提出本系统
二级菜单本月账单查询可查询该卡号的套餐费用,实际消费金额,账户余额
二级菜单套餐余量查询可查询该卡号的套餐余量
二级菜单打印消费详情输入正确的卡号和密码后,可打印当前卡号用户的消费详单, 使用输出流把用户信息输出到文件
二级菜单套餐变更可变更为其他套餐类型,变更后话费余额需减去变更后的套餐费用,余额不足时需要给出信息提示,套餐变更后重新统计卡中实际消费数据以及当月消费金额
二级菜单办理退网输入正确的卡号和密码后,可以从已注册的号码列表中删除本号码,并退出系统

二、项目需求分析

2.1 登陆

  1. 让用户输入手机号码, 密码,

  2. 根据手机号码,密码到数据库: tb_mobole_card查询

  3. 如果没有记录: 登录失败, 错误提示: 手机号码或者密码错误

  4. 如果有记录,但是状态是1(冻结): 登录失败, 错误提示: 该手机号码已冻结,请联系工作人员

  5. 登录成功, 进入到二级菜单

2.2 注册

  1. 查询所有可用卡 tb_card

  2. 查询所有的套餐类型, 用户选择套餐类型,

  3. 根据用户选择的套餐类型, 查询套餐信息

  4. 用户输入用户,密码. 输入充值金额

  5. 根据输入金额与用户选择套餐的月租比较, 输入金额小于月租, 错误提示, 用户再重新输入

  6. 如果大于等于, 往用户卡表(tb_mobole_card)插入一条记录

  7. 修改tb_card表,用户选择该手机号码的卡状态设置为不可用

  8. 往充值记录表中添加一条充值记录

  9. 显示办卡成功, 输出用户卡相关信息,以及套餐信息

  10. 跳转到一级菜单

​​​​2.3 使用soso

  1. 输入手机号码   查询到用户卡信息   查询套餐 2. 如果卡冻结状态, 无法使用嗖嗖 显示错误信息 3. 查询所有的场景, 随机一个场景进行模拟   得到场景类型,  数据

  2. 假设随机第一个场景, 通话场景, 打90分钟电话,

    剩余免费余量 = 套餐最大免费量 - 月消费当月消费量(查询月消费)

  3. 如果用户的卡的剩余免费余量 > =场景的数量, 不需要扣钱, 在月消费记录表, 当月增加使用量的值

  4. 如果用户的卡的剩余免费余量 < 场景的数量, 需要扣钱, 在月消费记录表, 当月增加使用量的值,超出的部分进行扣费, 修改的用户卡的余额

  5. 往消费记录表进行记录本次消费 消费记录表

2.4 套餐变更

  1. 查询所有的套餐类型

  2. 根据当前登录的手机号码, 查询当前用户卡信息

  3. 用户选择套餐类型,根据用户现在的套餐明细得到套餐类型

  4. 判断用户选择的套餐是否是用户卡现在套餐,如果是,提示,

  5. 如果不是,根据用户选择的套餐类型,查询对应的套餐明细

  6. 判断用户卡的余额是否满足该套餐的月租, 如果不满足, 提示

  7. 如果满足, 更换套餐, 修改用户卡信息(套餐,余额)

  8. 打印用户新套餐的明细

三、代码展示

1.系统大体结构

2.使用的jar包

commons-dbutils-1.7.jarmysql-connector-java-5.1.47.jar
提供了简化数据库操作的工具连接 MySQL 数据库的 JDBC 驱动程序

这两个 JAR 包通常用于 Java 应用程序中与数据库进行交互的过程中

hamcrest- 2.1jarjunit-4.12.jar 
提供更加灵活和可读性强的测试断言方式用于编写和运行单元测试

这两个库通常会一起被用于编写高质量的测试代码,以确保代码的正确性和稳定性。

3.完整代码

1、常量类(constant包)
package com.lx.soso.constant;


public interface SystemConstant {

     /**
      * 用户正常状态
      */
     int MOBOLE_STATUS_NORMAL=0;
     /**
      * 用户冻结状态
      */
     int MOBOLE_STATUS_FREEZE=1;

     /**
      * 手机卡的正常状态
      */
     int CARD_STATUS_NORMAL = 0;

     /**
      * 手机卡卡号的禁用状态
      * 已被使用
      */
     int CARD_STATUS_FREEZE = 1;

     /**
      * 一级管理员
      */
     int FIRST_LEVEL_ADMINISTRATOR = 1;

     /**
      * 二级管理员
      */
     int SECONDARY_LEVEL_ADMINISTRATOR = 2;

     /**
      * 已回复
      */
     int REPLIED = 0;

     /**
      * 未回复
      */
     int NOT_REPLIED = 1;
}
2、功能实现类(service包)
package com.lx.soso.service;

import com.lx.soso.constant.SystemConstant;
import com.lx.soso.dao.*;
import com.lx.soso.dao.impl.*;
import com.lx.soso.entity.*;
import com.lx.soso.ui.SosoApp;
import com.lx.soso.util.DateUtil;
import com.lx.soso.util.JDBCUtil;

import java.util.*;


public class SoSoService {
    Scanner input = new Scanner(System.in);
    //private String number = null;

    /**
     * 登陆
     *
     * @return
     */
    public MoboleCard login() {
        System.out.print("请输入手机卡号:");
        String number = input.next();
        System.out.print("请输入密码:");
        String password = input.next();

        //实例化赋给接口
        //2.调用dao层类的方法
        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        MoboleCard moboleCard = moboleCardDao.queryByNumber(number);

        if (moboleCard == null) {//没有找到该手机号
            System.out.println("【友情提示:】卡号或者密码错误!");
        } else {//有该手机号 ,但可能状态异常和密码错误
            if (!moboleCard.getPassword().equals(password)) {//密码错误
                System.out.println("【友情提示:】卡号或者密码错误!");
            } else if (moboleCard.getStatus().intValue() == SystemConstant.MOBOLE_STATUS_FREEZE) {//状态异常(为1)
                System.out.println("【友情提示:】该手机号码已冻结,请联系工作人员!");
            } else {
                System.out.println("【友情提示:】登陆成功!");
                return moboleCard;
            }

        }

        return null;
    }

    /**
     * 注册
     */
    public void register() {
        System.out.println("*********可选的卡号*********");
        CardDao cardDao = new CardDaoImpl();
        //查询所以可以注册的卡号
        List<Card> cards = cardDao.queryByStatus(SystemConstant.CARD_STATUS_NORMAL);
        if (cards == null) {//没有可用卡号时不可注册
            System.out.println("【友情提示:】暂时没有可用卡号,请稍后再试!");
            return;
        }
        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();
            }
        }
        System.out.println();

        int cardsId = 0;
        do {
            System.out.print("请选择您需要办理的卡号序号:");
            cardsId = input.nextInt();
            if (cardsId <= 0 || cardsId >= cards.size()){
                System.out.println("【友情提示:】输入有误,请重新输入!");
            }

        } while (cardsId <= 0 || cardsId >= cards.size());
        String number = cards.get(cardsId - 1).getCardNumber();

        //查询所以套餐类型
        SerpackageTypeDao serpackageTypeDao = new SerpackageTypeDaoImpl();
        List<SerpackageType> serpackageTypes = serpackageTypeDao.queruAll();
        if (serpackageTypes == null) {//没有可用卡号时不可注册
            System.out.println("【友情提示:】没有套餐信息,更多套餐还在制作中。。。");
            return;
        }

        for (int i = 0; i < serpackageTypes.size(); i++) {
            System.out.print((i + 1) + "." + serpackageTypes.get(i).getName() + "\t");
        }
        System.out.println();
        System.out.print("请选择套餐:");
        int serpackageId = input.nextInt();
        SerpackageType serpackageType = serpackageTypes.get(serpackageId - 1);

        //根据选择的套餐获取详信息
        SerpackageDao serpackageDao = new SerpackageDaoImpl();
        Serpackage serpackage = serpackageDao.queryByType(serpackageId);


        //输入用户密码和姓名,还有充值金额
        System.out.print("请输入姓名:");
        String name = input.next();

        System.out.print("请输入密码:");
        String password = input.next();

        int money = 0;

        do {
            System.out.print("请输入预存话费金额:");
            money = input.nextInt();
            if (money < serpackage.getPrice()) {
                System.out.println("您预存的话费不足以支付您所选的套餐的本月资费,请重新输入!");
            }
        } while (money < serpackage.getPrice());//费用小于预存话费一种循环

        //费用大于所选套餐资费
        //修改选择的卡状态
        Card card = new Card();
        card.setCardNumber(number);
        card.setStatus(SystemConstant.CARD_STATUS_FREEZE);
        cardDao.update(card);

        //费用大于所选套餐资费
        //添加一个用户
        MoboleCard moboleCard = new MoboleCard();
        moboleCard.setCardNumber(number);
        moboleCard.setUsername(name);
        moboleCard.setPassword(password);
        moboleCard.setSerPackage(serpackageId);
        moboleCard.setMoney(money - serpackage.getPrice());
        moboleCard.setStatus(SystemConstant.MOBOLE_STATUS_NORMAL);

        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        moboleCardDao.insert(moboleCard);


        //费用大于所选套餐资费
        //添加一条充值记录
        RechargeRecord rechargeRecord = new RechargeRecord();
        rechargeRecord.setCardNumber(number);
        rechargeRecord.setAmount((double) money);
        rechargeRecord.setRechargeDate(new Date());

        RechargeRecordDao rechargeRecordDao = new RechargeRecordDaoImpl();
        rechargeRecordDao.rechargeByNumber(rechargeRecord);

        //

        System.out.println("您的个人信息:");
        System.out.println("用户名:" + moboleCard.getUsername() + "\t用户当前余额:" + moboleCard.getMoney());
        System.out.println("您所办理的套餐信息:");
        System.out.println("套餐名称 \t通话时长(分/月)\t短信条数(条/月)\t套餐月资费(元/月)\t上网流量(GB/月)");
        System.out.println(serpackageType.getName() + "\t\t" + serpackage.getTalkTime() + "\t\t\t\t" + serpackage.getSmsCount()
                + "\t\t\t\t" + serpackage.getPrice() + "\t\t\t" + serpackage.getFlow());

    }


    /**
     * 使用嗖嗖
     */
    public void useSoso() {
        System.out.print("请输入手机号码:");
        String number = input.next();

        //根据手机号码查用户信息
        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        MoboleCard moboleCard = moboleCardDao.queryByNumber(number);
        if (moboleCard == null) {
            System.out.println("【友情提示:】该手机号码为空号无法使用,请您注册后再使用!");
        } else if (moboleCard.getStatus() == SystemConstant.MOBOLE_STATUS_FREEZE) {
            System.out.println("【友情提示:】该手机号码已冻结,请联系工作人员!");
        } else {
            //获取随机场景信息
            SceneDao sceneDao = new SceneDaoImpl();
            List<Scene> scenes = sceneDao.queruAll();
            Random random = new Random();
            int i = random.nextInt(scenes.size());

            String type = scenes.get(i).getType();//获取随机的套餐类型
            Integer data = scenes.get(i).getData();//获取随机场景的消费数量
            String description = scenes.get(i).getDescription();//获取随机数据场景的内容

            //获取办理的套餐信息
            Integer id = moboleCard.getSerPackage();//获取当前号码办理的套餐编号
            SerpackageDao serpackageDao = new SerpackageDaoImpl();
            Serpackage serpackage = serpackageDao.queryByType(id);//所办理套餐信息


            //获取当月实际消费
            MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
            //List<MonthlyConsumptionRecords> monthlyConsumptionRecordsList = monthlyConsumptionRecordsDao.queryByNumber(number);
            Date firstDay = DateUtil.getMonthFirst(new Date());//获取当月一号日期

            MonthlyConsumptionRecords monthlyConsumptionRecords = monthlyConsumptionRecordsDao.queryByNumberAndDate(number, firstDay);//存储当月消费信息对象

            if (monthlyConsumptionRecords == null) {
                monthlyConsumptionRecords = new MonthlyConsumptionRecords();
                monthlyConsumptionRecords.setCardNumber(number);
                monthlyConsumptionRecords.setRealFlow(0);
                monthlyConsumptionRecords.setConsumAmount(0.0);
                monthlyConsumptionRecords.setRealTalkTime(0);
                monthlyConsumptionRecords.setRealSmsCount(0);
                monthlyConsumptionRecords.setConsumeDate(firstDay);
                //添加这条数据
                monthlyConsumptionRecordsDao.insert(monthlyConsumptionRecords);
                //让这条数据有id
                monthlyConsumptionRecords = monthlyConsumptionRecordsDao.queryByNumberAndDate(number, firstDay);
            }

            //计算剩余随机到的消费类型免费余量
            int remainingFreeQuantity = 0;

            if (type.equals("通话")) {
                //计算的通话的余量
                remainingFreeQuantity = serpackage.getTalkTime() - monthlyConsumptionRecords.getRealTalkTime();
                monthlyConsumptionRecords.setRealTalkTime(monthlyConsumptionRecords.getRealTalkTime() + data);
            }else if (type.equals("短信")) {
                //计算的短信的余量
                remainingFreeQuantity = serpackage.getSmsCount() - monthlyConsumptionRecords.getRealSmsCount();
                monthlyConsumptionRecords.setRealSmsCount(monthlyConsumptionRecords.getRealSmsCount() + data);
            }else if (type.equals("上网")) {
                //计算的上网的余量
                remainingFreeQuantity = serpackage.getFlow() - monthlyConsumptionRecords.getRealFlow();
                monthlyConsumptionRecords.setRealFlow(monthlyConsumptionRecords.getRealFlow() + data);
            }

            //计算随机到的场景消费
            double consumption = 0.0;
            if (remainingFreeQuantity <= 0) {//没有免费余量,全额扣费
                consumption = costComputational(data, type);
            } else {
                if (remainingFreeQuantity < data) { //有费用,但费用不足超出部分扣费
                    consumption = costComputational(data - remainingFreeQuantity, type);
                }
            }

            //修改用户余额
            moboleCard.setMoney(moboleCard.getMoney() - consumption);
            moboleCardDao.update(moboleCard);

            //添加一次消费记录
            ConsuminfoDao consuminfoDao = new ConsuminfoDaoImpl();
            Consuminfo consuminfo = new Consuminfo();
            consuminfo.setCardNumber(number);
            consuminfo.setType(type);
            consuminfo.setConsumData(data);
            consuminfo.setConsumeDate(new Date());

            consuminfoDao.insert(consuminfo);


            //根据随机到的场景类型
            // 修改当月消费类型数据
            monthlyConsumptionRecordsDao.updateType(monthlyConsumptionRecords, type);
            //修改实际消费金额


            System.out.println(description);


        }

    }



    /**
     * @param number
     * @param type
     * @return 计算费用
     */
    private double costComputational(int number, String type) {
        double cost = 0;
        if (type.equals("通话")) {
            cost = number * 0.2;
        } else if (type.equals("短信")) {
            cost = number * 0.1;
        } else if (type.equals("上网")) {
            cost = number * 0.1;
        }
        return cost;
    }

    /**
     * 查询套餐信息
     * 资费说明
     *
     * @return
     */
    public boolean printSerpackage() {
        SerpackagesDao serpackageDao = new SerpackagesDaosImpl();
        Map<SerpackageType, Serpackage> serpackages = serpackageDao.querySerpackage();
        if (serpackages != null) {
            System.out.println("序号 \t套餐名称 \t通话时长(分/月)\t短信条数(条/月)\t套餐月资费(元/月)\t上网流量(GB/月)");
            serpackages.forEach((key, value) -> {
                System.out.println(key.getId() + "\t\t" + key.getName() + "\t\t" + value.getTalkTime() + "\t\t\t\t" + value.getSmsCount() + "\t\t\t\t" + value.getPrice() + "\t\t\t" + value.getFlow());
            });
            System.out.println("【友情提示:】查询成功!");
            return true;
        } else {
            System.out.println("【友情提示:】没有套餐信息,更多套餐还在制作中。。。");
            return false;
        }

    }

    /**
     * 话费充值
     * @return 添加成功
     */
    public boolean Recharge() {
        System.out.println("******话费充值******");
        System.out.print("请输入要充值的卡号:");
        String number = input.next();
        System.out.print("请输入充值金额:");
        String amount = input.next();

        //根据号码获取用户信息
        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        MoboleCard moboleCard = moboleCardDao.queryByNumber(number);
        if (moboleCard == null){
            System.out.println("【友情提示:】没有该卡号!");
            return false;
        }else if (moboleCard.getStatus().intValue() ==SystemConstant.MOBOLE_STATUS_FREEZE){
            System.out.println("【友情提示:】该手机号码已冻结无法充值,请联系工作人员!");
            return false;
        }else {

            moboleCard.setMoney(moboleCard.getMoney()+Integer.parseInt(amount));
            int i = moboleCardDao.updateByMoney(moboleCard);

            if (i == 1) {//充值成功在进行添加充值记录操作
                //创建RechargeRecord(充值记录)对象
                RechargeRecord rechargeRecord = new RechargeRecord();
                rechargeRecord.setAmount(Double.valueOf(amount));//将传入的string转为double
                rechargeRecord.setRechargeDate(new Date());
                rechargeRecord.setCardNumber(number);

                //创建dao进行添加操作
                RechargeRecordDao rechargeRecordDao = new RechargeRecordDaoImpl();
                rechargeRecordDao.rechargeByNumber(rechargeRecord);

                Double money = moboleCardDao.queryByNumber(number).getMoney();//查询修改后的余额值

                System.out.println("【友情提示:】充值成功,卡上余额:" + money + "元");
                return true;
            } else {
                System.out.println("【友情提示:】充值失败!");
                return false;
            }
        }

    }

    /**
     * 反馈功能
     */
    public int feedback() {
        if (SosoApp.number == null) {
            System.out.print("请输入电话号码:");
            SosoApp.number = input.next();//13677478866;13666557788
        }
        System.out.println("反馈信息:");
        FeedbackDao feedbackDao = new FeedbackDaoImp();
        List<Feedback> notReplied = feedbackDao.queruReplied(SosoApp.number, SystemConstant.NOT_REPLIED);
        System.out.println("未回复("+notReplied.size()+")");
        List<Feedback> replied = feedbackDao.queruReplied(SosoApp.number, SystemConstant.REPLIED);
        System.out.println("已回复("+replied.size()+")");
        System.out.println("1.查看回复\t2.反馈\t3.返回上一级");
        System.out.print("选择操作(1~3):");
        int op = input.nextInt();
        switch (op){
            case 1:
                for (int i = 0; i < replied.size(); i++) {
                    Feedback feedback = replied.get(i);
                    System.out.println("------编号:"+(i+1)+"-----------");
                    System.out.println("反馈时间:"+feedback.getFeedbackDate()+"\t反馈号码:"+feedback.getCardNumber()+"\n反馈内容:"+feedback.getFeedbackContent());
                    System.out.println("回复信息:"+feedback.getAdministratorReply());
                    System.out.println("回复人:"+feedback.getAdministratorName());
                    System.out.println("-----------------------");
                    System.out.println("下一个(输入1,其他退出查看)");
                    int op1 = input.nextInt();
                    boolean next = true;
                    while (next){
                        if (op1 == 1){
                            if (i == replied.size()-1){
                                System.out.println("【温馨提示:】没有回复了!");
                                System.out.println("-----------------------");
                                next = false;
                            }
                        }else {
                            System.out.println("【友情提示】:输入有误,请重新输入");

                            next = false;

                        }
                    }
                }
                //todo 操作管理员
                feedback();
                break;
            case 2:
                System.out.println("请输入反馈内容:");
                String reply = input.next();

                Feedback feedback = new Feedback();//new一个 Feedback(反馈信息)对象

                feedback.setCardNumber(SosoApp.number);//电话
                feedback.setFeedbackContent(reply);//反馈内容
                feedback.setFeedbackDate(new Date());//时间

                int insert = feedbackDao.insert(feedback);//添加反馈记录
                if (insert == 1){
                    System.out.println("【温馨提示】反馈成功!");
                    return insert;
                }
                feedback();
                break;
                //todo 操作管理员

            case 3:

                //todo 操作管理员
                break;
            case 4:
                //返回上级菜单
                System.out.println("【友情提示】:返回上一级菜单成功");
                break;
            default:
                System.out.println("【友情提示】:输入有误,请重新输入");
                break;
        }



        return 0;


    }




    //-------------------------二级菜单服务-------------------------------------


    /**
     * 本月账单查询
     */
    public void queryMonthBill() {
        //number = "13677478866";
        System.out.println("你的卡号是:"+ SosoApp.number);
        System.out.println("当月账单:");

        //获取当月套餐资费
        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        Integer type = moboleCardDao.queryByNumber(SosoApp.number).getSerPackage();//套餐类型
        SerpackageDao serpackageDao = new SerpackageDaoImpl();
        Double price = serpackageDao.queryByType(type).getPrice();//办理的套餐资费
        System.out.println("套餐资费:"+price);

        //获取当月额外消费
        MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
        MonthlyConsumptionRecords monthlyConsumptionRecords = monthlyConsumptionRecordsDao.queryByNumberAndDate(SosoApp.number,DateUtil.getMonthFirst(new Date()));
        Double consumAmount = monthlyConsumptionRecords.getConsumAmount();

        //计算合计消费
        System.out.println("合计消费:"+(consumAmount+price));

        //打印账户余额
        System.out.println("账户余额:"+moboleCardDao.queryByNumber(SosoApp.number).getMoney());



    }



    /**
     * 套餐余量查询
     */
    public void queryPackageBalance() {
        //number = "13652363333";

        //获取办理套餐信息
        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        Integer type = moboleCardDao.queryByNumber(SosoApp.number).getSerPackage();//套餐类型
        SerpackageDao serpackageDao = new SerpackageDaoImpl();
        Serpackage serpackage = serpackageDao.queryByType(type);
        Integer talkTime = serpackage.getTalkTime();//通话
        Integer smsCount = serpackage.getSmsCount();//短信
        Integer flow = serpackage.getFlow();//上网

        //获取当月实际用量
        MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
        MonthlyConsumptionRecords monthlyConsumptionRecords = monthlyConsumptionRecordsDao.queryByNumberAndDate(SosoApp.number,DateUtil.getMonthFirst(new Date()));
        if (monthlyConsumptionRecords == null) {
            monthlyConsumptionRecords = new MonthlyConsumptionRecords();
            monthlyConsumptionRecords.setCardNumber(SosoApp.number);
            monthlyConsumptionRecords.setRealFlow(0);
            monthlyConsumptionRecords.setConsumAmount(0.0);
            monthlyConsumptionRecords.setRealTalkTime(0);
            monthlyConsumptionRecords.setRealSmsCount(0);
            monthlyConsumptionRecords.setConsumeDate(DateUtil.getMonthFirst(new Date()));
            //添加这条数据
            monthlyConsumptionRecordsDao.insert(monthlyConsumptionRecords);
            //让这条数据有id
            monthlyConsumptionRecords = monthlyConsumptionRecordsDao.queryByNumberAndDate(SosoApp.number, DateUtil.getMonthFirst(new Date()));
        }

        Integer realTalkTime = monthlyConsumptionRecords.getRealTalkTime();//通话
        Integer realSmsCount = monthlyConsumptionRecords.getRealSmsCount();//短信
        Integer realFlow = monthlyConsumptionRecords.getRealFlow();//上网

        Integer residueTalkTime = talkTime-realTalkTime;
        Integer residuesmsCount = smsCount-realSmsCount;
        Integer residueflow = flow - realFlow;

        if (residueTalkTime >=0){
            System.out.println("通话时间:"+realTalkTime+"分钟");
        }else {
            System.out.println("通话时间:0分钟");
        }

        if (residuesmsCount >=0){
            System.out.println("短信条数:"+residuesmsCount+"条");
        }else {
            System.out.println("短信条数:0条");
        }

        if (residueflow >=0){
            String format = String.format("%.2f",  (double)residueflow / 1024);
            System.out.println("上网流量:"+format+"G");
        }else {
            System.out.println("上网流量:0G");
        }

    }



    /**
     * 打印消费详单
     */
    public void printConsumptionDetails() {
        //String number = "13677478866";
        System.out.print("请输入本年需要查询的月份(1~12):");
        String month = input.next();

        ConsuminfoDao consuminfoDao = new ConsuminfoDaoImpl();
        List<Consuminfo> consuminfoList = consuminfoDao.queryByNumber(SosoApp.number);
        List <Consuminfo>ThisMonthConsuminfo = new ArrayList();
        //ThisMonthConsuminfo = null;
        if (consuminfoList == null){
            System.out.println("【友情提示】:对不起,您还没有使用过soso快去使用把。");
        }else {
            for (int i = 0; i < consuminfoList.size(); i++) {

                Date consumeDate = consuminfoList.get(i).getConsumeDate();
                int consumeMonth = DateUtil.getMonth(consumeDate);
                if (month.equals(String.valueOf(consumeMonth))){
                    ThisMonthConsuminfo.add(consuminfoList.get(i));
                }
            }
            if (ThisMonthConsuminfo.size() > 0){
                System.out.println("序号\t\t类型\t\t数据\t\t日期");
                for (int i = 0; i < ThisMonthConsuminfo.size(); i++) {
                    System.out.println((i+1)+"\t\t"+ThisMonthConsuminfo.get(i).getType()+"\t\t"+
                            ThisMonthConsuminfo.get(i).getConsumData()+"\t\t"+ThisMonthConsuminfo.get(i).getConsumeDate());
                }
            }else {
                System.out.println("【友情提示】:对不起,不存在本卡号"+month+"月消费记录!");
            }
        }

    }

    /**
     * 套餐变更
     */
    public void packageChanges() {

        SerpackageTypeDao serpackageTypeDao = new SerpackageTypeDaoImpl();
        List<SerpackageType> serpackageTypes = serpackageTypeDao.queruAll();
        if (serpackageTypes == null) {//没有可用卡号时不可注册
            System.out.println("【友情提示:】没有套餐信息,更多套餐还在制作中。。。");
            return;
        }

        for (int i = 0; i < serpackageTypes.size(); i++) {
            System.out.print((i + 1) + "." + serpackageTypes.get(i).getName() + "\t");
        }
        System.out.println();
        Integer serpackageId = 0;


        do {
            System.out.print("请选择套餐:");
            serpackageId = input.nextInt();
            if (serpackageId <= 0 || serpackageId >= serpackageTypes.size()){
                System.out.println("【友情提示:】输入有误,请重新输入!");
            }

        } while (serpackageId <= 0 || serpackageId >= serpackageTypes.size());

        //根据选择的套餐获取详信息
        SerpackageDao serpackageDao = new SerpackageDaoImpl();
        Serpackage serpackage = serpackageDao.queryByType(serpackageId);
        Double price = serpackage.getPrice();//套餐费用


        //查询用户信息
        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        MoboleCard moboleCard = moboleCardDao.queryByNumber(SosoApp.number);
        Double money = moboleCard.getMoney();
        Integer type = moboleCard.getSerPackage();
        //serpackageId.equals(type+"")
        if (serpackageId == type){
            System.out.println("【友情提示]】:您已经是改套餐的用户,无需更换!");
        }else {
            if (money < price){
                System.out.println("【友情提示】:对不起,您的余额不足以支付新套餐本月资费,请充值后办理变更套餐业务!");
            }else {

                moboleCard.setMoney(money - price);
                moboleCardDao.updateByMoney(moboleCard);
                moboleCardDao.updatebyNumberSerPackage(SosoApp.number, serpackageId);
                System.out.println("【友情提示】:更换"+serpackageTypes.get(serpackageId-1).getName()+"成功!");
                System.out.println("套餐信息:通话时长:"+ serpackage.getTalkTime()+"分钟/月,短信条数:"+serpackage.getSmsCount()+"条/月,上网流量:"+serpackage.getFlow()+"GB/月,月租:"+serpackage.getPrice()+"元/月");
            }
        }

    }

    /**
     * 办理退网
     */
    public void logout() {
        //根据号码删除用户信息
        MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
        moboleCardDao.deleteByNumber(SosoApp.number);

        //修改电话卡表该卡状态
        Card card = new Card();
        card.setCardNumber(SosoApp.number);
        card.setStatus(SystemConstant.CARD_STATUS_NORMAL);

        CardDao cardDao = new CardDaoImpl();
        cardDao.update(card);

        List<Card> cards = cardDao.queryByStatus(SystemConstant.CARD_STATUS_NORMAL);
        long count = cards.stream().filter(str -> str.getStatus().equals(SystemConstant.CARD_STATUS_NORMAL)&str.getCardNumber().equals(SosoApp.number)).count();
        if (count == 1){
            System.out.println("用户卡号:"+SosoApp.number+"退网办理成功");
        }

    }

    /*-------------------------------------------------管理员操作------------------------------------------*/

    /**
     * 管理员登陆
     * @return
     */
    public Administrators ALogin() {
        System.out.println("***********管理员登陆***********");
        System.out.print("请输入账号:");
        String number = input.next();
        System.out.print("请输入密码:");
        String password = input.next();

        //实例化赋给接口
        //调用dao层类的方法
        AdministratorsDao administratorsDao = new AdministratorsDaoImpl();
        Administrators administrators = administratorsDao.queruByNumber(number);

        if (administrators == null) {//没有找到该账号
            System.out.println("【友情提示:】卡号或者密码错误!");

        } else {//有但密码错误
            if (!administrators.getPassword().equals(password)) {//密码错误
                System.out.println("【友情提示:】卡号或者密码错误!");

            } else {
                System.out.println("【友情提示:】登陆成功!");
                return administrators;
            }

        }
        return null;
    }

    public void viewFeedback(){
        FeedbackDao feedbackDao = new FeedbackDaoImp();
        List<Feedback> feedbackList = feedbackDao.queruAll();
        if (feedbackList.size() == 0){
            System.out.println("【温馨提示】暂时还没有未回复的反馈");
        }
        for (int i = 0; i < feedbackList.size(); i++) {

            Feedback feedback = feedbackList.get(i);
            System.out.println("------编号:"+(i+1)+"-----------");
            System.out.println("反馈时间:"+feedback.getFeedbackDate()+"\t反馈号码:"+feedback.getCardNumber()+"\n反馈内容:"+feedback.getFeedbackContent());
            System.out.println("-----------------------");
            System.out.println("是否处理(1.处理,2.跳过)");
            System.out.print("请选择:");
            int op = input.nextInt();
            boolean next = true;
            int op2 = 0;
            while (next){
                if (op == 1){

                    MoboleCardDao moboleCardDao = new MoboleCardDaoImpl();
                    MoboleCard moboleCard = moboleCardDao.queryByNumber(feedback.getCardNumber());//账户信息
                    if (moboleCard == null){
                        System.out.println("【温馨提示】非本运营商用户!");
                    }
                    SerpackageDao serpackageDao = new SerpackageDaoImpl();
                    MonthlyConsumptionRecordsDao monthlyConsumptionRecordsDao = new MonthlyConsumptionRecordsDaoImpl();
                    System.out.println("************反馈功能************");
                    System.out.println("1.查看账户信息\t2.查看账户各项消费\t3.解除冻结\t4.回复\t5.下一个\t6.退出反馈");
                    System.out.print("请选择操作:");
                    op2 = input.nextInt();
                    switch (op2){
                        case 1:
                            System.out.println("-----账户信息-----");
                            if (moboleCard != null){
                                String status = null;
                                if (moboleCard.getStatus() == SystemConstant.MOBOLE_STATUS_FREEZE){
                                    status = "冻结";
                                }else if (moboleCard.getStatus() == SystemConstant.MOBOLE_STATUS_NORMAL){
                                    status = "正常";
                                }

                                System.out.println("账户状态:"+status);
                                //System.out.println("所属套餐:"+moboleCard.getSerPackage());
                                System.out.println("账户余额:"+moboleCard.getMoney());
                            }else {
                                System.out.println("【温馨提示】非本运营商用户,没有消息!");
                            }

                            System.out.println("----------------");
                            break;
                        case 2:
                            System.out.println("-----扣费情况-----");
                            if (moboleCard != null){
                                Serpackage serpackage = serpackageDao.queryByType(moboleCard.getSerPackage());//套餐信息
                                MonthlyConsumptionRecords monthlyConsumptionRecords =
                                        monthlyConsumptionRecordsDao.queryByNumberAndDate(moboleCard.getCardNumber(), DateUtil.getMonthFirst(feedbackList.get(i).getFeedbackDate()));//实际消费

                                if (monthlyConsumptionRecords.getRealTalkTime()>serpackage.getTalkTime()){//实际消费大于套餐
                                    if (serpackage.getTalkTime() == 0){
                                        System.out.print("套餐没有免费短信条数");
                                    }else {
                                        System.out.print("套餐使用超出,");
                                    }
                                    System.out.println("通话使用扣费");
                                }else {
                                    System.out.println("通话未造成扣费");
                                }

                                if (monthlyConsumptionRecords.getRealSmsCount()>serpackage.getSmsCount()){//实际消费大于套餐
                                    if (serpackage.getTalkTime() == 0){
                                        System.out.print("套餐没有免费短信条数");
                                    }else {
                                        System.out.print("套餐使用超出,");
                                    }
                                    System.out.println("短信使用扣费");
                                }else {
                                    System.out.println("短信未造成扣费");
                                }

                                if (monthlyConsumptionRecords.getRealFlow()>serpackage.getFlow()){//实际消费大于套餐
                                    if (serpackage.getTalkTime() == 0){
                                        System.out.print("套餐没有免费上网流量,");
                                    }else {
                                        System.out.print("套餐使用超出,");
                                    }
                                    System.out.println("上网使用扣费");
                                }else {
                                    System.out.println("流量未造成扣费");
                                }
                            }else {
                                System.out.println("【温馨提示】非本运营商用户,没有信息!");
                            }
                            System.out.println("------------------");
                            break;
                        case 3:
                            if (moboleCard != null){
                                moboleCardDao.updateByNumberStatus(moboleCard.getCardNumber());//解除冻结
                            }else {
                                System.out.println("【温馨提示】非本运营商用户,无法进行该项服务!");
                            }

                            break;
                        case 4:
                            System.out.println("请输入回复内容:");
                            String reply = input.next();

                            AdministratorsDao administratorsDao = new AdministratorsDaoImpl();
                            Administrators administrators = administratorsDao.queruByNumber(SosoApp.accountName);//SosoApp.accountNumber
                            String administratorName = administrators.getName();

                            feedbackList.get(i).setAdministratorReply(reply);//讲回复内容添加到 处理的 feedback对象
                            feedbackList.get(i).setAdministratorName(administratorName);//处理管理员姓名
                            feedbackList.get(i).setState(SystemConstant.REPLIED);//回复后将反馈状态改为已回复
                            //将回复修改
                            int update = feedbackDao.update(feedbackList.get(i));
                            if (update == 1){
                                System.out.println("【温馨提示】回复成功");
                            }


                            break;
                        case 5:
                            if (i == feedbackList.size()-1){
                                System.out.println("【温馨提示:】用户反馈查看完毕");
                            }
                            next = false;
                            break;
                        case 6:
                            return;
                        default:
                            System.out.println("【友情提示】:输入有误,请重新输入");
                            break;
                    }
                }else if (op == 2){
                    if (i == feedbackList.size()-1){//最后一条
                        System.out.println("【温馨提示:】用户反馈查看完毕");
                    }
                    next = false;
                }else {
                    System.out.println("【友情提示】:输入有误,请重新输入");
                }
            }


        }
    }

    /**
     * 修改级别
     */
    public void aa(){

        AdministratorsDao administratorsDao = new AdministratorsDaoImpl();

        Administrators administrators1 = new Administrators();
        List<Administrators> administratorsList = administratorsDao.queruAll();
        int sum = 0;
        for (int i = 0; i < administratorsList.size(); i++) {
            /*if (administratorsList.get(i).getLevels() == SystemConstant.FIRST_LEVEL_ADMINISTRATOR){
                continue;
            }*/
            //System.out.println(administratorsList.get(i));
            System.out.println((++sum)+"."+administratorsList.get(i).getName()+" 等级:"+administratorsList.get(i).getLevels());
        }

        System.out.print("请选择需要修改的人:");
        int  name= input.nextInt();
        System.out.print("请选择需要的等级:");
        int  levels= input.nextInt();
        sum = 0;
        for (int i = 0; i < administratorsList.size(); i++) {
            sum++;
            if (sum == name){//确定修改的人的名字
                administrators1.setName(administratorsList.get(i).getName());
                administrators1.setLevels(levels);
            }
        }
        administratorsDao.update(administrators1);
        System.out.println("【温馨提示】修改成功!");

    }


    /**
     * 添加管理员
     */
    public void bb(){
        AdministratorsDao administratorsDao = new AdministratorsDaoImpl();
        System.out.println("请输入名字:");
        String name = input.next();
        System.out.println("请输入账号:");
        String accountNumber = input.next();
        System.out.println("请输入密码:");
        String password = input.next();
        System.out.println("请输入等级:");
        int level = input.nextInt();

        Administrators administrators = new Administrators();
        administrators.setName(name);
        administrators.setAccountNumber(accountNumber);
        administrators.setPassword(password);
        administrators.setLevels(level);

        int insert = administratorsDao.insert(administrators);
        System.out.println("【温馨提示】添加成功!");
    }

    /**
     * 删除管理员
     */
    public void cc(){
        AdministratorsDao administratorsDao = new AdministratorsDaoImpl();
        List<Administrators> administrators = administratorsDao.queruAll();
        int sum = 1;
        for (int i = 0; i < administrators.size(); i++) {
            if (administrators.get(i).getLevels().equals(SystemConstant.FIRST_LEVEL_ADMINISTRATOR)){
                continue;
            }

            System.out.println((sum++)+"."+administrators.get(i).getName());
        }
        System.out.print("请选择需要删除的人:");
        int i = input.nextInt();
        //int update = administratorsDao.deleteById(sum);

        System.out.println("【温馨提示】删除成功!");

    }



}
3、菜单类(ui包)
package com.lx.soso.ui;

import com.lx.soso.constant.SystemConstant;
import com.lx.soso.entity.Administrators;
import com.lx.soso.entity.MoboleCard;
import com.lx.soso.service.SoSoService;

import java.util.Scanner;


public class SosoApp {
    Scanner input = new Scanner(System.in);
    //号码
    public static String number = null;
    //管理员账号
    public static String accountName = null;
    //
    public static String name = null;
    //管理员等级
    Integer levels = 2;

    private SoSoService soSoService = new SoSoService();

    public static void main(String[] args) {

        new SosoApp().showFirstMenu();
    }

    /**
     * 显示一级菜单
     */
    public void showFirstMenu(){
        System.out.println("****************************欢迎使用嗖嗖移动业务大厅****************************");
        System.out.println("1.用户登录\t2.用户注册\t3.使用嗖嗖\t4.话费充值\t5.资费说明\t6.反馈\t7.退出系统\t8.管理员登陆");
        System.out.print("请选择(1~8)功能:");
        String  choose = input.next();

        switch (choose){
            case "1":
                MoboleCard moboleCard = soSoService.login();
                if (moboleCard == null){
                    showFirstMenu();
                }
                number = moboleCard.getCardNumber();
                showSecondMenu();

                break;
            case "2":
                soSoService.register();//用户注册
                showFirstMenu();
                break;
            case "3":
                soSoService.useSoso();//使用嗖嗖
                showFirstMenu();
                break;
            case "4":
                soSoService.Recharge();//话费充值
                showFirstMenu();
                break;
            case "5":
                soSoService.printSerpackage();//资费说明
                showFirstMenu();
                break;
            case "6":
                soSoService.feedback();//反馈
                showFirstMenu();
                break;
            case "7":
                System.out.println("欢迎使用本系统~~~");
                System.out.println("系统正在退出....");
                System.exit(0);
                break;
            case "8":
                Administrators administrators = soSoService.ALogin();//管理员登陆
                if (administrators == null){
                    showFirstMenu();
                }
                accountName = administrators.getAccountNumber();
                levels = administrators.getLevels();
                name = administrators.getName();
                administratorsMenu();
                break;
            default:
                System.out.println("【友情提示】:输入有误,请重新输入");
                showFirstMenu();
                break;
        }
    }


    /**
     * 显示二级菜单
     */
    public void showSecondMenu(){
        System.out.println("****************************嗖嗖移动用户菜单****************************");
        System.out.println("1.本月账单查询\t2.套餐余量查询\t3.打印消费详单\t4.套餐变更\t5.反馈\t6.办理退网\t7.返回上一级");
        System.out.print("请选择(1~6)功能:");
        String  choose = input.next();
        switch (choose){
            case "1":
                soSoService.queryMonthBill();//本月账单查询
                showSecondMenu();
                break;
            case "2":
                soSoService.queryPackageBalance();//套餐余量查询
                showSecondMenu();
                break;
            case "3":
                soSoService.printConsumptionDetails();//打印消费详单
                showSecondMenu();
                break;
            case "4":
                soSoService.packageChanges();//套餐变更
                showSecondMenu();
                break;
            case "5":
                soSoService.feedback();
                showSecondMenu();
                // 反馈 反馈表:反馈号码、反馈内容、回复
                break;
            case "6":
                soSoService.logout();// 办理退网
                showFirstMenu();
                break;
            case "7":
                //返回上级菜单
                showFirstMenu();
                System.out.println("【友情提示】:返回上一级菜单成功");
                break;
            default:
                System.out.println("【友情提示】:输入有误,请重新输入");
                showSecondMenu();
                break;
        }
    }


    /**
     * 一级管理员菜单
     */
    public void administratorsMenu(){
        String levelStr = null;
        String op = null;
        int ops = 2;
        if (levels == SystemConstant.FIRST_LEVEL_ADMINISTRATOR){
            levelStr = "一级";
            op = "\n3.操作管理员";
            ops+=1;
        }else {
            levelStr = "二级";
        }
        System.out.println("****************************"+levelStr+"管理员:"+name+"****************************");
        System.out.println("1.查看反馈\n2.返回上一级"+op);
        System.out.print("请选择(1~"+ops+")功能:");
        String  choose = input.next();
        switch (choose){
            case "1":
                soSoService.viewFeedback();
                administratorsMenu();
                break;

            case "2":
                //返回上级菜单
                showFirstMenu();
                System.out.println("【友情提示】:返回上一级菜单成功");
                break;
            case "3":

                if (levels == SystemConstant.FIRST_LEVEL_ADMINISTRATOR){
                    fist();
                }else {
                    System.out.println("【友情提示】:输入有误,请重新输入");
                    administratorsMenu();
                }
                break;
            default:
                System.out.println("【友情提示】:输入有误,请重新输入");
                administratorsMenu();
                break;
        }
    }

    public void fist(){
        System.out.println("*******************************************************");
        System.out.println("1.修改级别\t2.添加管理员\t3.删除管理员\t4.返回上一级");
        System.out.print("选择操作:");
        int op3 = input.nextInt();
        switch (op3){
            case 1:
                soSoService.aa();
                //todo 操作管理员
                fist();
                break;
            case 2:
                soSoService.bb();
                fist();
                //todo 操作管理员
                break;
            case 3:
                soSoService.cc();
                fist();
                //todo 操作管理员
                break;
            case 4:
                //返回上级菜单
                System.out.println("【友情提示】:返回上一级菜单成功");
                administratorsMenu();

                break;
            default:
                System.out.println("【友情提示】:输入有误,请重新输入");
                fist();
                break;
        }
    }
}
4、工具类(util包)
        4.1JDBC连接数据库
package com.lx.soso.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;


public class DateUtil {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static SimpleDateFormat yearSdf = new SimpleDateFormat("yyyy-MM-dd");
    //Date date = new Date(System.currentTimeMillis());//获取当前时间戳

    /**
     * 将时间转化为规定的格式(yyyy-MM-dd HH:mm:ss格式字符串)
     * @param date
     * @return
     */
    public static String  formatDate(Date date){
        return sdf.format(date);

    }

    public static String  yearFormatDate(Date date){
        return yearSdf.format(date);

    }
    //根据时间获取这个时间的当月1号日期
    public static Date getMonthFirst(Date date){
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.DATE,1);
        Date time = ca.getTime();
        return time;

    }

    public static int getMonth(Date date){
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        int i = ca.get(Calendar.MONTH);
        return i+1;
    }





}
        4.2时间格式化
package com.lx.soso.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * @author lx
 * @version 1.0
 * @title JDBCUtil
 * @description
 * @create 2024/1/8 9:48
 */

public class JDBCUtil {
    static Properties props = new Properties();
    static{
        // 包裹选中的代码, ctrl + alt + T
        try {
            InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");
            props.load(in);
            Class.forName(props.getProperty("jdbc.driver"));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return
     */
    public static Connection getConnection() throws SQLException {
        return  DriverManager.getConnection(props.getProperty("jdbc.url"),props.getProperty("jdbc.username"),props.getProperty("jdbc.password"));
    }


    public static void close(Connection conn, Statement statement, ResultSet resultSet){
        //6.关闭资源 倒序关  先开的后关, 后开的先关
        try {
            if(resultSet!=null){
                resultSet.close();
            }
            if(statement!=null){
                statement.close();
            }
            if(conn!=null){
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

四、部分功能展示

登陆

注册

使用soso

 

话费充值   资费说明

 

本月账单查询 套餐余量查询

 

打印消费详单

 

用户反馈

 

查看回复

 

管理员回复

 

五、分析总结

1、Java基础

项目中用到了java中的属性,方法,集合,接口,随机数,if语句,switch语句,while循环等,涉及到的知识面相当广泛巩固了之前的Java基础。

2、数据库

其中涉及到了数据库的知识,包括基础的增删查改sql语句的编写。还有JDBC操作数据库。这其实是这个项目的重点

3、项目结构

Java Dao模式的运用(将数据库操作封装):一个实体类对应一个Dao接口和Dao实现类

共同属性、方法进行封装:实体类的idDao接口的增删改查方法

工具类的编写:JDBCUtilDateUtil

4、IDEA Debug使用

由于项目代码量比较多功能模块较多,在程序编码中容易出bug,尤其NullPointerException

出现颇多,这时Debug可以帮我们节省大量时间,当然在日常编写也应该注意防止bug的出现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/325466.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[HNCTF 2022 Week1]What is Web

flag 在源码里 <! 是 HTML 文档的注释格式&#xff0c;在源码里按 Ctrl F 搜索 <! 能帮你更快地找到提示。 将这个字符串 base64 解码得到 flag &#xff1a;

React Native 环境安装

Notion – The all-in-one workspace for your notes, tasks, wikis, and databases. 搭建开发环境 React Native 中文网 Homebrew&#xff08;包管理器&#xff09; → rvm&#xff08;ruby版本管理&#xff09; → ruby → cocoapods 安装 Homebrew Homebrew /bin/ba…

shell 循环 判断

for 循环 Shell 脚本里最简单的循环当属 for 循环。最简单的 for 循环如下所示&#xff0c;你只需将变量值依次写在 in 后面即可&#xff1a; #!/bin/bashfor num in 1 2 3 4 doecho $num done 如果要循环的内容是字母表里的连续字母或连续数字&#xff0c;那么就可以按以下语…

Matlab 使用 DH table 建立的 robot 和实际不符

机器人仿真 想借助 matlab robotics toolbox 来仿真机器人&#xff0c;但是直接输入自己的 DH table 显示出来的 robot 和实际不情况不符。 DH table 建立 robot Build Manipulator Robot Using Kinematic DH Parameters 主要使用 setFixedTransform&#xff0c;DH table 中…

智云谷再获资本市场青睐,完成数千万元A+轮融资

近日&#xff0c;深圳前海智云谷科技有限公司&#xff08;以下简称“智云谷”&#xff09;完成数千万元A轮融资&#xff0c;本轮融资由青松基金独家投资&#xff0c;多维资本担任独家融资财务顾问。本轮融资资金将用于扩大新技术研发投入、智能工厂扩产、加速产品交付&#xff…

K8S----YAML

kubernetes中资源可以使用YAML描述&#xff08;如果您对YAML格式不了解&#xff0c;可以参考YAML语法&#xff09;&#xff0c;也可以使用JSON。其内容可以分为如下四个部分&#xff1a; typeMeta&#xff1a;对象类型的元信息&#xff0c;声明对象使用哪个API版本&#xff0c…

Vue-20、Vue监测数组改变

1、数组调用以下方法Vue可以监测到。 arr.push(); 向数组的末尾追加元素 const array [1,2,3] const result array.push(4) // array [1,2,3,4] // result 4arr.pop(); 删除末尾的元素 const array [a, b] array.pop() // b array.pop() // a array.pop() // undefi…

【Shell编程练习】编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机状态

系列文章目录 输出Hello World 通过位置变量创建 Linux 系统账户及密码 监控内存和磁盘容量&#xff0c;小于给定值时报警 猜大小 输入三个数并进行升序排序 系列文章目录编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机状态 编写脚本测试 192.…

opencv_角点检测

文章内容 一个opencv检测角点的程序 运行效果 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream>using namespace cv; using namespace std;void detectCorners(M…

AI数字人短视频变现项目:打造短视频运营变现新模式

如今&#xff0c;随着科技的快速发展和人们对数字内容的增长需求&#xff0c;短视频成为了互联网用户最喜爱的娱乐方式之一。然而&#xff0c;在这个竞争激烈的市场中&#xff0c;如何为短视频创作者提供更多的变现机会成为了一个重要的问题。AI数字人短视频变现项目的出现&…

【RT-DETR改进涨点】MPDIoU、InnerMPDIoU损失函数中的No.1(包含二次创新)

前言 大家好&#xff0c;我是Snu77&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持Re…

深入解析多目标优化技术:理论、实践与优化

本文深入探讨了多目标优化技术及其在机器学习和深度学习中的应用&#xff0c;特别聚焦于遗传算法的原理和实践应用。我们从多目标优化的基础概念、常见算法、以及面临的挑战入手&#xff0c;进而详细介绍遗传算法的工作原理、Python代码实现&#xff0c;以及如何应用于实际的机…

【React源码 - Diff算法】

介绍 在React学习中&#xff0c;Diff算法(协调算法)&#xff0c;想必我们并不陌生&#xff0c;简单来说就是一个对比新老节点寻找差异&#xff0c;然后找出最小的一个变化集&#xff0c;最后对这个最小变化集进行最小的DOM操作&#xff0c;本文将从源码来分析在React(17.0.2)中…

四、任意文件读取漏洞

一、介绍 解释&#xff1a;任意文件读取漏洞就其本身来说就是&#xff0c;攻击者绕过网站防御者设置的防御&#xff0c;读取到了正常使用者不应该读取到的内容。网站开发者使用不同的语言&#xff0c;任意文件读取漏洞利用方式就不同。 二、不同开发语言的不同漏洞点 1.PHP …

韶音、南卡、Oladance开放式耳机值得买吗?超强机型对比环节!

​虽然很多耳机音频爱好者最近都爱上了使用开放式耳机&#xff0c;但是作为一个7年音频数码测评的老司机&#xff0c;我还是要提醒一下&#xff0c;目前有很多的开放式耳机过分强调外观颜值设计&#xff0c;在音质体验和佩戴舒适性上的效果极差&#xff0c;还会有很多漏音、破音…

cesium设置近地天空盒 多种效果(附天空盒原图)

效果&#xff08;天空盒原图已放云盘在文章最后&#xff09;&#xff1a; 为了效果逼真设置了当达到一定高度时就恢复系统默认星空天空盒所&#xff0c;以设置了两个变量 一个是近地的天空盒子一个是当超过一定高度时用系统默认的 let currSkyBox; // 当前生效的Skybox let de…

OpenCV——图像按位运算

目录 一、算法概述1、逻辑运算2、函数解析3、用途 二、代码实现三、结果展示 OpenCV——图像按位运算由CSDN点云侠原创&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、算法概述 1、逻辑运算 OpenCV4 针对两个图像之…

Android studio 简单登录APP设计

一、登录界面: 二、xml布局设计: <LinearLayoutandroid:id="@+id/linearLayout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:layout_editor_absoluteX="…

二、基础篇 vue计算属性和侦听器

计算属性 模板内的表达式非常便利&#xff0c;但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如&#xff1a; <div id"example">{{ message.split().reverse().join() }} </div> 在这个地方&#xff0c;模板不…

Scratch图形化编程如何快速从入门到精通

Scratch是一款由麻省理工学院媒体实验室开发的图形化编程工具&#xff0c;它以拖拽式的编程方式&#xff0c;让编程变得简单易懂&#xff0c;适合所有年龄段的人学习。无论是初学者还是有一定编程基础的人&#xff0c;都可以通过Scratch快速上手并深入学习。下面&#xff0c;65…