1.访问数据库

step1.导包

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>

step2. 将jdbc02工程中的DBUtils和jdbc.properties文件拷贝过来。

public class DBUtils {
private static BasicDataSource dataSource;

static {
    Properties prop = new Properties();
    //文件输入流
    InputStream ips = DBUtils.class.getClassLoader()
            .getResourceAsStream("jdbc.properties");
    try {
        prop.load(ips); 
        String driver = prop.getProperty("driver");
        String url = prop.getProperty("url");
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        String initSize = prop.getProperty("initSize");
        String maxSize = prop.getProperty("maxSize");
        //创建连接池数据源对象

        dataSource = new BasicDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setInitialSize(Integer.parseInt(initSize));
        dataSource.setMaxActive(Integer.parseInt(maxSize));


    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static Connection getConn() 
        throws SQLException {
    return dataSource.getConnection();
}

public static void close(ResultSet rs,
        Statement stat,Connection conn) {
    if(rs != null) {
        try {
            rs.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if(stat != null) {
        try {
            stat.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if(conn != null) {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        }
    }
}

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jsd1810db?useUnicode=true&characterEncoding=UTF-8
username=root
password=root
initSize=3
maxSize=5

step3. 建库建表。

create database jsd1810db default character set utf8;
use jsd1810db;

create table t_user(
    id int primary key auto_increment,
    username varchar(50) unique,
    password varchar(30),
    email varchar(50)
);

step4. 测试DBUtils

System.out.println(DBUtils.getConn());

step5. 修改AddUserServlet,使用jdbc访问数据库。

public class AddUserServlet extends HttpServlet{

@Override
protected void service(
        HttpServletRequest request, 
        HttpServletResponse response) 
                throws ServletException,
                IOException {

    /*
     * 设置处理post请求时,使用指定的字符集
     * 对请求参数值进行解码。
     * 注:
     *   这行代码一定要添加到所有的getParameter
     * 方法的最前面。
     */
    request.setCharacterEncoding("utf-8");
    response.setContentType(
            "text/html;charset=utf-8");
    PrintWriter out = response.getWriter();

    //读取用户信息
    String username =
            request.getParameter("username");
    String pwd = 
            request.getParameter("pwd");
    String email =
            request.getParameter("email");


    System.out.println(
            "username:" + username + " pwd:" 
            + pwd + " email:" + email);

    //将用户信息插入到数据库
    Connection conn = null;
    PreparedStatement stat = null;
    try {
        conn = DBUtils.getConn();
        stat = conn.prepareStatement(
                "INSERT INTO t_user "
                + "VALUES(null,?,?,?)");
        stat.setString(1, username);
        stat.setString(2, pwd);
        stat.setString(3, email);
        stat.executeUpdate();

        out.println("添加成功");

    } catch (SQLException e) {
        /*
         * step1.记日志(保留现场)。
         * 日志一般会记录在文件里面。
         */
        e.printStackTrace();
        /*
         * step2.看异常能否恢复,如果不能够恢复
         * (比如数据库服务停止、网络中断等等,这样
         * 的异常一般称之为系统异常),则提示用户
         * 稍后重试。如果能够恢复,则立即恢复。
         */
        out.println("系统繁忙,稍后重试");
    }finally {
        DBUtils.close(null, stat, conn);
        }
    }
}

2.DAO (扩展)

(1)什么是DAO? (Data Access Object 数据访问对象)

封装了数据访问逻辑的一个对象。

(2)如何写一个DAO?

step1. 写一个实体类。

/**
 * 实体类:
 *   实体类与表的结构要一致,表有哪些字段,对应的
 *   实体类也要有对应的属性(类型要匹配)。
 */
public class User {
private int id;
private String uname;
private String pwd;
private String email;


@Override
public String toString() {
    return "User [id=" + id + ", uname=" + uname + ", pwd=" + pwd + ", email=" + email + "]";
}

public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getUname() {
    return uname;
}
public void setUname(String uname) {
    this.uname = uname;
}
public String getPwd() {
    return pwd;
}
public void setPwd(String pwd) {
    this.pwd = pwd;
}
public String getEmail() {
    return email;
}
public void setEmail(String email) {
    this.email = email;
    }
}

step2.写一个DAO类,提供访问数据库的方法

/**
 *  DAO类:
 *    用于封装数据访问逻辑。
 */
public class UserDAO {

/**
 * 将用户表(t_user)中所有用户信息查询出来。
 * @throws SQLException 
 */
public List<User> findAll() throws SQLException{
    List<User> users = 
            new ArrayList<User>();
    Connection conn = null;
    PreparedStatement stat = null;
    ResultSet rst = null;
    try {
        conn = DBUtils.getConn();
        stat = conn.prepareStatement(
            "SELECT * FROM t_user");
        rst = stat.executeQuery();
        while(rst.next()) {
            int id = rst.getInt("id");
            String uname = 
                    rst.getString("username");
            String pwd = 
                    rst.getString("password");
            String email = 
                    rst.getString("email");

            User user = new User();
            user.setId(id);
            user.setUname(uname);
            user.setPwd(pwd);
            user.setEmail(email);

            users.add(user);
        }
    } catch (SQLException e) {
        e.printStackTrace();
        throw e;
    } finally {
        DBUtils.close(rst, stat, conn);
    }
    return users;
    }
}

(3)DAO的优点

1)DAO封装了数据访问逻辑,调用者不用关心底层数据库访问逻辑是如何实现的,方便代码的维护。

比如说,数据访问逻辑发生了改变(从jdbc变成了mybatis),对调用
者没有任何影响。

2)方便测试。

比如说,将数据访问逻辑写在DAO里面,可以直接测试。如果
将数据访问逻辑写在Servlet里面,就需要部署整个应用才能测试。

练习

写一个Servlet(ListUserServlet)以表格的形式返回所有用户的信息。

http://localhost:8080/servlet03/list

提示:

step1.将所有用户信息查询出来

String sql = "SELECT * FROM t_user";
....
Result rst = ...

step2.依据查询到的用户信息,生成表格

out.println("<table border='1' width='60%'>");
out.println("<tr><td>ID</td><td>用户名</td>...</tr>");
while(rs.next()){
    int id = rs.getInt("id");
    String username = rs.getString("username");
    ..
    out.println("<tr><td>" + id + "</td>...</tr>");
}
out.println("</table>");