javaBean和数据层的DAO设计模式

我们两清 提交于 2019-11-26 10:09:39

jsp:javaBean

一、javaBean简介

javaBean是使用java语言开发的一个人可重用的组件,在jsp开发中可以使用javaBean减少重复的代码,是一种特殊的java类,使用java语言编写,遵循javaBean API规范

优点

  1. 将html和java代码分离,这主要是为了日后的维护方便
  2. 减少代码重复

在jsp中如果要应用jsp提供的javaBean的标签来操作简单类,则此类要满足以下要求:

  • 所有类都要在一个包中,在web项目中没有包的类时不存在的。
  • 所有类必须是public修饰,这样才能被外界访问。
  • 提供一个默认的无参构造函数。
  • 需要被序列化并且实现了 Serializable 接口。
  • 可能有一系列可读写属性。(可能的意思就是除了private修饰的字段,也可以有其他修饰符修饰的字段,但是必须至少要有一个private修饰的字段)
  • 可能有一系列的 getter 或 setter 方法。

二、在jsp中使用javaBean

一个javaBean编写结束后,需要进行打包编译,那么存放到哪里呢?

classes目录保存所有的javaBean,如果不存在则可以手动创建(WEBAPP/WEB-INFO/classes)

引入useBean
  1. 打包编译

直接使用javac -d.类名,根据该类的路径的定义来打包编译变为class文件,在web开发中,tomcat安装目录的lib文件夹、WEB-INFO\classes和WEB-INFO\lib文件夹实际上都表示了classpath,所以直接将类或者jar包复制到这些文件夹中就可以直接使用了。

  1. 使用jsp:useBean指令,语法:
<jsp:useBean id="实例化对象名称(自己命名)"  scope="作用范围" class="包.类名">
  1. 使用jsp中的page指令导入所需要的javaBean<%@ page import=""%>

三、javaBean属性

1. 一个 JavaBean 对象的属性应该是可访问的。这个属性可以是任意合法的 Java 数据类型,包括自定义 Java 类。
2. 一个 JavaBean 对象的属性可以是可读写,或只读,或只写。JavaBean 对象的属性通过 JavaBean 实现类中提供的两个方法来访问:
方法 描述
getPropertyName() 举例来说,如果属性的名称为 myName,那么这个方法的名字就要写成 getMyName() 来读取这个属性。这个方法也称为访问器。
setPropertyName() 举例来说,如果属性的名称为 myName,那么这个方法的名字就要写成 setMyName()来写入这个属性。这个方法也称为写入器。
一个只读的属性只提供 getPropertyName() 方法,一个只写的属性只提供 setPropertyName() 方法。
四 、jvaBean实例程序
package taeyeon.com.jsp.javaBean;

import java.io.Serializable;

public class JavaBean_1 implements Serializable {

        private  String firstName;
        private  String lastName;
        private  Integer age;

        public String getFirstName() {
                return firstName;
        }

        public void setFirstName(String firstName) {
                this.firstName = firstName;
        }

        public String getLastName() {
                return lastName;
        }

        public void setLastName(String lastName) {
                this.lastName = lastName;
        }

        public Integer getAge() {
                return age;
        }

        public void setAge(Integer age) {
                this.age = age;
        }
}


五、访问javaBean

接下来给出的是 jsp:useBean 标签的一个简单的用法:
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>javaBean的测试</title>
</head>
<body>
<jsp:useBean id="date" scope="page" class="java.util.Date"  />
    <%
String date1=new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss").format(date);
    %>
<p>日期为<%=date1%>
</body>
</html>

输出
日期为2019-11-07 23:14:59

六、javaBean的保存范围

scope 的值可以是 page,request,session 或 application。id值可任意只要不和同一 JSP 文件中其它 jsp:useBean 中 id 值一样就行了。

七、访问javaBean对象的属性

jsp:useBean 标签主体中使用 jsp:getProperty/ 标签来调用 getter 方法,使用 jsp:setProperty/ 标签来调用 setter 方法,语法格式如下:
<jsp:useBean id="id" class="bean 编译的类" scope="bean 作用域">
   <jsp:setProperty name="bean 的 id" property="属性名"  
                    value="value"/>
   <jsp:getProperty name="bean 的 id" property="属性名"/>
   ...........
