Fork me on GitHub

面向接口编程

1. DAO 模式

  • DAO 模式就是写一个类,把访问数据库的代码封装起来. DAO 在数据库与业务逻辑(Service)之间.
    换句话说, java.sql 包下的内容不能出现在 DAO 层以外.
  • 实体域, 即操作的对象, 例如我们操作的表是 user 表, 那么就需要写一个 User 类;
  • DAO 模式需要先提供 DAO 接口;
  • 然后再提供一个 DAO 接口的实现类;
  • 再编写一个 DAO 工厂, Service 通过工厂来获取 DAO 实现.
// DAO 层
public class UserDao{
    public User findByUsername(String username){

        private String path="/Users/姓名/Desktop/users.xml;"

        // 查找方法
        public User findByUsername(String username){

            // 创建解析器
            SAXReader reader = new SAXReader();

            try{
                Document doc = reader.read(path);
                // 使用 XPath 查找属性为 username 的元素
        Element ele = (Element)doc.selectSingleNode("//user[@username='"+username+"']");

                // 如果没有找到, 返回 null
                if(ele==null) return null;


                // 如果找到了, 返回 User 对象
                User user = new User();
                String attrUsername = ele.attributeValue("username");
                String attrPassword = ele.attributeValue("password");
                User.setUsername(attrUsername);
                User.setPassword(attrPassword);

                return user;
            } catch (DocumentException e){
                throw new RuntimeException(e);
            }
        }

        // 添加元素方法
        public void addUser(User user){

            // 创建解析器
            SAXReader reader = new SAXReader();

            try{
                Document doc = reader.read(path);
                Element root = doc.getRootElement();

                // 添加 user 元素
                Element ele = root.addElement("user");

                // 添加属性
                ele.addAttribute("username",user.getUsername());
                ele.addAttribute("password",user.getPassword());

                // 回写
                OutputFormat format = new OutputFormat("\t",true);
                // 清除原有换行和缩进
                format.setTrimText(true);

                XMLWriter writer = new XMLWriter(
                            new OutputStreamWriter(
                                new FileOutputStream(path),"utf-8"),format);

                writer.write(doc);
                writer.close();
            } catch(Exception e){
                throw new RuntimeException(e);
            }
        }
    }
}

// service 层
    public class UserService{

        // 因为依赖 Dao 层, 创建 userDao 对象
        private UserDao userDao = new UserDao();
        ....
    }


// 升级版
    // 创建 UserDao 接口
    pulic interface UserDao{
        public void addUser(User form);
        public User findByUsername(String username);
    }

    // 创建 UserDao 接口的实现类
    public class UserDaoImpl implements UserDao{
        private String path = "/Users/姓名/Desktop/users.xml";

        // 查找方法
        public User findByUsername(String username){

            // 创建解析器对象
            SAXReader reader = new SAXReader();

            try{
                Document doc = reader.read(path);
          Element ele = (Element)doc.SelectSingleNode("//user@[username='"+username+"']");

                if(ele==null) return null;

                String attrUsername = ele.attributeValue("username");
                String attrPassword = ele.attributeValue("password");

                User user = new User();
                user.setUsername(attrUsername);
                user.setPassword(attrPassword);
                return user;
            } catch(DocumentException e){
                throw new RuntimeException(e);
            }
        }

        // 添加方法
        public void addUser(User user){

            SAXReader reader = new SAXReader();
            try{
                Document doc = reader.read(path);
                Element root = doc.getRootElement();
                Element ele = root.addElement("user");

                ele.addAttribute("username",user.getUsername());
                ele.addAttribute("password",user.getPassword());

                // 回写 xml
                OutputFormat format = new OutputFormat("\t",true);
                format.setTrimText(true);

                XMLWriter writer = new XMLWriter(
                                    new OutputStreamWriter(
                                        new FileOutpuStream(path),"utf-8"
                                    ),format);

                writer.write(doc);
                writer.close();
            } catch(Exception e){
                throw new RuntimeException(e);
            }
        }
    }

// src 目录下的 dao.properties
// 其中键为接口名, 值为接口的实现类
    cn.itcast.user.dao.UserDao=cn.itcast.user.dao.UserDaoImpl


