一、核心技术

1、JDBC编程
2、MySQL
3、注解技术
4、反射
5、集合框架
6、Stream式编程

二、项目特色

1、数据库操作
1.1 在进行数据库设计时,同一个用户下单时生成的订单以及该订单内含有的下单时所选的多个商品(订单项),将这两种情景映射成订单表和订单项表,这两个表是一对多的关系,在JDBC操作中,订单项表大致定位就是购物车,订单就是最终的订单
1.2 用户表与订单表也是一对多的关系,这样就可以多次购物,并且可以随时查看自己以前的订单,
2、集合框架和注解以及反射
利用注解将所有命令分类,再利用反射拿到注解,将自己想要展示的不同命令以及拿到的用来分类的注解通过key-value的方式存进map中,在展示在不同的情景下
3、其他
本项目属于一个业务性的项目,功能实现比较多,分层现实时自己的脑子里必须有一个清醒的逻辑,假设你对面向对象思想还不是很熟练,那么将这个项目整体独立的做下来,无论是对面向对象的思维还是对整个数据库的解析来说应该都会有很大的提升

三、项目核心需求

1、公共端
  1. 入口命令
    1.1 登录(DL)
    1.2 注册(ZC)
  2. 公共命令
    2.1 帮助信息(BZ)
    2.2 关于系统(GY)
    2.3 退出系统(TC)
2、管理端
  1. 帐号信息
    1.1 启停帐号(QTZH)
    1.2 重置密码(CZMM)
    1.3 查看帐号(CKZH)
  2. 商品信息
    2.1 上架商品(SJSP)
    2.2 下架商品(XJSP)
    2.3 浏览商品(LLSP)
    2.4 更新商品(GXSP)
  3. 公共命令
    3.1 帮助信息(BZ)
    3.2 关于系统(GY)
    3.3 退出系统(TC)
  4. 我的信息
    4.1 修改密码(XGMM)
    4.2 个人信息(GRXX)
3、客户端
  1. 商品信息
    1.1 浏览商品(LLSP)
  2. 公共命令
    2.1 帮助信息(BZ)
    2.2 退出系统(TC)
    2.3 关于系统(GY)
  3. 我的订单
    3.1 取消订单(QXDD)
    3.2 支付订单(ZFDD)
    3.3 查看订单(CKDD)
  4. 我的信息
    4.1 修改密码(XGMM) 4.2 个人信息(GRXX)

四、项目技术实现

1、数据库设计

java 收银机源码 收银系统 github_解决方案

java 收银机源码 收银系统 github_解决方案_02

2、分层设计,代码分为四层,分别进行具体的业务实现
将代码分层,这样项目的代码清晰明明了,无论是改错还是进行内部的维护都会很方便,这种良好的编程习惯是非常重要的

java 收银机源码 收银系统 github_缓存_03

3、具体功能实现
1、入口端功能

1、注册:输入用户名、二次验证密码,然后存进数据库
2、登录:验证输入的用户名、密码是否正确

2、管理端

关于账户
1.启停账号:将数据库内账户表中对应账户的状态改为启停
2.重置密码:进数据库将对应账户的密码重置
3.查看账户:将对应的账户所有信息打印出来

关于商品
1.上架商品,向数据库中的商品表内新增商品数据
2.下架商品,原理同上,将想新增的数据放进数据库内
3 .浏览商品
4.更新商品

3、客户端

1、浏览订单:客户与订单是一对多的关系,根据账号id找到所有与此账号相关的订单,并打印出来
2、支付订单:这一块是处理订单与订单项之间的关系,首先先将选好的商品挨个存进订单项内,然后通过同一个订单号找到相对应的所有订单项,打印出来询问客户是否选择支付,不支付则回滚到下单之前,这里用到了事务

节选一部分关于命令分类的代码粘贴下来,如果想看完整项目可以点进我下面附的链接