</jsp:useBean>
name属性指的是Bean的id属性。property属性指的是想要调用的getter或setter方法。

接下来给出使用以上语法进行属性访问的一个简单例子:

<%--
  Created by IntelliJ IDEA.
  User: YOONA
  Date: 2019/11/7/007
  Time: 23:00
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>javaBean的Property </title>
</head>
<body>
<jsp:useBean id="student" scope="page" class="taeyeon.com.jsp.javaBean.JavaBean_1">
    <jsp:setProperty name="student" property="firstName" value="teayeon"/>
    <jsp:setProperty name="student" property="lastName" value="西西"/>
    <jsp:setProperty name="student" property="age" value="19"/>
</jsp:useBean>

<p>学生名字:
    <jsp:getProperty name="student" property="firstName"/>
</p>
<p>学生姓氏:
    <jsp:getProperty name="student" property="lastName"/>
</p>
<p>学生年龄:
    <jsp:getProperty name="student" property="age"/>
</p>

</body>
</html>

输出
学生名字: teayeon

学生姓氏: 西西

学生年龄: 19

八、javaBean的删除

当不再使用javaBean的时候,我们可以使用4种属性范围的removeAttribute()方法进行删除。
  • 删除page域:pageContext.removeAttribute(javaBean名称id);
  • 删除request域:request.removeAttribute(javaBean名称id);
  • 删除session域:session.removeAttribute(javaBean名称id);
  • 删除application域:application.removeAttribute(javaBean名称id);
删除session范围的javaBean
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>通过removeAttribute()方法进行删除javaBean</title>
</head>
<body>
<jsp:useBean id="sessionScope" scope="session" class="taeyeon.com.jsp.javaBean.JavaBean_1">
    <jsp:setProperty name="sessionScope" property="age" value="21"/>
</jsp:useBean>
<p>年龄1:<jsp:getProperty name="sessionScope" property="age"/></p>
<%
    session.removeAttribute("sessionScope");
%>
<p>年龄2:<jsp:getProperty name="sessionScope" property="age"/></p>
</body>
</html>
输出

当我们不使用session.removeAttribute("sessionScope");这行语句时系统运行正常,但是当我们使用时,就会报错在<p>年龄2:<jsp:getProperty name="sessionScope" property="age"/></p>报错,因为运行到这一行时该id的javaBean已经被删除了,所以会报错500:java.lang.NullPointerException

年龄1:21

九、dao设计模式

1. DAO设计模式简介
DAO的主要功能就是数据操作,在程序的标准开发构架中属于数据层的操作,程序的标准开发构架如下:

客户层 -->显示层(servlet、jsp)-->业务层(BO)-->数据层(DAO)-->(资源层)DataBase

  • 客户层:因为现在都采用B/S开发构架,所以一般都是用浏览器进行访问。
  • 显示层:使用jsp、Servlet进行页面效果的显示。
  • 业务层:会将多个原生的DAO操作进行组合,组合成一个完整的业务逻辑。
  • 数据层:提供多个原子性的DAO操作,如增删改,都属于原子性操作。
在整个DAO中实际上是以接口为操作标准的,即客户端依靠DAO实现的接口进行操作,而服务器端将接口进行具体的实现。DAO由以下几部分组成。
  • DatabaseConnection:专门负责数据库打开与关闭操作的类;

  • VO:主要由属性,setter,getter方法组成,VO类中的属性与表中的字段相对应,每一个VO类的对象都表示表中的每一条记录;

  • DAO:主要定义操作的接口,定义一系列数据库的原子性操作,例如增删改查等;

  • Impl: DAO接口的真实实现类,主要完成具体数据库操作,但不负责数据库的打开和关闭;

  • Proxy:代理实现类,主要完成数据库的打开和关闭并且调用真实实现类对象的操作;

  • Factory: 工厂类,通过工厂类取得一个DAO的实例化对象。

对于包的命名:

