• 最课程阶段大作业04:毫无用处的学生管理系统


    前面几期就业班学生知道,我在做简历指导时说过:如果你的简历中项目经历写的是“学生管理系统”、“**办公自动化”这样的系统,那么就等于告诉面试官:你没有项目经验。

    对于面试找工作,学生管理系统这样的项目简直毫无用处,甚至是减分项。如果你一定要说你实现了一个NB的学生管理系统,那么就需要拿出你在GITHUB上的源码来,并对面试官说:我已经把它做成了一个框架,以后所有的用户管理系统都可以基于这个框架进行扩展~~

    学生管理系统对于找工作毫无用处,但对于当前的我们来说,倒是一个好的案例。如果说HelloWorld是我们学习Java的第一个程序,那么学生系统则应该说是我们在做项目时的HelloWorld。

    它,简单,直观。即使再笨,我们也能切身知道其中的业务逻辑。

    为什么?因为现阶段我们刚学完MySql+JDBC,迫切需要做一个真实的案例来检验和巩固学习的知识,那么这个简单的Mis系统再合适不过了。

    如果能独立完成该MIS系统,那意味着我们可以做最基础的增删改查(CRUD)了。不过,仅仅用这个案例来完成CRUD的工作,有点太浪费这次练习的时间了,我们不妨稍稍提升下B格:做一个三层架构的CRUD。

    实现取数据

    先假设数据库中已经存在学生表,现在要用java代码把所有的学生全部取出来并显示到前台,该怎么做?

    按照以前的写法,我们会这样去实现(使用了c3p0和DbUtils,配置文件及附属代码略):

    package com.zuikc.usermanagement;
    
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.ResultSetHandler;
    
    public class IndexPage {
        public static void main(String[] args) throws SQLException {
            QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
            List<User> users = qr.query("select * from user_tb", new ResultSetHandler<List<User>>(){
    
                @Override
                public List<User> handle(ResultSet rs) throws SQLException {
                    List<User> list = new ArrayList<User>();
                    while(rs.next()){
                        User user = new User();
                        user.setUsername(rs.getObject("username").toString());
                        System.out.println(user.getUsername());
                        list.add(user);
                    }
                    return list;
                }});
    
        }
    }

    顺便附上整个项目结构:

    但紧接着问题来了,现在需求变更为:将用户列表从数据库取出来导出到文件中~~。

    有同学说,这好办,让我们修改代码:

    List<User> list = new ArrayList<User>();
                    try {
                        FileWriter writer = new FileWriter("c:\temp\temp.txt");
                        while (rs.next()) {
                            User user = new User();
                            user.setUsername(rs.getObject("username").toString());
                            //System.out.println(user.getUsername());
                            writer.write(user.getUsername() + "
    ");
                            list.add(user);
                        }
                        
                        writer.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return list;

    看上去,问题解决了。但是紧接着问题又来了,让我们把结果输出到网页中或者socket传输到另一台电脑中。怎么办?

    难道我们只要有新需求,就去改这个while循环吗?

    不知道大家有没有发现,无论我们的输出怎么变化,我们的“获取数据”这部分的代码实际上从来没有变过。

    没有变过的代码能不能将它隔离开来放到某个层中呢?答案当然是可以的,这种手法就叫做:分层架构的设计思想。

    什么是三层架构

    所谓架构,指的是一种编码的思想,一种指导我们将代码写的更加优美的思想。三层架构是最早出现的软件架构设计思想之一,它用于指导我们将代码归置的更整洁,以便我们完成更庞大的系统。

    最原始的分层架构,叫做:三层架构(表示层、业务逻辑层、数据访问层)。每层的作用如下:

    01.表示层(User Interface layer):如果光看英文,直译过来是:用户接口层。也就是说,这个层专门负责接收用户的输入,将输出呈现给用户。另外,输入输出过程中的访问安全性验证、输入的数据的正确性验证也由这个层负责。

    02.业务逻辑层(Business Logic Layer):负责系统业务逻辑的处理。它也包括对所输入的逻辑性数据的正确性及有效性的负责。有人可能要问,UI层不是已经负责了正确性吗,为什么业务逻辑层也要负责?答案是:因项目而异。在部分项目中,需要将正确性验证等功能放置在UI层,而在有些项目中,则在业务逻辑层,甚至有些项目,两个层都要做。

    03.数据访问层(Data Access Layer):数据访问层的功能较为单一,它负责与数据源的交互,即数据的插入,删除,修改,以及从数据库中读出数据等操作,但对数据的正确性和有效性不负责,对业务逻辑不负责。

    结束了吗?其实并没有,以上是最主要的三层,实际还有有些辅助的层,如:

    04 工具层

    通用类库,比如一些工具类就可以放在这里。这些工具类最简单的可以是检验email是否符合规则,也可以是加密解密工具类,同时,数据库连接帮助类也放在这里。

    05实体层

    比如,上文代码中的User类,就是一个实体类。它很大程度上是数据库表字段在Java语言中的对应。

    以上,基本上就差不多了。它们的主要依赖关系如下:

    接下来,让我们改造代码以便符合三层架构。

    其中,

    表示层:com.zuikc.usermanagement.ui

    业务逻辑层:com.zuikc.usermanagement.biz

    数据访问层:com.zuikc.usermanagement.dao

    工具层:com.zuikc.usermanagement.common

    实体层:com.zuikc.usermanagement.bean

    从上层到下层的代码依次为:

    表示层,IndexPage:

    package com.zuikc.usermanagement.ui;
    
    import java.util.List;
    import com.zuikc.usermanagement.bean.User;
    import com.zuikc.usermanagement.biz.UserService;
    
    public class IndexPage {
        public static void main(String[] args) throws Exception {
            
            UserService service = new UserService();
            List<User> users = service.getAllUsers();
            for (User user : users) {
                System.out.println(user.getUsername());
            }
        }
    }

    业务逻辑层,UserService:

    package com.zuikc.usermanagement.biz;
    
    import java.sql.SQLException;
    import java.util.List;
    
    import com.zuikc.usermanagement.bean.User;
    import com.zuikc.usermanagement.dao.UserDao;
    
    public class UserService {
        UserDao dao = new UserDao();
        
        public List<User> getAllUsers() throws SQLException{
            List<User> users = dao.queryUsers();
            return users;
        }
    }

    数据访问层,UserDao:

    package com.zuikc.usermanagement.dao;
    
    import java.io.FileWriter;
    import java.io.IOException;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.ResultSetHandler;
    
    import com.zuikc.usermanagement.bean.User;
    import com.zuikc.usermanagement.common.C3P0Util;
    
    public class UserDao {
        public List<User> queryUsers() throws SQLException {
            QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
            List<User> users = qr.query("select * from user_tb", new ResultSetHandler<List<User>>() {
    
                @Override
                public List<User> handle(ResultSet rs) throws SQLException {
                    List<User> list = new ArrayList<User>();
                    while (rs.next()) {
                        User user = new User();
                        user.setUsername(rs.getObject("username").toString());
                        list.add(user);
                    }
    
                    return list;
                }
            });
    
            return users;
        }
    }

    工具层,C3P0Util:

    package com.zuikc.usermanagement.common;
    
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import javax.sql.DataSource;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class C3P0Util {
        // 得到数据源
        private static DataSource dataSource = new ComboPooledDataSource();
    
        public static DataSource getDataSource() {
            return dataSource;
        }
    
        // 得到连接对象
        public static Connection getConnection() {
            try {
                return dataSource.getConnection();
            } catch (SQLException e) {
                throw new RuntimeException("获取连接失败");
            }
        }
    
        public static void release(Connection conn, Statement stmt, ResultSet rs) {
            if (rs != null) {
                try {
                    rs.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    
    }

    实体层,User:

    package com.zuikc.usermanagement.bean;
    
    public class User {
        String username;
        String password;
        
        public User() {
        }
        public User(String username, String password) {
            super();
            this.username = username;
            this.password = password;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }

    最后放上一个c3p0的配置文件c3p0-config.xml,

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
      <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3317/test</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
      </default-config>
    </c3p0-config>

    三层架构的优缺点

    优点: 

    1、在某种架构下,某些开发人员可以只关注整个结构中的其中某一层;

    2、可以很容易的用新的实现来替换原有层次的实现(后面要学的动态代理、spring等);

    3、可以降低层与层之间的依赖;

    4、有利于标准化;

    5、利于各层逻辑的复用。

    6、扩展性强。不同层负责不同层次的代码。

    7、安全性高。用户端只能通过逻辑层来访问数据层,减少了入口点,把很多危险的系统功能都屏蔽了。

    8、项目结构更清楚,分工更明确,有利于后期的维护和升级 

    缺点:

    1、降低了系统的性能。分层之后,会增加代码,有些地方看上去仅仅就是service层封装了一下dao层。代码增加,意味着性能降低。

    2、可能存在级联的修改。为了增加某个功能,相应的要去增加service和dao。

    3、增加了代码量,增加了工作量

    更进一步的三层架构?

    聪明的同学可能已经发现,分层的“层”这个概念在当前这个java项目中对应的就是包(package)的概念。那是不是永远是这样的呢?

    并不是。层的概念,更多的是project的概念。在大型项目中,一个层就是一个project,就是一个jar包。

    我们可以继续改造我们的三层架构代码,看下图:

    在这个过程中,我们将每个层都独立成为了一个Project了。如果大家仔细观察,我们会发现,上层service和ui层,压根就没有依赖数据库的那几个第三方包。在实际的开发中,其实也是这样:

    作为UI层的,可能是一个动态网页,可能是手机APP端的,对于它们来说,实际上它们不应该,也不需要知道我们的数据是来自于数据库还是来自于其它地方。对于它们来说,只需要知道:我现在需要一个用户列表,于是底层就给了它一个用户列表。仔细回味一下这句话。

    上层所依赖的只是下层的包:

    UI层,依赖com.zuikc.usermanagement.biz, com.zuikc.usermanagement.bean, com.zuikc.usermanagement.common;

    Service层,依赖com.zuikc.usermanagement.dao,com.zuikc.usermanagement.bean,com.zuikc.usermanagement.common;

    Dao层,依赖com.zuikc.usermanagement.bean,com.zuikc.usermanagement.common;

    Bean层,谁都不依赖(可以依赖common),被谁都依赖;

    Common,谁都不依赖,被谁都依赖;

    有同学可能对于project依赖另一个project不熟悉,下面给出图示:

    第一步,

    第二步,

    第三步,

    以上,我们完成了一个最彻底的三层架构的解决方案。

    作业之用例

    有了上面的知识储备,现在引出我们的大作业。

     

    1.主界面

     

    2.添加用户

     

    3.用户列表

     

    4.用户查询

     

    5.用户删除

     

    作业之要求

     

    华丽分割线

    ===========================================================

    最课程JavaEE+互联网分布式新技术开班进行中,来http://www.zuikc.com

    看看吧。你想参加不一样的培训班,并且一毕业就NB,那就来加入我们吧;

    更多技术文章和开班信息请加入,

    QQ群:

     

  • 相关阅读:
    java数组------数组基本使用和3中初始化方式
    java面向对象-------final关键字
    java面向对象------- 多态
    java面向对象------- 封装
    Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
    Android 音视频开发(四):使用 Camera API 采集视频数据
    音频 PCM 数据的采集和播放
    http协议的学习
    Kotlin入门学习笔记
    RxJava笔记
  • 原文地址:https://www.cnblogs.com/luminji/p/9633974.html
Copyright © 2020-2023  润新知