Java项目-简单通讯录实践总结【2】

189 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情
这个简单通讯录系统是我第一个自主完成的实践小项目,即使开发完成后,所需的功能完善了,还额外添加了一个背景音乐的功能,但缺点非常多,现在来看看都有哪些问题和优点。

1、开发顺序颠倒

我的开发顺序 1、功能需求分析,编写了需求规格说明书; 2、项目框架搭建; 3、设计页面; 4、根据页面的需求设计数据库; 5、事务处理; 正确开发顺序 1、功能需求分析,编写了需求规格说明书; 2、根据功能需求设计数据库; 3、项目框架搭建; 4、事务处理; 5、设计页面;

2、数据库设计

1、不应该根据页面去设计数据库,页面不知道需要完成什么功能,而是要根据需求规格说明书来设计数据库。因为是根据页面设计的数据库,导致没有理清数据之间的关系,在开发完成后,出现不能添加新的分组,用户登录后好友列表是共用的,出现了用户没有添加的好友,这里就是在设计数据库是忽略了用户和用户好友的关系。
2、在设计数据库是尽量减少使用外键,在使用外键时要弄清楚外键是在哪个数据库表中添加。在1中出现的不能添加新的分组,问题就在外键设计不当。数据库简单还可以稍微使用一下外键,如果数据库复杂,使用外键会使数据库愈发复杂。
3、在多对多的关系中,最好是多建立一个关系,要不然会导致数据冗余等问题。

3、事务处理-·对数据进行操作

事务处理是保证数据库中数据完整性与一致性的重要机制。
事务处理,对数据库进行操作也是要根据功能需求进行设计的。

1、建立连接

private String driver = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/数据库名称?serverTimezone=UTC&characterEncoding=utf-8&&useSSL=false";
private String user = "root";
private String sqlpassword = "密码";
Connection conn = null;
Class.forName(driver);
try {
   conn = DriverManager.getConnection(url, user, sqlpassword);
} catch (SQLException ex) {
   ex.printStackTrace();
} finally {
   if (conn != null) {
      conn.close();
   }
}

2、对数据库进行操作

PreparedStatement ps = null;
ResultSet rs = null;
public List<FriendAd> AllFAdmin() throws ClassNotFoundException, SQLException {

   String sql = " select * from friend";    //查询语句
   //String sql = " delete  from friend where fname =?";  删除语句
   //String sql = "insert into friend values(?,?,?,?,?,?,?)";  插入语句
   //String sql = "update friend set =fname=?,telphone=?,mophone=?,adress=?,gname=?,gender=? where fanme=?";  更新数据
   Class.forName(driver);   //加载驱动

   FriendAd friendAd = null;
   List<FriendAd> friendAds = new ArrayList<>();
   try {
      //连接代码
      conn = DriverManager.getConnection(url, user, sqlpassword); 
      ps = conn.prepareStatement(sql);
      rs = ps.executeQuery();      //查询结果
      while (rs.next()) {
         String name = rs.getString("fname");
         String telphone = rs.getString("telphone");
         String mophone = rs.getString("mophone");
         String adress = rs.getString("adress");
         String gname = rs.getString("gname");
         String gender = rs.getString("gender");
         friendAd = new FriendAd(name, telphone, mophone, adress, gname, gender);
         friendAds.add(friendAd);     
      }
      return friendAds;

   } catch (SQLException ex) {
      ex.printStackTrace();
      return null;
   } finally {
      if (rs != null) {
         rs.close();
      }
      if (ps != null) {
         ps.close();
      }
      if (conn != null) {      //关闭连接
         conn.close();
      }
   }
}
4、代码风格简洁规范

由于这个是我第一个项目,没有很多经验,现在复看项目代码的时候发现代码紊乱,难以看出哪块代码实现的是哪个功能。实体类和数据访问层均在同一个类中,代码冗余,没有过多的对代码进行注释,难以阅读代码。
在编写程序时,代码没有规范,思路不清晰,没有条理。在命名方法和类时没有规范命名,导致代码只有自己可读,降低了代码可读性。

5、页面设计

在设计页面时没有使用布局,使得页面不稳定,使用组件的大小,默认间隙设计页面,在页面放大和缩小时组件会浮动,在意识到这点后,我在布局页面时使用了FlowLayout。

JPanel jPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 30, 50));

在设计页面时使用了许多相同的组件,为了代码简洁,使用循环给组件赋予不同的参数

MenuItem menuItem2[];
String[] strings4 = { "增加好友", "查询好友", "删除好友" };
private void initPop() {
   menuItem2 = new MenuItem[3];
   for (int i = 0; i < menuItem.length; i++) {
      menuItem2[i] = new MenuItem(strings4[i]);
      popupMenu.add(menuItem2[i]);
      menuItem2[i].addActionListener(this);
   }
   add(popupMenu);
}
6、页面渲染

好友列表使用的是树组件构成的。查询到好友列表的数据渲染在树组件上。

image.png 树根是好友列表,这个是不能改变的,每一个根节点是分组,分组下的叶子节点是该分组的好友。
创建树组件

DefaultMutableTreeNode node = new DefaultMutableTreeNode("好友列表");    //树状控件
DefaultMutableTreeNode root;
DefaultMutableTreeNode you;
JTree tree = new JTree(node);

在数据库中查询到的好友列表的数据渲染到树组件上

private void layoutCenter(Container contentPane) {

         contentPane.add(tree);
         tree.setFont(new Font(null, Font.BOLD, 15));
         tree.setOpaque(false);
         try {
            java.util.List<FriendAd> friendAds = navicatGF.AllFAdmin(); // 查询所有人的信息
            java.util.List<FriendAd> fAds = navicatGF.AllGAdmin(); // 查询所有组
            for (FriendAd fAd : fAds) {
               root = new DefaultMutableTreeNode(fAd.getGname()); // 组结点
               node.add(root);
               for (FriendAd friendAd : friendAds) { // 好友名
                  if (friendAd.getGname().equals(fAd.getGname())) {
                     you = new DefaultMutableTreeNode(friendAd.getName());
                     root.add(you);
                  }
               }
            }

   } catch (ClassNotFoundException e) {
      // TODO 自动生成的 catch 块
      e.printStackTrace();
   } catch (SQLException e) {
      // TODO 自动生成的 catch 块
      e.printStackTrace();
   }
7、背景音乐

背景音乐是不能在程序中关闭的,背景音乐在程序开始时开始,程序结束时结束。

public class Music extends Thread {
   Player player;
   String music;

   public Music(String file) {
      this.music = file;
   }

   public void run() {
      try {
         play();
      } catch (FileNotFoundException | JavaLayerException e) {
         e.printStackTrace();
      }
   }

   public void play() throws FileNotFoundException, JavaLayerException {
      BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music));
      player = new Player(buffer);
      player.play();
   }

   public void Stop() throws FileNotFoundException, JavaLayerException {
      BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music));
      player = new Player(buffer);
      player.play();
   }
}
8、总结

emmmm....从新再捋一遍感觉收获许多,语言实在太匮乏啦,没有把我想表达的表达出来。不得不说,纵使看许多的书和视频还不及自己动手实现更好。
总的来说能独立完成第一个程序已经是一个进步,虽然这个程序错漏百出,没有严谨的思路,但是把该要实现的功能都实现了。后面就不在整理这个项目啦,虽然在文章中没有完整的表达出来,但是我在复盘项目的时候收获了许多,就已经足够了。
感谢阅读,如若有误,还请指正。