前言

这次进行 Java 的大作业,虽然是一拖三,不过还是准备做得漂亮一点.Java 还是很有趣的,并且可能以后工作室项目能用得到.

嗯,如果做得好了,就请自己去搓一顿!

思路

  • 需求分析
  • 架构
  • 界面设计

需求分析

这是一个项目的开始,课程设计(非游戏类)应该是要去解决一个实际的问题,而不是单纯的应付差事.
这一次的项目需求与暑假项目相同,所以就不做赘述.

架构

项目架构是衡量一个项目的质量的重要指标.逻辑清晰的项目结构可以省去开发过程中的很多烦恼,同时,也能够极大地增加协同开发的效率.

我这次使用的是比较传统的 mvc 架构.

  • 最上面的一层,是直接面向最终用户的”视图层”(View)。它是提供给用户的操作界面,是程序的外壳。
  • 最底下的一层,是核心的”数据层”(Model),也就是程序需要操作的数据或信息。
  • 中间的一层,就是”控制层”(Controller),它负责根据用户从”视图层”输入的指令,选取”数据层”中的数据,然后对其进行相应的操作,产生最终结果。

当然也可以将 mvc 混淆,都合并在少数的文件当中,事实上我在完成 C#的课程设计的时候就是这么做的,这样的后果也很明显,我现在已经看不懂我的 C#课设了…

当然,便于阅读维护只是 MVC 模式下思路清晰 的一个小小的伴生好处.
随着项目的膨胀,越来越多的功能涌入,mvc 甚至还需要再次进行划分.这个时候,你是选择凭借自己的记忆去记录各个接口之间的关系,还是寄托于 MVC 架构,简单明了地管理自己的项目呢?

再说一说协作开发的效率.
协作开发这个词估计不会存在于我四年大学生活之中了.不过我还是可以憧憬一下的.
mvc 模式下,各个模块功能明确,责任关系清晰,任务可以以极低的耦合度准确地分配到每个人的头上,如果,我是说如果,一群水平相当的开发者在这种模式下齐头并进,开发效率无疑是十分可怕的.

推而广之,这种模式的变体可以应用到社会的很多合作模式中…emmmm,好吧,这只是一篇讲技术的文章,就这样吧.

现在回头看看暑期的项目,一个人能开发到这个地步,我还是有点小小的得意的.

界面设计

每一个直男的噩梦,唉…暂且先挂起来吧…

数据库二三事

Java 课设中的问题以及解决方案(二)
Java 课设中的问题以及解决方案(一)
中,都有对数据库连接的一些叙述.不过都是一些比较粗浅的尝试.

在进行登录&注册模块的开发时,我对数据库进行了比较深入的了解和操作.

prepareStatement 和 createStatement

prepareStatement 会先初始化 SQL,先把这个 SQL 提交到数据库中进行预处理,多次使用可提高效率.

createStatement 不会初始化,没有预处理,每次都是从 0 开始执行 SQL.
两者这代码上有显著的区别.

e.g.

// prepareStatement
ResultSet rs = null;
String sql = "select * from users where  username=? and userpwd=?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1,username);
pstmt.setString(2, userpwd);
//prepareStatement.setString() 给sql中的"?"赋值,这里将第一个?设置为username,第二个?设置为userpwd

// createStatement
ResultSet rs = null;
String sql = "select * from users where  username= '"+username+"' and userpwd='"+userpwd+"'";
createStatement ps = con.prepareStatement(sql);
rs = stmt.executeQuery(sql);
// createStatement没有?形式的格式化,直接使用

格式化的方法让我们在编写代码时思路更加清楚,代码的形式也更加的优雅.(试想一下,上述如果不是 2 个参数,而是十多个参数,那么 create 方法将会有多少个+和”)

同时,预编译的方法还可以有效地抵御 sql 注入攻击.

e.g.

String sql = "select * from user where username= 'zxj' and userpwd='"+varpasswd+"'";

如果用户在密码栏中输入 'or '1' = 1';drop table book; 那么就构成了这样一条查询语句

select * from user where username= 'zxj' and userpwd='or '1' = 1';
drop table usr;

这样的查询语句毫无疑问是成立并且是可以通过执行的.
所以,用户可以通过这种方法,在不获取数据库账号密码的情况下,删除你的 usr 表!~

而如果你使用prepareStatement,用 setString 的方法传递参数,再进行一次预编译,就可以有效地避免这种困扰.

所以说,无论从代码的可读性和可维护性,还是从提高性能方面,或者说避免攻击方面,都应该使用 prepareStatement.

hash 加密

密码的明文传递一直是为业界所诟病的事情.
在进行暑假项目工作的时候,涛哥教我使用 hash 加密一次密码.

牢骚话:本来嘛,课设没必要做到这个地步,不过今天正好涛哥出国,这之后一年才能回来,所以传承一下他严谨的工作态度,算是一个纪念吧

public static String getSHA(String input) {
    MessageDigest md = MessageDigest.getInstance("SHA-256");

    byte[] messageDigest = md.digest(input.getBytes());

    BigInteger no = new BigInteger(1, messageDigest);

    String hashtext = no.toString(16);

    while (hashtext.length() < 32) {
        hashtext = "0" + hashtext;
    }

    return hashtext;
}

datetime 处理

数据库的 datetime 数据是 xxxx-xx-xx xx : xx : xx 形式的,所以就用了一个比较土的办法…

Date date=new Date();
String date = String.format("%tF%n", date)+" "+String.format("%tT%n",date)

另外,关于 string 的格式化,推荐一篇博客

后记

  • 等待,并心怀希望.