public class Commands {
    public static Map<String,Command> ADMIN_COMMANDS=new HashMap<>();
    public static Map<String,Command> CUSTOMER_COMMANDS=new HashMap<>();
    public static Map<String,Command> ENTRANCE_COMMANDS=new HashMap<>();
    //存放所有的命令的集合
    private static final Set<Command> COMMANDS=new HashSet<>();
    private static final Command CACHED_HELP_COMMANDS;
    static {  //静态代码库
        Collections.addAll(COMMANDS,
                new AccountBrowseCommand(),
                new AccountPasswordResetCommand(),
                new AccountStatusSetCommand(),
                new AboutCommand(),
                CACHED_HELP_COMMANDS= new HelpCommand(),//将HelpCommand进行缓存
                new QuitCommand(),
                new LoginCommand(),
                new RegisterCommand(),
                new GoodsBrowseCommand(),
                new GoodsPutAwayCommand(),
                new GoodsSoldOutCommand(),
                new GoodsUpdateCommand(),
                new OrderBrowseCommand(),
                new OrderPayCommand());
        for(Command command:COMMANDS){
            //利用反射,将命令进行分类到不同的map
            Class<?> cls=command.getClass();
            AdminCommand adminCommand=cls.getDeclaredAnnotation(AdminCommand.class);
            CustormerCommand customerCommand=cls.getDeclaredAnnotation(CustormerCommand.class);
            EntranceCommand entranceCommand=cls.getDeclaredAnnotation(EntranceCommand.class);
            CommandMeta commandMeta=cls.getDeclaredAnnotation(CommandMeta.class);
            if(commandMeta==null){
                continue;
            }
            String commandKey=commandMeta.name();
            if(adminCommand!=null){
                ADMIN_COMMANDS.put(commandKey,command);
            }
            if(customerCommand!=null){
                CUSTOMER_COMMANDS.put(commandKey,command);
            }
            if(entranceCommand!=null){
                ENTRANCE_COMMANDS.put(commandKey,command);
            }
        }
    }

    //得到缓存的命令
    public static Command getCachedHelpCommands() {
        return CACHED_HELP_COMMANDS;
    }
    public static Command getAdminCommand(String commandKey){
        return getCommand(commandKey,ADMIN_COMMANDS);
    }
    public static Command getCustomerCommand(String commandKey){
        return getCommand(commandKey,CUSTOMER_COMMANDS);
    }
    public static Command getEntranceCommand(String commandKey){
        return getCommand(commandKey,ENTRANCE_COMMANDS);
    }
    public static Command getCommand(String commandKey,Map<String,Command>commandMap){
        //遍历相应的map,根据commandKey,得到相应的value值
        return commandMap.getOrDefault(commandKey,CACHED_HELP_COMMANDS);
        //找不到返回帮助(缓存好的命令)

    }
}

剩下的其他功能其实都是数据库的操作,以及逻辑思维的建立,就略过

6 、最终项目效果

java 收银机源码 收银系统 github_数据库_04

java 收银机源码 收银系统 github_解决方案_05

java 收银机源码 收银系统 github_java 收银机源码_06

java 收银机源码 收银系统 github_解决方案_07

java 收银机源码 收银系统 github_java 收银机源码_08

java 收银机源码 收银系统 github_java 收银机源码_09

java 收银机源码 收银系统 github_java 收银机源码_10

五、项目还可以优化吗

这个项目当然可以优化
问题一、

从代码方面来说,在做这个项目的时候全程用的都是JavaSE的基础知识,涉及到高阶的地方写的代码相对较少,所以里面很多基础代码都是重复的,而且类与类之间的依赖性太强,维护起来很难。

解决方案

引入Spring框架技术以及MyBatis,最大程度将类与类解耦,这样后期就算要修改需求或者是出现异常也很好维护

问题二、

从功能方面来说,虽然订单与订单项的处理能够一定程度的解决多次购物和一次购物时选购多个商品问题,但其实内部也会存在很多问题,就拿我自己写得来说,存在的最大的缺陷就是,举一个场景吧
一个客户 下了订单以后,并没有选择之后,而是选择离开,在他下一次登录在进行支付的时候,此商品最后库存已经被另一个客户下单并支付,但此客户的订单上依然会表示原本的货物还存在并且可以下单

解决方案

这个问题解决方案就我目前想到的就是库存已空时,查找所有用户未支付的订单内是否含有此商品,假设有,将此商品移除并做出相应的提示,然后再数据库的商品表中将库存已空的商品移除,以保证不会再有用户可以下单,一直到下一次库存补上,再上架

问题三、

此程序最终展现给我们的是一个字符界面,实际上看起来比较低端,所以如果结合网页来做这个项目,最终展现出来的是很完美的购物系统外加收银系统,那这个项目会更完美一些

解决方案

引入Servlet、JSP以及一系列网络编程的技术,可以很好的解决这个问题,而且就目前的项目而言,前台实现不会太难

项目源代码:

https://github.com/Fancccy/CasherSystem/commit/7260026143e94369ffa0e08ae037e5a9f99b8ce4