// 创建 DaoFactory, 提供 getUserDao() 方法
    public class DaoFactory{

        private static Properties props = null;
        static{
            // 加载配置文件内容到 props 对象中
            try{
                InputStream in =
                  DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
                props = new Properties();
                props.load(in);

            }catch(IOException e){
                throw new RuntimeException(e);
            }
        }


        public static UserDao getUserDao(){
            // 给出一个配置文件, 文件中给出 UserDao 接口的实现类名称!
            // 我们这个方法, 获取实现类的类名, 通过反射完成创建对象!!
            // 配置文件 dao.properties 在 src 目录下

            /*  
             * 将配置文件中的内容加载到 props 对象中
             * (因为并不需要每回都加载, 所以放到静态代码块中)
             * InputStream in =
             *     DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
             *
             * Properties props = new Properties();
             * props.load(in);
             */

            // 得到 dao 实现类的名称
            String daoClassName = props.getProperty("cn.itcast.user.dao.UserDao");

            // 通过反射来创建实现类的对象
            try{
                Class clazz = Class.forName(daoClassName);
                return (UserDao)clazz.newInstance();
            } catch (Exception e){
                throw new RuntimeException(e);
            }
        }
    }


// service 层
    public class UserService{

        // 把具体的实现类的创建, 隐藏到工厂中
        private UserDao userDao = DaoFactory.getUserDao();

        .....
    }


// 创建一个新类, 实现 UserDao 接口, 操作 MySql 数据库
// 使用 MySql 数据库, 需要导包 mysql-connector-java
// 使用 JdbcUtils 小工具类和 dbconfig.properties 来获取 Connection 对象 
    public class JdbcUserDaoImpl implements UserDao{

        public User findByUsername(String username){
            Connection con = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            try{
                // 得到 Connection 对象
                con = JdbcUtils.getConnection();

                // 准备 sql 模板, 创建 PreparedStatement 对象
                String sql = "SELECT * FROM user WHERE username=?";
                pstmt = con.prepareStatement(sql);

                // 为 sql 模板赋值
                pstmt.setString(1,username);

                // 发送 sql 语句, 返回 ResultSet 对象
                rs = pstmt.executeQuery();

                if(rs==null) return null;

                // 获取 ResultSet 对象中的内容
                if(rs.next()){

                    // 将 ResultSet 对象中的内容封装到 User 对象中
                    User user = new User();
                    user.setUsername(rs.getString("username"));
                    user.setPassword(rs.getString("password"));

                    return user;
                }else{
                    // 如果第一行内容为空,也返回 null.
                    return null;
                }

            }catch(Exception e){
                throw new RuntimeException(e);
            }finally{
                try{
                    if(rs != null) rs.close();
                    if(pstmt != null) pstmt.close();
                    if(con != null) con.close();
                }catch(Exception e){
                    throw new RuntimeException(e);
                }
            }
        }

        public void addUser(User user){
            Connection con = null;
            PreparedStatement pstmt = null;

            try{
                con = JdbcUtils.getConnection();

                // 创建 sql 模板, 获取 PreparedStatement 对象
                String sql = "INSERT INTO user VALUES(?,?)";
                pstmt = con.prepareStatement(sql);

                // 为 sql 模板中的参数赋值
                pstmt.setString(1,user.getUsername());
                pstmt.setString(2,user.getPassword());

                // 发送 sql 语句
                pstmt.executeUpdate();

            } catch(Exception e){
                throw new RuntimeException(e);
            } finally{
                // 关闭资源
                try{
                    if(pstmt != null) pstmt.close();
                    if(con != null) con.close();
                }catch(Exception e){
                    throw new RuntimeException(e);
                }
            }
        }
    }

// 然后只需要修改 dao.properties 配置文件,
// 就可以将数据库 从 xml 文件改为 MySql 数据库
cn.itcast.user.dao.UserDao=cn.itcast.user.dao.JdbcUserDaoImpl

参考资料:

posted @ 2017-10-02 10:41  小a的软件思考  阅读(212)  评论(0编辑  收藏  举报