JAVA实验课大作业笔记

Java实验大作业是做一个GUI,我分配到的是高铁售票系统

简单交互

初期的时候以为只要做一个在控制台(Console)里交互显示的就可以了,做完找老师验收才知道要做GUI。

看了老师给的作品,看懂之后,照着它依葫芦画瓢,抄抄改改写写做完了交互的。

写之前,根据自己分配到的题目,列了个提纲规划一下自己要实现的功能以及要创建的数据表有哪些,如下:(字丑见谅Orz)

image-20210529221703751

大概过程就是创建三个对象分别为Paid(已购信息)、Passenger(乘客信息)、Railway(高铁信息),每个对象里面都是简单的定义成员变量以及给每个成员变量写好设定方法(set)和获取方法(get),然后写数据库查询(sql)的类,然后写对应不同功能的视图类(view),最后就是创建一个主程序入口用户交互。项目结构如下:

image-20210529222511025

util包和window包是后面GUI的时候写的

mysql表及结构:

image-20210530001312358

image-20210530001349781

GUI图形化

本来也想看看老师给的成品,然后自己抄抄改改写写就好了,但是好多GUI的东西都看不懂,索性就直接把第九章的自学了,把书上的每一个Example都敲了一遍,学完再回来写GUI就觉得简单多了

插件

看书自学完第九章GUI,看书的时候除了学了GUI组件之外还学到了之前老师没讲到的内部类和Lambda表达式,看的时候有些地方不是很明白,但不影响我coding。然后看书上用的插件是JavaFX,照着书上教程安装结果报错了,网上搜了很久,发现关于这个插件的信息很少而且有的也是年代久远,没有找到解决办法,于是搜了下其他的GUI插件,就找到了WindowBuilder的教程(前两篇参考文章),讲的很详细,安装完之后看了教程基本学会了怎么用。

前期准备

跟之前一样,写之前先用笔写了个草稿,如下,就是规划好了菜单栏。(字太丑了~~)

image-20210529232559640

主要过程

登录界面直接复制的,懒得写了。把老师给的成品看了一下,登录进之后主要就是一个主界面(MainFrame),然后菜单栏里的每个界面对应一个java文件,每个界面无非也就是初始化(initComponents)然后再加上一些响应事件。界面用插件设置好组件并且写完动作事件之后,在最后设置可见,然后在主界面里面的动作事件里new classname()就可以响应了

学到的点

1.每个界面用插件做好之后,在最后加上下面两句代码

1
2
setLocationRelativeTo(getOwner());
setVisible(true);

第一个可加可不加,只是一个相对位置。第二个一定要加,不然点击就不会显示了

2.写的时候遇到了要把String类型转为int类型,网上搜了下可以用Integer.parseInt()函数实现

3.我看老师给的作品里有提示框,查询完之后根据查询返回的int结果来判断是否成功,如下

1
JOptionPane.showMessageDialog(null, "添加成功");

提示并退出

4.关闭窗体用dispose()可以实现,比如在退出按钮的动作里加上这个就可以实现退出了

查询多结果处理

查询所有车次信息这种功能可能会出现多条数据,一开始不知道怎么办,因为他查出来的数据是动态的,有多少条我不知道不能提前做好多少个文本框,另外因为我没法运行老师的作品,不知道它是怎么写的。所以自己想了个办法,就是创建JScrollPane,里面再加一个JPanel,每一个查出的结果都创建为一个JTextField然后加到JPanel里,这样不就可以实现滚动了嘛,多了就可以有滚动条了,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int n=0,c=0;
String inf;
List<Railway> list=RailwayView.allRailwayView();
for(Railway r:list) {
n++;
JTextField textField = new JTextField();
textField.setBounds(0, c, 412, 21);
panel.add(textField);
textField.setColumns(10);
inf="日期:"+r.getDate()+" 时间:"+r.getTime()+" 商务座:"+r.getSy()+" 一等座:"+r.getYy()+" 二等座:"+r.getEy()+" 车号:"+r.getCh();
textField.setText(inf);
c+=20;
}
}
});