一个好的程序必须要有严格的命名要求,在使用DAO定义操作时一定要注意包的命名很严格,使用如下方式命名:

  • 数据库连接: xxx.dbc.DatabaseConnection
  • DAO接口: xxx.dao.IXxxDAO
  • DAO接口真实实现类:xxx.dao.impl.XxxDAOImpl
  • DAO接口代理实现类:xxx.dao.proxy.XxxDAOProxy
  • VO类:xxx.vo.Xxx, VO命名要与表的命名一致
  • 工厂类:xxx.factory.DAOFactory.
2. DAO开发
  • 用户注册信息表user
create table user
(
   ID          int    auto_increment comment '序列号',
   NAME        varchar(50)  not null, -- 姓名
   USERNAME    varchar(100) primary key not null, -- 用户名(登陆名)
   PASSWORD    varchar(30)  null, -- 密码
   SEX         char(5)      null,  --性别
   TEL         varchar(20)  null,  -- 电话
   PWDTROUBLE1 varchar(100) null,  -- 密保问题1
   ANSWER1     varchar(100) null,-- 答案1
   PWBTROUBLE2 varchar(100) null, -- 密保问题2
   ANSWER2     varchar(100) null,  --答案2
   constraint user_ID_uindex  --索引
       unique (ID)
)
   comment '用户信息表';
  • 下面按照DAO的方式完成后端代码的开发,首先定义VO类,VO类的名称与表的名称一致,类的首字母大写,该类表示当前用户,可以存储一些该用户的属性。
package taeyeon.com.dao_1;

import java.io.Serializable;

/**
 * 定义用户信息类,保存用户个人信息
 */
public class User implements Serializable {
        private String name;//用户姓名
        private String username;//登陆名
        private String password;//密码
        private String tel;//电话
        private String sex;//性别
        private String pwdtrouble1;//密保问题
        private String answer1;//答案
        private String pwbtrouble2;
        private String answer2;

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        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;
        }

        public String getTel() {
                return tel;
        }

        public void setTel(String tel) {
                this.tel = tel;
        }

        public String getSex() {
                return sex;
        }

        public void setSex(String sex) {
                this.sex = sex;
        }

        public String getPwdtrouble1() {
                return pwdtrouble1;
        }

        public void setPwdtrouble1(String pwdtrouble1) {
                this.pwdtrouble1 = pwdtrouble1;
        }

        public String getAnswer1() {
                return answer1;
        }

        public void setAnswer1(String answer1) {
                this.answer1 = answer1;
        }

        public String getPwbtrouble2() {
                return pwbtrouble2;
        }

        public void setPwbtrouble2(String pwbtrouble2) {
                this.pwbtrouble2 = pwbtrouble2;
        }

        public String getAnswer2() {
                return answer2;
        }

        public void setAnswer2(String answer2) {
                this.answer2 = answer2;
        }
}

  • 定义数据库连接和关闭的操作接口
package taeyeon.com.dao_1;
import java.sql.Connection;

/**
 * 定义数据库的链接与关闭接口
 */
public interface DatabaseConnection {

        public Connection getConnection();
        public void close();
}
  • 定义一个用于打开关闭数据库操作的类,实现DatabaseConnection接口
package taeyeon.com.dao_1;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

@SuppressWarnings("ALL")
/**
 * 实现数据库的链接与关闭接口
 * @param URL:mysql链接的url
 * @param NAME:用户名
 * @param PASSWORD:链接密码
 * @param DRIVER:mysql链接的jdbc驱动
 */
public class UserDatabaseConnection implements DatabaseConnection {

        private static final String URL = "jdbc:mysql://localhost:3306/student";
        private static final String NAME = "lining";
        private static final String PASSWORD = "123456";
        private static final String DRIVER = "com.mysql.jdbc.Driver";
        private Connection connection;

        public UserDatabaseConnection() {
                try {
                        Class.forName(DRIVER);
                        this.connection = DriverManager.getConnection(URL, NAME, PASSWORD);
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }

        //取得当前对象数据库链接
        @Override
        public Connection getConnection() {
                return this.connection;
        }

        //关闭当前对象数据链接
        @Override
        public void close() {
                if (this.connection != null) {
                        try {
                                this.connection.close();
                        } catch (SQLException e) {
                                e.printStackTrace();
                        }
                }
        }

}

