最近项目总结以及关于java的吐槽
唠叨
最近真的是忙的非常的不行,忙的几乎没有时间学习和写博客。这确实是自己时间安排上的巨大失误,我也是时候该停下来手中的工作了。再不复习期末考试就凉了。
这几个月项目以来,深刻的体会到疯狂码代码并不怎么能提升自己能力,我发现我自从4月份以来知识量就开始停滞了,于是我每天都在学习不深入,代码不深入的恐慌里面。
其实说实话,做项目其实是一件重复性很高的事情,尤其是普通的小型的网页系统和桌面业务系统。尽管我用了很多也重新学了很多重构,优化,去耦合,写组件之类的方法,依旧摆脱不了它本质上就是一件重复而无用的事情,而我在这几个月以来毫无长进。我现在是真的这么觉得,劝比我小一点点的小朋友,不要看见是代码就喜欢,看见项目就想搞。书能好好读,语言能好好学,不要瞎接项目就搞。
当然,我并不是否定写项目就是一件没用的事。不论是工作室还是学院都有很多真正有用的创新项目可以选择,能够帮助你成长为大牛。同时,也不一定要会编写代码,我现在知道了策划和产品方案是一件多牛逼的事情。同时自己接软件委托开发也是一件很好的锻炼自己的一件事情,但是一定要安排好时间,安排好自己的学习时间,学习课程,学习工程,学习"码代码"。
这几个月以来还是有一些有意思的事情可以说一下的,但是时间不多,我就借着最近的项目说一下我的一些理解。
正文
一
我家的强某月,然后他家格力部门(估计不大,大部门不会找我这种渣渣),委托我开发的一个单据管理软件。这个软件说实话,是个学过软件都能写。只是恰好这个东西对于我来说真的是异常的坑。
首先,我不会C#,入坑以来我就是学的web开发,于是 .NET、winForm与我无缘(十分难受)。其次我也几乎不会C++,知识量仅仅够用C做几个课程实验,图形开发看都没看过。主流的两个windows桌面开发语言与我无缘了。
(淘宝旺旺和QQ分别用C#和C++编写)
于是我尝试沟通做成自己擅长的B/S模式。经过一番沟通发现更凉了,不仅不要B/S,连C/S都不能需要。"所有客户端直接连接数据库,同时还要带有权限控制"。我一惊,我自己根本没有接触过这样的骚操作。其实自己想想,对于公司内网,整个小软件就没有几个人用,甲方提出的需求其实非常合理。认真思考一下,直接连接数据库?这其实才是最原始的C/S模式,我们平时所理解的是C/S/S(Client、maybe Service?、Server)模式,中间有应用服务。为什么原始的C/S模式听起来不可思议,其实是C/S/S出现后解决了安全性、可控性,还有很多的问题,并且开发速度甚至比直接连接数据库快。对于小项目来说区别不大,但是甲方认为少步骤总是好的,对于这个小软件我也认同。甲方毕竟是爸爸,给钱还是要听他的。

我把下手点定在了java。Java里面,javaFx讲真我非常喜欢,虽然我没有学过,但是IntelliJ IDE 全家桶我用了那么久了,不得不说实在很令人享受。结果一看客户电脑,Windows XP,原生不支持,还需要靠点歪门邪道才能运行起来。
卢某人,先吐一口血。

那么,我还是乖乖的用swing吧。swing被人吐槽了那么旧,但不得不说它其实也是个好东西(废话,它是我最后的出路!)。
从别人那里偷个图,如果丑到你了,我代这个图片作者向你说对不起hhhhhhh。

java的生态环境太庞大了,办法总是有的,于是我想到了使用亲爱的Spring 结合Swing做一个客户端。
直觉上,Spring基本用户Web开发。但是事实上,我们要理解清楚,这个框架并不局限于Web,它提供的最核心的两个功能IoC、AOP。知乎 Spring 的理解 (opens new window)
也就是,我可以通过使用Spring来管理我的Bean,管理对象的生命周期,还可以使用AOP进行面向切面编程(代理,拦截器……)同时,Spring还是一个庞大的家族,提供更多的额外的东西,比如声明式事务管理,对象的创建和依赖关系由Spring自动管理……
我选择它的原因是,我想不到有别的东西比它更方便了。
二
于是初步确定了如何实现这个项目。我使用了 Spring Boot + MyBatis + Swing ,这其实和Web上 Spring + Mybatis + SpringMVC的思维一模一样,区别只是VIEW层的构成。
Spring Boot 其实就是Spring 的一个整合包,有Spring基础当然是使用Spring Boot Initializer 下一步下一步下一步的构建啦。
跟以往一样,项目从底往上写。但是数据库有现成的了,我问数据表结构,结果甲方直接把整个数据库备份发了给我,足足100MB的数据啊,一百多万条数据啊!!!商业机密啊!这都敢网络发给我喵喵喵?
并且,当我导入要看表结构的时候。

这个数据库,
没有主键?
没有索引?
单据有重复??
条码有重复??
每次一查询都是全表扫描???
数据量居然是百万级???
插入可以随便插???
设计这个数据表的人真的是人才。

这也是我第一次体验百万级表的恐怖之处,select * 直接卡死,搜10000条没有个大半分钟都不出结果。
三
其实数据结构特别简单,使用mybatis ganerator 生成改都不用改, 也没有任何的关联,这恐怕是我接触最简单的一个数据表了。
生成之后就是Mapper.xml、Mapper接口、表对应POJO和PojoExample了。 当然还需要一点点修改就是分页。 Sql Server 的分页查询和mybatis不一样, 需要用Top 选择前那条数据, 还需要嵌套一次Select 跳过前几条数据。 其他方法基本都要子查询,并且都复杂。MySql在分页上还是方便的呀。。
写好了Mapper之后,Service层也简单,太简单了直接想直接写。。然后让注册成Component就可以给Swing使用了。
四
Swing这一层是让我耗费最多时间的,甚至绝大多数时间都是在写Swing组件,让我不得不怀疑自己。。因为碰到的问题是在是太多了。
首先,是IntelliJ Idea Swing Gui Designer 的问题。 Gui Designer 和Maven 不兼容。 Gui 生成的form文件不能被maven编译, 必须要用IntelliJ自带的Java2编译。Stack Overflow搜索得到了几个编译插件,可以帮助两者整合。 但是使用上发现,只要我已使用JDK1.8 的lambda表达式, 编译直接报错ArrayIndexOutOfBoundsException。 继续面向Stack Overflow编程, 得知莫法了,调来调去还是报错,我自己也不理解Gui Designer 还有这几个编译工具的本质。只好把所有使用了JAVA 8 新语言特性的代码全部重构, 刚学来的重构优化知识全部用不上了。
其次,是Swing的问题,Swing和AWT混用的话并不会出什么错,但就是会各种层遮混乱,因为AWT是重量级控件,Swing是轻量级控件,细节我也不想了解。但是只要注意尽量不要混用就行了,虽然偶尔也出现类似JInternalFrame被遮住的问题,通产都是换一个组件就搞定了,比如使用JDialog。
最后,就是阻塞问题, 刚开始发现无论怎么弄,只要调用了数据库读写,界面就会阻塞卡死。后来才发现,我可以使用SwingWorker 来进行业务层操作,我们来理解一下Swing线程。
- 初始化线程:就是main函数,用来启动GUI
- 用户事件调度线程EDT:负责对GUI组件的渲染和刷新,它只有一个,一定要注意这个问题,它处理的就是事件队列里的事情,他通过调用事件处理器来响应用户交互。所有的事件处理都是在EDT上进行的。
- 任务线程:响应时具体的数据处理。
同时有几个注意点
- 其他线程上访问UI组件和事件处理器都是不安全的,都有可能导致界面的更新和绘制错误。
- 应使用独立的任务线程来执行耗时计算或输入输出密集型任务,想数据库通信,访问网站资源,读写大量数据的文件。
- 从非EDT线程访问UI主键及其事件监听器会废纸界面更新和绘制错误。
- 从EDT上执行耗时任务线程会使程序失去响应,这会使GUI事件阻塞在队列中得不到处理。
于是SwingWorker 可以新建线程 ,整个生命周期有三个线程,
- 主线程 Swing线程
- Worker线程 业务线程
- 事件指派线程 与Swing交互

同时还是用了一个动画遮罩类使得页面有Loading效果,优化交互体验
五
运行环境问题。
java Swing 还是要运行在JVM之上, 但是客户的电脑几乎不可能会有jre运行环境,一开始自己打包精简弄了很多岔子,最后发现有install4J这一神器,可以集成并且精简JRE,然后于程序一起打包。 jar运行包有15MB,封装后的安装程序只有35MB,还是非常的可观的。
同时Windows XP安装JAVA8的比较麻烦,JAVA 8 不直接支持XP。为了兼容性,只好JDK和所有依赖降级成JDK7, 这一降级又要重构好一部分代码。JDK7在Windows XP上表现的非常不错。
六
折腾了约一个星期,程序终于写完了


其实程序很简单,但是swing没有想Web开发一样有前端框架,甚至没有类似jQuery的东西。再加之组件非常的老。 日期选择和分页插件都是自己从零用组件拼出来。
数据约束,事件监听,事件的传递,都非常的原始,像Vue的$emit 这种高级功能要是想实现全部要自己来。
但总之, 还是写完了,能够交差并且甲方说还挺快的。