菜单栏

image-20210529235015172

image-20210529235023201

image-20210529235029134

image-20210529235034975

image-20210529235042695

具体的功能页面懒得截了

登录功能存在SQL注入漏洞

因为我的登录功能的java是直接复制老师的,我看到它里面用的是statement来查询的,再加上它的查询语句是直接拼接且没有做任何过滤,导致了漏洞的存在。

image-20210530104806423

这里我使用万能密码' or 1=1#就能绕过登录验证了

image-20210530104953371

image-20210530105008468

成功进入并且是管理员身份,因为在user表中第一条数据就是admin用户,用万能密码登录后会返回所有数据,根据登录的逻辑result.next()取到的数据就是第一条admin用户,所以登录的身份是admin

image-20210530105258266

image-20210530105536845

如果不是admin用户的话,菜单栏里的前两个菜单是被禁用的。

修复方法是使用prepareStatement预编译SQL语句,把查询函数用prepareStatement修改了下果然万能密码失效了,网上查了些文章,大概原理就是预编译的sql语句是带着占位符的,并且查询前已经被预编译一次了,之后不会再次编译,只会把接受到动态参数当成一个属性进行解析查询,这样即使接收到' or 1=1这样的参数也只会把他当成属性值来处理而不会作为SQL指令,讲得不是很清楚,可查看(前两篇除外的)参考文章。

image-20210530110456054

image-20210530110841874

但是使用prepareStatement就一定安全了吗,前几天刚好看到Ms08067安全实验室公众号里发的Java注入漏洞精选文章里看到一篇名为 “用java PreparedStatement就不用担心sql注入了吗?“ 的文章,顿时吸引了我的注意力,因为我觉得预编译应该不能再注入了,看完之后又学到了新的思路。

总结

写这个GUI的过程遇到了很多的问题,越做到后面越感觉力不从心,因为我觉得我一开始的草稿没有写好,每个数据库里的表的结构没有协调好,因为一个功能(比如购票、退票等等)会牵扯到很多数据表牵一发而动全身,比如购票之后会在paid表里加一条数据,然后passenger表也要相应的加一条数据,但是这个联动没有做好,导致可能购票成功之后只在paid表里加了数据,passenger表没有加上,所以最后我修改了一些东西,把passenger表里的好多列都删了。

写完之后感觉还有很多优化的点,比如购买了没有的车次要怎么处理,查询没有的车号要怎么处理等等,以及表的结构也有很多问题,基本的功能实现了,但是觉得写的非常烂,还有很大的提升空间。

所以总结下来就是前期准备工作很重要,要提前想好每个表要有哪些字段,才可以完美地实现需要的功能。

代码

链接:https://pan.baidu.com/s/1yOZf_D4k8T91tw1ol_Lo5Q
提取码:xcsy

扩展

这个Java的GUI感觉可以写一些小工具,之前ctf做misc题的时候用到的很多工具(比如Stegsolve等等)可能就是用Java的GUI来写的把,以后有想法的话可以自己做一些小工具,感觉挺好玩的。

参考

https://blog.csdn.net/cnds123/article/details/103237529

https://blog.csdn.net/yerenyuan_pku/article/details/82861589

https://www.zhihu.com/question/43581628

https://www.cnblogs.com/yaochc/p/4957833.html

https://www.php.cn/mysql-tutorials-418692.html

https://blog.csdn.net/weixin_45179130/article/details/90761966

https://juejin.cn/post/6844904036106256397

https://blog.nowcoder.net/n/be73b8f592504ae8b1d00368433061be

https://www.cnblogs.com/iyangyuan/p/4809494.html

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2020-2021 Blog of Tianze

请我喝杯咖啡吧~

支付宝
微信