  • 创建实现数据库连接关闭类UserDatabaseConnection的工厂类,该类可以直接获取其他类的实例。
package taeyeon.com.dao_1;
/**
 * 创建链接类的工厂<br/>
 * 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。<br/>
 * 通过专门定义一个类来负责创建其它类的实例,被创建的实例通常<br/>
 * 都具有共同的父类。
 */
public class UserDatabaseConnectionFactory  {
        public  static DatabaseConnection getDatabaseConnection(){
                return new UserDatabaseConnection();
        }
}
  • 定义DAO接口,用于实现用户具体对数据库的操作,比如对数据的增删改查。
package taeyeon.com.dao_1;

import java.util.List;
import java.util.Map;

/**
 *定义操作数据库的方法
 */
public interface IUserDAO {
        /**
         * 修改数据(增加,跟新)
         */
        public boolean doModify(String state, String username, Map<String,String> map,User userMsg);

        /**
         * 修改密码
         */
        public boolean doModifyPWD(String username,String pwd);

        /**
         * 查询数据(按照登陆名来查询信息)
         */
        public List<User> doSelect(String username);

}

  • 创建用于实现IUserDAO接口的类
package taeyeon.com.dao_1;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

@SuppressWarnings("ALL")
public class UserDaoImpl implements IUserDAO {

        private Connection conn;
        private PreparedStatement pst;

        //当创建该类的对象时获得链接
        public UserDaoImpl(Connection conn) {
                this.conn = conn;
        }

        /**
         * 判断是否修改数据成功(增加,更新)
         *
         * @param state=(I,U)                         I代表新增注册信息,U代表用户修改基本数据
         * @param username:表示当前登录的用户名
         * @param map:用于当前用户更新数据。除掉密码修改,密码修改有单另的方法和界面
         * @param userMsg:用于新增数据的对象
         * @return
         */
        @Override
        public boolean doModify(String state, String username, Map<String, String> map, User userMsg) {
                boolean flag = false;
                if ("I" == state) {
                        //新增用户数据时,用的是注册的信息,所以可以使用getXXX来获取User类的数据
                        String sql = "INSERT INTO USER ( NAME , USERNAME ,PASSWORD , SEX  , TEL , PWDTROUBLE1  ," +
                                " ANSWER1 , PWBTROUBLE2 , ANSWER2,LOGINDATE )  VALUES  (?,?,?,?,?,?,?,?,?,sysdate)";
                        try {
                                this.pst = this.conn.prepareStatement(sql);
                                this.pst.setString(1, userMsg.getName());
                                this.pst.setString(2, userMsg.getUsername());
                                this.pst.setString(3, userMsg.getPassword());
                                this.pst.setString(4, userMsg.getSex());
                                this.pst.setString(5, userMsg.getTel());
                                this.pst.setString(6, userMsg.getPwdtrouble1());
                                this.pst.setString(7, userMsg.getAnswer1());
                                this.pst.setString(8, userMsg.getPwbtrouble2());
                                this.pst.setString(9, userMsg.getAnswer2());
                                if (this.pst.executeUpdate() > 0) {//判断该链接对象运行的sql语句返回受影响行数是否大于0
                                        flag = true;
                                }
                                this.pst.close();
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                } else {
                        //更新数据是使用登录后的用户this,将修改界面的数据更新到该用户名的数据中
                        if (map.size() != 0) {
                                String name = map.get("NAME");
                                String username1 = map.get("USERNAME");//修改的用户名
                                String sex = map.get("SEX");
                                String tel = map.get("TEL");
                                String pwdtrouble1 = map.get("PWDTROUBLE1");
                                String answer1 = map.get("ANSWER1");
                                String pwbtrouble2 = map.get("PWBTROUBLE2");
                                String answer2 = map.get("ANSWER2");
                                String sql = "UPDATE   USER  SET  NAME=" + name + " , USERNAME=" + username1 + "  , SEX =" + sex + " , " +
                                        "TEL=" + tel + " , PWDTROUBLE1 =" + pwdtrouble1 + " ," +
                                        " ANSWER1 =" + answer1 + ", PWBTROUBLE2=" + pwbtrouble2 + " , ANSWER2 =" + answer2 + ")  " +
                                        "WHERE USERNAME= ? ";
                                try {
                                        this.pst = this.conn.prepareStatement(sql);
                                        this.pst.setString(1, username);
                                        if (this.pst.executeUpdate() > 0) {
                                                flag = true;
                                        }
                                        this.pst.close();
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
                return flag;
        }

        /**
         * 修改密码
         * 利用当前用户的用户名来查找该密码,进行更改登录密码
         *
         * @param username:当前用户的用户名
         * @return
         */
        @Override
        public boolean doModifyPWD(String username, String pwd) {
                boolean flag = false;
                String sql = "UPDATE  USER SET  PASSWORD=?  WHERE USERNAME =?";
                try {
                        this.pst = this.conn.prepareStatement(sql);
                        this.pst.setString(1, pwd);
                        this.pst.setString(2, username);
                        if (this.pst.executeUpdate() > 0) {
                                flag = true;
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }
                return flag;
        }

        /**
         * @param username:根据用户登录名来查询客户基本信息然后返回到信息页面上
         * @return 将用户信息保存在list集合中
         */
        @Override
        public List<User> doSelect(String username) {
                String sql = "SELECT   NAME  , USERNAME , SEX  , TEL , PWDTROUBLE1    ,ANSWER1, PWBTROUBLE2, " +
                        "ANSWER2  FROM  USER WHERE  USERNAME=?";
                List<User> userList = null;
                try {
                        this.pst = this.conn.prepareStatement(sql);
                        ResultSet rs = this.pst.executeQuery();
                        if (this.pst.execute()) {//如果返回的有结果集
                                while (rs.next()) {
                                        User user = new User();
                                        user.setName(rs.getString(1));
                                        user.setUsername(rs.getString(2));
                                        user.setSex(rs.getString(3));
                                        user.setTel(rs.getString(4));
                                        user.setPwdtrouble1(rs.getString(5));
                                        user.setAnswer1(rs.getString(6));
                                        user.setPwbtrouble2(rs.getString(7));
                                        user.setAnswer2(rs.getString(8));
                                        userList.add(user);
                                }
                        }
                } catch (SQLException e) {
                        e.printStackTrace();
                }
                return userList;
        }
}
  • 创建用于具体操作用户数据的代理类,用于连接操作关闭数据库。
package taeyeon.com.dao_1;

import java.util.List;
import java.util.Map;

/**
 * 用来实行数据库连接,数据库操作,关闭数据库
 */
public class IUserDAOProxy implements IUserDAO {
        private DatabaseConnection dbc = null;
        private IUserDAO dao = null;

        public IUserDAOProxy() {
                this.dbc = UserDatabaseConnectionFactory.getDatabaseConnection();
                this.dao = new UserDaoImpl(this.dbc.getConnection());//获得数据库连接
        }

        @Override
        public boolean doModify(String state, String username, Map<String, String> map, User userMsg) {
                boolean flag = false;
                flag = this.dao.doModify(state, username, map, userMsg);
                return flag;
        }

        @Override
        public boolean doModifyPWD(String username, String pwd) {
                boolean flag = false;
                flag = this.dao.doModifyPWD(username, pwd);
                return flag;
        }

        @Override
        public List<User> doSelect(String username) {
                List<User> list = null;
                list = this.dao.doSelect(username);
                return list;
        }
}
  • 创建该代理类的工厂类
package taeyeon.com.dao_1;

public class IUserDAOProxyFactory {
        public static IUserDAOProxy getIUserDAOInstance() {
                return new IUserDAOProxy();
        }
}

在书写dao设计模式的开发时,要做到低耦合,这样才能减少每个类之间的依赖性,降低后期维护的难度

八、总结

  1. 使用javaBean可以减少jsp中的代码重复,以达到程序的重用功能。
  2. 在jsp中定义了jsp:useBean,jsp:setProperty,jsp:getProperty3个标签支持javaBean操作
  3. javaBean存在page,request,session,application四种操作域,可以用removeAttribute()删除这四种属性范围中设置的属性。
  4. DAO设计模式可以完成数据层的开发,首先使用DAO定义数据表的操作标准,即具体对数据的操作,然后通过代理类和真实实现类实现接口的具体操作,真实实现类只操作数据,代理类实现对数据库的连接,数据库的关闭,调用具体实现类实现对数据的操作,所有DAO接口的实例要通过工厂类取得。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!