Day14

JDBC开发

一。JDBC简介

l数据库驱动
lSUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC
 
JDBC其实就是数据库驱动,只有通过驱动才能取到数据,由于数据库有很多种,为了避免应用程序直接访问数据库儿产生一些不同的数据驱动,SUN公司定义了一套操作数据库的驱动JDBC,JDBC中定义了很多接口,然后由数据驱动厂商去实现这些接口,而我们在编写应用程序时只需要实现JDBC接口就可以连接数据库了
也就是说我们在写应用程序的时候必须加载相应的数据库驱动,实现JDBC的接口,从而才可以操作数据库
 
JDBC全称为:Java Data Base Connectivityjava数据库连接),它主要由接口组成。
组成JDBC的2个包:
 java.sql
 javax.sql
开发JDBC应用需要以上2个包的支持外,还需要导入相应JDBC的数据库实现(即数据库驱动)
 
值得注意的是java.sql和javax.sql这两个包以及纳入到j2se的范畴了,所以在MyEclipse中建立项目时可不导入这两个包,但是我们还必须导入数据库驱动mysql-connector-java-5.0.8-bin.jar
 
(1.1)第一个JDBC程序
 

现在我们有一张表,以前我们都是在命令行中操作数据库,但是现在我们可以从JDBC中去炒作数据库了

我们先在命令行中创建这个表

 

查看一下

 

现在我们在通过JDBC创建

我们在MyEclipse中要连接数据库可以建立web工程也可以建立java工程,如果涉及到要将数据库中的数据显示在web页面则可以使用web工程

(1)建立java工程,建立lib文件,导入数据库驱动包,然后将驱动包加到构建路劲去(变成奶瓶)

(2)加载数据库驱动

在JDK中有一个DriverManager的类有registerDriver(Driver driver)这个方法可以加载数据库驱动,而JDBC的数据库驱动在数据库驱动包中的com.mysql.jdbc中的Driver.class

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

 

(3)获取mysql的连接

DriverManager类有静态方法getConnection方法连接数据库,返回的是一个连接Connection

Connection conn = DriverManager.getConnection(url,user,password);    //连接数据库,指定要连接的那个数据库,以及数据库的用户名和密码

 

(4)操作数据库(有了连接Connection之后就可以用连接操作数据库了)

 (4.1)创建一个statement对象将SQL语句发送到数据库

  Statement st = conn.createStatement();      //创建一个statement对象

 (4.2)向数据库发送SQL语句

  //String sql = "select * from users";    //我们在开发中写SQL语句的时候不要用*,要明确写出列名,便于将来的维护

  String sql = "selecect id,name,password,email,birthday from users";

  ResultSet rs = st.executeQuery(sql);            //向数据库中发sql语句,返回一个ResultSet结果集

  (4.3)将结果集中的数据取出来显示

  在ResultSet中保存的数据就想命令行中保存数据的格式一样,在表中默认指针是指在第一行的,我们想取出数据就必须要控制指针

在结果集ResultSet这个类中有一个方法next(),只要调用这个方法指针就会移动一次,另外所有存在表中的数据都是Object,所以可以用getObject(“xxx”)获取某列的数据

  while(rs.next()){

  System.out.println("id="+rs.getObject("id"));

  System.out.println("name="+rs.getObject("name"));

  System.out.println("password="+rs.getObject("password"));

  System.out.println("email="+rs.getObject("email"));

  System.out.println("birthday="+rs.getObject("birthday"));

}

(5)释放资源(特别重要)

数据库连接数是有限的,所以用完数据库就必须释放资源,我们在释放资源的时候除了要把链接还给数据库之外,还会降链接和数据库产生的交互(比如产生的Statement,以及返回来的结果集ResultSet)也释放掉,这是为了释放内存,并且这里释放的时候需要遵守一些顺序,倒着释放,先释放结果集ResultSet,然后在释放产生的Statement,最后在把链接还给数据库

rs.close();    //释放结果集

st.close();    //释放statement

conn.close();    //把链接还给数据库,释放连接

package cn.itcast.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo1 {

    public static void main(String[] args) throws SQLException {

        String url = "jdbc:mysql://localhost:3306/day14";        //关于数据库的写法之后再说
        String username = "root";
        String password = "root";
        
        //1.加载驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        
        //2.获取链接
        Connection conn = DriverManager.getConnection(url, username, password);
        
        //3.获取向数据库发送sql语句的statement
        Statement st = conn.createStatement();
        
        //4.向数据库发送sql,得到结果集
        String sql = "select id,name,password,email,birthday from users";
        ResultSet  rs = st.executeQuery(sql);
        
        //5.取出数据显示
        while(rs.next()){
            System.out.println("id=" + rs.getObject("id"));
            System.out.println("name=" + rs.getObject("name"));
            System.out.println("password=" + rs.getObject("password"));
            System.out.println("email=" + rs.getObject("email"));
            System.out.println("birthday=" + rs.getObject("birthday"));
        }
        
        //6.释放资源
        rs.close();
        st.close();
        conn.close();
    }
}

 

以上是就是Mysql数据库操作的流程

——————————————————————————————————————————————————————————

(1.2)程序详解—DriverManager

Jdbc程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:
•DriverManager.registerDriver(new Driver())
•DriverManager.getConnection(url, user, password),
registerDriver(Driver driver)    这个方法是注册一个驱动
deregisterDriver(Driver driver)    这个是删除一个驱动
getConnection(String url)
getConnection(String url,Properties info)
getConnection(String url,String user,String password)  这三个方法是连接数据库的
getDriver(String url)        可以通过给定url指定驱动地址,这个方法说明可以给定多个驱动,只通过url就可以指定需要哪个驱动
 
 
 
注意:在实际开发中并不推荐采用registerDriver方法注册驱动。原因有二:

一、查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象。

二、程序依赖mysqlapi,脱离mysqljar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。
也就是说用registerDriver加载驱动,如果已经指定了mysql的驱动包的话,在以后做更改驱动包(比如要换成Oracal驱动包)就会比较麻烦,因为这里已经指定了mysql驱动包,就会很依赖mysql的api,做更改的话就会牵一发而动全身,第二个就是采用这种方式会在内存中有两个Driver对象,因为用这种方式,首先要new com.mysql.jdbc.Driver(),而在new之前会去加载这个类从而去执行源码中的静态方法
,这个静态方法也new Driver(),然后加载到DriverManager中,从而在内存中有两个Driver
 
•推荐方式:Class.forName(“com.mysql.jdbc.Driver”);
采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高,这种方式即使你把msql的jar包移除,都不会报错的 
这种方法来源于MySql 5.1参考文档
 
 
l同样,在开发中也不建议采用具体的驱动类型指向getConnection方法返回的connection对象。
其实DriverManager.getConnection(url,username,password)中的DriverManager并不是直接调用getConnetion方法,儿时调换用Driver中的方法去调用这个方法
 
 
 
(1.3)数据库URL
URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,
URL的写法为:jdbc:mysql:[]//localhost:3306/test ?参数名:参数值
 
常用的参数名和参数值通常会是以下几种
常用属性:useUnicode=true&characterEncoding=UTF-8      //加上这个可以保证得到的连接Connection的字符集是UTF-8
 
写完整就是:String url = "jdbc:mysql://localhost:3306/day14?useUnicode=true&characterEncoding=UTF-8"
//当然url地址后面还可以跟一些参数,(比如数据库的用户密码也可以),这个在Mysql手册中有详细的解说
 
所以在获取连接的时候,我们将数据库用户和密码写到url里面,在获取连接的方法中只传入一个url就可以了,不用床数据库的用户名和密码
String url = "jdbc:mysql:///day14?user=root&password=root";    //将数据库的用户名和密码在url中传入
Connection conn = DriverManager.getConnection(url);      //这里就不需要再传入数据库的用户名和密码了
 
在url后面到底能够跟多少参数这个可以在MySQL文档中这个地方查找到,但常用的还是那么几个
 
常用数据库URL地址的写法:
•Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
•SqlServer—jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
•MySql—jdbc:mysql://localhost:3306/sid
Mysql的url地址的简写形式: jdbc:mysql:///sid  //如果连接的是localhost,并且默认的端口是3306则可以用“/”代替,就可以简写成这个样子。
注意一点,无论跟多少自协议,最后一个冒号绝对不能少,否则会出错
package cn.itcast.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import cn.itcast.domain.User;
public class Demo2 {
    /**
     * jdbc入门案例
     * @throws SQLException 
     * @throws ClassNotFoundException 
     */
    public static void main(String[] args) throws SQLException, ClassNotFoundException {

        String url = "jdbc:mysql:///day14?user=root&password=root";  //http://
        String username = "root";
        String password = "root";
        
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        
        //2.获取链接
        Connection conn = DriverManager.getConnection(url);
        
        //3.获取向数据库发送sql语句的statement
        Statement st = conn.createStatement();
        
        //4.向数据库发送sql,得到结果集
        String sql = "select id,name,password,email,birthday from users";
        boolean b = st.execute(sql);
        
        if(b){
            ResultSet rs = st.getResultSet();
            List list = new ArrayList();
            //5.取出数据显示
            while(rs.next()){
                User user = new User();
                user.setBirthday(rs.getDate(5));
                user.setEmail(rs.getString("email"));
                user.setId(rs.getInt("id"));
                user.setPassword(rs.getString("password"));
                user.setName(rs.getString("name"));
                list.add(user);
            }
            
            //6.释放资源
            rs.close();
            st.close();
            conn.close();
        }
        
    }
}

——————————————————————————————————————————————————————————

(1.4)程序详解—Connection
Jdbc程序中的Connection,它用于代表数据库的链接,Connection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法:
•createStatement():创建向数据库发送sql的statement对象。
•prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。    //关于什么是预编译以后会细讲
•prepareCall(sql):创建执行存储过程的callableStatement对象。            //关于什么是存储过程以后会细讲
•setAutoCommit(boolean autoCommit):设置事务是否自动提交。           //关于什么是事务以后会细讲
•commit() :在链接上提交事务。
•rollback() :在此链接上回滚事务。
 
 
(1)程序详解—Statement
这个方法主要用于创建一个statement对象将SQL语句发送到数据库
Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:
•executeQuery(String sql) :用于向数据发送查询语句。
•executeUpdate(String sql):用于向数据库发送insert、update或delete语句
•execute(String sql):用于向数据库发送任意sql语句
•addBatch(String sql) :把多条sql语句放到一个批处理中。
•executeBatch():向数据库发送一批sql语句执行。
 
这个方法可以向数据库发送一条查询语句,返回的是结果集
 
 
这个方法可以执行任何SQL语句,但是返回的是boolean,需要单独获取结果集
单独获取结果集的方法
 
 
excuteUpdate方法向数据库发送增删改语句,返回的是int,int表示影响了多少行,通过返回值可以判断这个返回方法有没有成功
 
综上不同语句对应不同的方法,查询用executeQuery,增删改用executeUpdate,如果用execute方法就必须单独获取结果集
代码如下
package cn.itcast.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import cn.itcast.domain.User;
public class Demo2 {
    /**
     * jdbc入门案例
     * @throws SQLException 
     * @throws ClassNotFoundException 
     */
    public static void main(String[] args) throws SQLException, ClassNotFoundException {

        String url = "jdbc:mysql:///day14?user=root&password=wyszxqy5378428";  //http://
        String username = "root";
        String password = "root";
        
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        
        //2.获取链接
        Connection conn = DriverManager.getConnection(url);
        
        //3.获取向数据库发送sql语句的statement
        Statement st = conn.createStatement();
        
        //4.向数据库发送sql,得到结果集
        String sql = "select id,name,password,email,birthday from users";
        boolean b = st.execute(sql);
        
        if(b){
            ResultSet rs = st.getResultSet();
            List list = new ArrayList();
            //5.取出数据显示

        while(rs.next()){
          System.out.println("id=" + rs.getObject("id"));
          System.out.println("name=" + rs.getObject("name"));
          System.out.println("password=" + rs.getObject("password"));
          System.out.println("email=" + rs.getObject("email"));
          System.out.println("birthday=" + rs.getObject("birthday"));
          }

//6.释放资源
            rs.close();
            st.close();
            conn.close();
        }
        
    }
}

综上调用execute这种方法比较麻烦,调用executeQuery这个方法可以直接返回结果集,这个方法就比较方便,建议查询的时候用executeQuery方法,增删改用executeUpdate方法

 

addBatch(String sql),这个是一个批处理命令,可以将多条sql语句放到一个批处理中,其实这个statement对象内部就有一个list集合

当你加多条sql语句到一个批处理中去的时候,就会将这些语句放到list集合中去

executeBatch(),这个方法向数据库发送一批sql语句执行,这个方法以后会细讲

 

(2)程序详解—ResultSet

Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。
ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:
•获取任意类型的数据
•getObject(int index)
•getObject(string columnName)
•获取指定类型的数据,例如:
•getString(int index)
•getString(String columnName)
•提问:数据库中列的类型是varchar,获取该列的数据调用什么方法?Int类型呢?bigInt类型呢?Boolean类型?
 
 
但是通过getObject(String columnName)这种方法获取到的数据需要强转,因为我们取到数据通常都是
保存到javabain里面去的,强转数据很麻烦的,所以在结果集ResultSet这个类中提供了很多取结果的方法
这些方法都是获取对应数据类型的方法,而且每一种数据获取方法都有两种获取方法,一是根据字符串名,一是
根据类的索引号,这样就可以避免强转,可以直接取到数据,这里取数据的时候要更具表中的类型选择不同的获取
方法,这个又有些麻烦的。这里要特别注意,下面提供一张常用数据类型转换表,可以根据这个来选方法
还有获取钱getBigDecimal,返回BigDecimal,在这个类中有转换成其它数据类型的方法
 
还有点要注意,这里的getDate方法获取到的数据时java.sql.Date,我们需要的却是java.util.Date的数据,这里之所以不报错
是应为java.sql.Date是java.util.Date的子类
 
 
ResultSet还提供了对结果集进行滚动的方法:
•next():移动到下一行
•Previous():移动到前一行
•absolute(int row):移动到指定行,定位到指定行
•beforeFirst():移动resultSet的最前面。
•afterLast() :移动到resultSet的最后面。
 
比如下面这段代码就是一个死循环
下面这个代码是指定取到第二行的数据
下面这段代码会抛异常,因为指针又回到的表头了,没有数据可取
下面这段代码也会报错,因为指针到了表尾巴去了,没有数据可取
这个afterLast()方法很有用的,在不知道表有多少行时,可以执行下面这段代码可以根据id知道这个表有多少行
 
 
(3)程序详解—释放资源
Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, StatementConnection对象。
特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
一定要注意哈,释放资源是很重要的,不然你的网站在发布以后的几天内就可能访问不了数据,这就是释放资源失败导致的
package cn.itcast.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo3 {
    /**
     * resultset的滚动结果集
     * @throws SQLException 
     */
    public static void main(String[] args) throws SQLException {

        String url = "jdbc:mysql://localhost:3306/day14";
        String username = "root";
        String password = "root";
        
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Connection conn = null;
        Statement st = null;
        ResultSet  rs  = null;
        try{            //这个内部的代码完全有可能抛异常,抛异常之后资源就不会关闭了,所以要用try...finally,无论抛不抛异常都得关闭资源
            conn = DriverManager.getConnection(url, username, password);
            st = conn.createStatement();
            String sql = "select id,name,password,email,birthday from users";
            rs = st.executeQuery(sql);
            rs.afterLast();
            rs.previous();
            System.out.println("id=" + rs.getObject("id"));
            System.out.println("name=" + rs.getObject("name"));
            System.out.println("password=" + rs.getObject("password"));
            System.out.println("email=" + rs.getObject("email"));
            System.out.println("birthday=" + rs.getObject("birthday"));
        }finally{
            try{
                if(rs!=null)             //判断一下是否为空,减少报空指针的异常
                    rs.close();
            }catch (Exception e) {
                e.printStackTrace();
                rs=null;                //为了以防万一,将它置为空,让垃圾回收机制去清理,这个是MySQL文档中的写法
            }
            try{
                if(st!=null) st.close();
            }catch (Exception e) {
                e.printStackTrace();
                st=null;
            }
            try{
                if(conn!=null) conn.close();
            }catch (Exception e) {
                e.printStackTrace();
                conn=null;
            }
            /*第二种释放资源的方法
            try{
                if(rs!=null){
                    rs.close();
                }
            }catch (Exception e) {
                try{
                    if(st!=null){
                        st.close();
                    }
                }catch (Exception e1) {
                    try{
                        if(conn!=null){
                            conn.close();
                        }
                    }catch (Exception e2) {
                        e.printStackTrace();
                    }
                }
            }
            */
        }
    }
}

 

最后来一个面试题,finally里面的代码一定会执行吗
package cn.itcast.demo;

public class Demo4 {

    public static void main(String[] args) {

        try{
            //return        会执行finally里面的内容
            System.exit(0);            //退出java虚拟机就不会执行finally里面的内容
        }catch (Exception e) {
        }finally{
            System.out.println("haha");
        }
        
    }

}

 

 
(4)使用JDBC对数据库进行CRUD
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。
练习:编写程序对User表进行增删改查操作。
练习:编写工具类简化CRUD操作。(异常暂不处理)
(4.1)CRUD操作-create
使用executeUpdate(String sql)方法完成数据添加操作,示例操作:
(4.2)CRUD操作-updata
使用executeUpdate(String sql)方法完成数据修改操作,示例操作:
 
(4.3)CRUD操作-delete
l使用executeUpdate(String sql)方法完成数据删除操作,示例操作:
 
(4.4)CRUD操作-read
使用executeQuery(String sql)方法完成数据查询操作,示例操作:
 
 
 
注意事项:通常在写数据库的增删改查的时候,都有重复的代码,比如加载数据库驱动,获取连接,以及释放资源都是重复的,所以我可以
将这些放在一个工具类中,还要注意一点在工具类中加载数据库驱动必须放在静态代码快中,不然不同的操作去调用工具类时就会在内存中产生多个Driver对象
package cn.itcast.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtils {

    private static String url;
    private static String username;
    private static String password;
    private static String driver;
    //对于以上的配置,为了以后便于更改数据库类型,最好是放在配置文件里边
    //还有一点,对于配置文件,如果配置的数据具有层次关系就用xml,没有层次关系就用properties
    //配置文件只获取一次,所以还是在静态代码块中获取
    static{                    //静态代码块中的异常不能抛,只能try...catch
        try {
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");        //加载配置文件,这个都是模板代码,记住就可以了
            Properties prop = new Properties();
            prop.load(in);
            
            url = prop.getProperty("url");
            username = prop.getProperty("username");
            password = prop.getProperty("password");
            driver = prop.getProperty("driver");
            
            Class.forName(driver);
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);        //如果数据库驱动没有加载成功则报错误,而非异常
        }
    }
    
    //加载驱动,获取链接
    public static Connection getConnection() throws SQLException{
        Connection conn = DriverManager.getConnection(url,username,password);
        return conn;
    }
    
    //释放资源
    public static void release(Connection conn,Statement st,ResultSet rs){    //注意再导入包的时候一定要针对接口导,这样在以后切换底层时就不用那么麻烦了,也就是说导入ResultSet一定要导入java.sql的包,不要导入com.mysql.jdbc的包,因为将来有可能到切换成其它数据库
        try{
            if(rs!=null) 
                rs.close();
        }catch (Exception e) {
            e.printStackTrace();
            rs=null;
        }
        try{
            if(st!=null) st.close();
        }catch (Exception e) {
            e.printStackTrace();
            st=null;
        }
        try{
            if(conn!=null) conn.close();
        }catch (Exception e) {
            e.printStackTrace();
            conn=null;
        }
        
    }
    
}

 

 
package cn.itcast.demo;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import cn.itcast.domain.User;
import cn.itcast.utils.JdbcUtils;

public class Demo5 {

    @Test
    public void insert(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "insert into users(id,name,password,email,birthday) values(4,'ddd','123','dd@sina.com','1980-09-09')";
            int num = st.executeUpdate(sql);
            if(num>0){        //num如果大于0表示插入数据成功
                System.out.println("插入成功");
            }
            
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    @Test
    public void update(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "update users set name='zzs',email='zss@sina.com' where id=1";        //注意呀在修改数据库的时候一定要先写where,不然最后死的心情都有了
            int num = st.executeUpdate(sql);
            if(num>0){
                System.out.println("修改成功");
            }
            
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    @Test
    public void delete(){
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "delete from users where id=4";            //还是那句话,在删除修改数据时一定要加限定where,不然结果很惨的
            int num = st.executeUpdate(sql);
            if(num>0){
                System.out.println("删除成功");
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    @Test
    public User find(){            //这个方法有返回值,不能直接test,可以在TestDemo5中断点测试
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "select * from users where id=1";
            rs = st.executeQuery(sql);        //这个时候只查询的是id=1的记录
            if(rs.next()){  //如果rs中没有数据,则这里返回false
                User user = new User();
                user.setBirthday(rs.getDate("birthday"));
                user.setEmail(rs.getString("email"));
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setPassword(rs.getString("password"));
                return user;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
        return null;            //注意,这个返回值是由于有异常e.printStackTrace()时的返回值
    }
    
    public List getAll(){            //这个方法也在TestDemo5中断点测试
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "select * from users";
            rs = st.executeQuery(sql);
            List list = new ArrayList();
            while(rs.next()){  //false
                User user = new User();
                user.setBirthday(rs.getDate("birthday"));
                user.setEmail(rs.getString("email"));
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setPassword(rs.getString("password"));
                list.add(user);
            }
            return list;
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
        return null;            //注意,这个返回值是由于有异常e.printStackTrace()时的返回值
    }
    
}

 

 
package cn.itcast.demo;

import java.util.List;

import org.junit.Test;

import cn.itcast.domain.User;

public class TestDemo5 {
    
    
    @Test
    public void testFind(){
        User user = new Demo5().find();
        System.out.println(user);
    }
    
    @Test
    public void testGetAll(){
        List list= new Demo5().getAll();
        System.out.println(list);
    }
}

 

(5)实例练习—用户注册和登陆
改写前面讲解的用户注册和登陆案例,实现如下需求:

1、把xml换成数据库,重写UserDao

2、定义DAO接口,并定义Dao工厂,实现service层和dao层的解耦。

3、自定义dao异常。

4、防范sql注入攻击

SQL 注入是用户利用某些系统没有对输入数据进行充分的检查,从而进行恶意破坏的行为。

1statement存在sql注入攻击问题,例如登陆用户名采用' or 1=1 or username=‘

2、对于防范 SQL 注入,可以采用PreparedStatement取代Statement

 
(5.1)先在数据库中创建好库和表,复制工具类和数据库驱动
代码如下

create database day14_user;
use day14_user;
create table users
(
id varchar(40) primary key,
username varchar(40) not null unique,
password varchar(40) not null,
email varchar(100) not null unique,
birthday date,
nickname varchar(100)
);

 
导入数据库驱动就是将/day14/lib/mysql-connector-java-5.0.8-bin.jar中的这个包复制到/day14_user/WebRoot/WEB-INF/lib/mysql-connector-java-5.0.8-bin.jar
 
复制配置文件db.properties到项目去
复制工具类到工具文件
 
(5.2)原来是用的xml作为数据库,现在用jdbc连接数据库,以前的web层和server层不用改变,改变的只是dao层
其实这里还是改了一点server层的数据,要想不改server层的数据之后会讲到该如何处理
package cn.itcast.dao.impl;

import java.sql.Connection;                //注意这些导入的包一定要基于squall接口导入,这样在将来切换底层数据库时候才会很方便
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.DateFormat;

import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;

public class UserDaoJdbcImpl implements UserDao {

    public void add(User user) {
        
        /*
         * id varchar(40) primary key,
        username varchar(40) not null unique,
        password varchar(40) not null,
        email varchar(100) not null unique,
        birthday date,
        nickname varchar(100)
         */
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            //以前的写法
            //String sql = "insert into users(id,username,password,email,birthday,nickname) values('"+user.getId()+"','"+user.getUsername()+"','"+user.getPassword()+"','"+user.getEmail()+"','"+user.getBirthday().toLocaleString()+"','"+user.getNickname()+"')";
            String sql = "insert into users(id,username,password,email,birthday,nickname) values(?,?,?,?,?,?)";
            st = conn.prepareStatement(sql);
            st.setString(1, user.getId());
            st.setString(2, user.getUsername());
            st.setString(3, user.getPassword());
            st.setString(4, user.getEmail());
            st.setDate(5, new java.sql.Date(user.getBirthday().getTime()));  //util--sql
            st.setString(6, user.getNickname());
            st.executeUpdate();
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    //username = ' or 1=1 or username=‘
    /*public User find(String username, String password) {
        
        Connection conn = null;
        Statement st = null;  //PreparedStatement
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "select * from users where username='"+username+"' and password='"+password+"'";
            System.out.println(sql);
            rs = st.executeQuery(sql);
            if(rs.next()){
                User user = new User();
                user.setBirthday(rs.getDate("birthday"));
                user.setEmail(rs.getString("email"));
                user.setId(rs.getString("id"));
                user.setNickname(rs.getString("nickname"));
                user.setPassword(password);
                user.setUsername(username);
                return user;
            }
            return null;
        }catch (Exception e) {
            throw new RuntimeException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }*/
    
    /*
     * statement和preparedStatement的区别
     * 1.preparedStatement是statement的孩子。
     * 2.preparedStatement可以预防sql注入的问题
     * 3.preparedStatement向数据库发送的是预编译后的sql,数据库的执行效率更高
     * 
     */
    
    public User find(String username, String password) {
        Connection conn = null;
        PreparedStatement st = null;  //PreparedStatement
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where username=? and password=?";
            
            st = conn.prepareStatement(sql);
            st.setString(1, username);  // ' or 1=1 or username='
            st.setString(2, password);
            rs = st.executeQuery();  //预编译的sql
            if(rs.next()){
                User user = new User();
                user.setBirthday(rs.getDate("birthday"));
                user.setEmail(rs.getString("email"));
                user.setId(rs.getString("id"));
                user.setNickname(rs.getString("nickname"));
                user.setPassword(password);
                user.setUsername(username);
                return user;
            }
            return null;
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }


    public boolean existUser(String username) {
        
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where username=?";
            st = conn.prepareStatement(sql);
            st.setString(1, username);
            
            rs = st.executeQuery();
            if(rs.next()){
                return true;
            }
            return false;
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }

    
}

 

上面我们项目中我们虽然说只改动dao层,但是实际上还是改动了一下server层的数据,要彻底不改变server层的数据就要建立工厂类,
工厂类根据配置文件中的配置需要哪个dao就用哪个dao的文件,另外注意工厂类必须用单例去写,这样生产的dao才是唯一的一个
还有点就是在读取配置文件的时候只读取一遍,所以将读取配置文件放在静态代码块或者单例的方法里
 
package cn.itcast.utils;

import java.io.InputStream;
import java.util.Properties;

import cn.itcast.dao.UserDao;

//负责产生dao    //这个需要用单例来写,保证生产的dao出自同一个工厂
public class DaoFactory {    

    private DaoFactory(){}
    private static DaoFactory instance = new DaoFactory();
    private static UserDao userDao = null;
    
    public static DaoFactory getInstance(){
        try{                                    //读取dao的配置文件也只读取一次,所以在getInstance()方法中读取
            InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
            Properties prop = new Properties();
            prop.load(in);
            String daoClassName = prop.getProperty("UserDao");
            userDao = (UserDao) Class.forName(daoClassName).newInstance();
        }catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
        return instance;
    }
    
    public UserDao createUserDao(){
        return userDao;
    }
}

 

导入dao时直接就不用改动这里了,只需要改动配置文件即可,这样severv层完全不受dao层之间的耦合性大大降低了,为将来的底层数据库切换做了准备,当我改动dao.properties中的配置文件时,可以在UserDaoXmlImpl和UserDaoJdbcImpl中切换,就可以将数据存储到不同的
数据库中去了,当改为UserDaoXmlImpl则会将数据保存到服务器中对应的web应用的users.xml中,当我改成UserDaoJdbcImpl时则会将数据保存都MySQL获取Oracal中去
 
还有一点在选择数据库的时候也可以根据配置文件Db.properties去查询数据库。
Oracal的数据库驱动在这个地方
ojdbc14.jar--->oracle.jdbc.driver-->OracleDriver.class
 用的时候导入oracle.jdbc.driver.OracleDriver
还有,在用Oracal时还要启动它的服务,用来比较麻烦
 
 总之一句话,在没有学习spring之前,向要将几个层解耦,就必须用工程模式,接口以及配置文件去解耦
 
 
5.3防范sql注入攻击
 SQL 注入是用户利用某些系统没有对输入数据进行充分的检查,从而进行恶意破坏的行为

1statement存在sql注入攻击问题,例如登陆用户名采用' or 1=1 or username=‘

2、对于防范 SQL 注入,可以采用PreparedStatement取代Statement

 

在用户名中输入的' or 1=1 or username=‘,最终会在find(String username,String password)方法中去找这个用户名和密码

由于在find中查找时根据sql语句去查找的,会将传过来的用户名和密码放在sql语句中去找

结果就会拼成这样一条查询语句:select * from users where username='' or 1=1 or username='' and password=''

实际上这条语句就是select * from users where true;

要解决这个问题有两种方法,第一种是在数据提交给Sverlet需要验证数据是否合法,第二种方法用PreparedStatement替换掉statement

 

 

6.PreparedStatement

PreperedStatement是Statement的孩子,它的实例对象可以通过调用Connection.preparedStatement()方法获得,相对于Statement对象而言:
•PreperedStatement可以避免SQL注入的问题。
•Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
•并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
以下是PreperedStatement的说明:
 
如果传递进来的是sql语句,这个PreparedStatement会自动将sql语句转译,从而阻止了SQL注入,并且这种方法避免了那种字符串拼凑的做法,直接用?代替
数据,然后在将数据传入,这种写法简洁很多,还有哇,PrepareStatement在发送的sql语句的时候,发送的是预编译的sql语句
什么叫预编译sql语句?在数据库中写一句SQL语句,其实数据库还需要编译一下才会执行这条语句的,实际上执行的是编译后的sql语句,就像java类一样,需要先编译成一个class文件,java虚拟机才执行class文件。由于发送的是预编译的SQL语句,所以对数据库的压力就小一些,试想有成千上万条SQL语句如果没有经过预编译就发给数据库,数据库的压力会是很大的。

* statement和preparedStatement的区别
* 1.preparedStatement是statement的孩子。
* 2.preparedStatement可以预防sql注入的问题
* 3.preparedStatement向数据库发送的是预编译后的sql,数据库的执行效率更高

综上所述:PrepareStatement有三个好处:一,防止SQL注入,二,写法相对Statement简洁,三,PrepareStatement发送的是预编译的SQL语句,减少了服务器的压力,这个是一个面试题
package cn.itcast.dao.impl;

import java.sql.Connection;                //注意这些导入的包一定要基于squall接口导入,这样在将来切换底层数据库时候才会很方便
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.DateFormat;

import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;

public class UserDaoJdbcImpl implements UserDao {

    public void add(User user) {
        
        /*
         * id varchar(40) primary key,
        username varchar(40) not null unique,
        password varchar(40) not null,
        email varchar(100) not null unique,
        birthday date,
        nickname varchar(100)
         */
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            //以前的写法
            //st = conn.createStatement();
            
            //String birthday = DateFormat.getDateInstnce(DateFormat.MEDIUM).format(user.getBirthday());        //国际化
            //String sql = "insert into users(id,username,password,email,birthday,nickname) values('"+user.getId()+"','"+user.getUsername()+"','"+user.getPassword()+"','"+user.getEmail()+"','"+user.getBirthday().toLocaleString()+"','"+user.getNickname()+"')";
            String sql = "insert into users(id,username,password,email,birthday,nickname) values(?,?,?,?,?,?)";
            st = conn.prepareStatement(sql);
            st.setString(1, user.getId());
            st.setString(2, user.getUsername());
            st.setString(3, user.getPassword());
            st.setString(4, user.getEmail());
            //注意这里需要的Date是一个属于sql,需要将util的Date转化成sql的Date
            st.setDate(5, new java.sql.Date(user.getBirthday().getTime()));  //util--sql
            st.setString(6, user.getNickname());
            st.executeUpdate();        //注意,这里就不要再传sql了
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    //username = ' or 1=1 or username=‘
    /*public User find(String username, String password) {
        
        Connection conn = null;
        Statement st = null;  //PreparedStatement
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "select * from users where username='"+username+"' and password='"+password+"'";
            System.out.println(sql);
            rs = st.executeQuery(sql);
            if(rs.next()){
                User user = new User();
                user.setBirthday(rs.getDate("birthday"));
                user.setEmail(rs.getString("email"));
                user.setId(rs.getString("id"));
                user.setNickname(rs.getString("nickname"));
                user.setPassword(password);
                user.setUsername(username);
                return user;
            }
            return null;
        }catch (Exception e) {
            throw new RuntimeException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }*/
    
    /*
     * statement和preparedStatement的区别
     * 1.preparedStatement是statement的孩子。
     * 2.preparedStatement可以预防sql注入的问题
     * 3.preparedStatement向数据库发送的是预编译后的sql,数据库的执行效率更高
     * 
     */
    //以下这个方法采用PrepareStatemnent可以防止SQL注入
    public User find(String username, String password) {
        Connection conn = null;
        PreparedStatement st = null;  //PreparedStatement
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where username=? and password=?";
            
            st = conn.prepareStatement(sql);
            st.setString(1, username);  // ' or 1=1 or username='
            st.setString(2, password);
            rs = st.executeQuery();  //预编译的sql
            if(rs.next()){
                User user = new User();
                user.setBirthday(rs.getDate("birthday"));
                user.setEmail(rs.getString("email"));
                user.setId(rs.getString("id"));
                user.setNickname(rs.getString("nickname"));
                user.setPassword(password);
                user.setUsername(username);
                return user;
            }
            return null;
        }catch (Exception e) {
            throw new DaoException(e);        //dao层应该抛自己层的异常,也就是说MVC每层都应该设立自己独立的异常处理类,这样在出问题后便于查找
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }


    public boolean existUser(String username) {
        
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where username=?";
            st = conn.prepareStatement(sql);
            st.setString(1, username);
            
            rs = st.executeQuery();
            if(rs.next()){
                return true;
            }
            return false;
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }

    
}

 

6.1自定义dao异常。
对于MVC模式,每一层都应该有自己的处理异常的类,这样在出问题的时候可以快速的找到错误出处,所在我们这里也应该在异常包中写上dao层的异常处理类
package cn.itcast.exception;

public class DaoException extends RuntimeException {

    public DaoException() {
        // TODO Auto-generated constructor stub
    }

    public DaoException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }

    public DaoException(Throwable cause) {
        super(cause);
        // TODO Auto-generated constructor stub
    }

    public DaoException(String message, Throwable cause) {
        super(message, cause);
        // TODO Auto-generated constructor stub
    }

}

 

 ____________________________________________________________________________________________________________________________
7.JDBC综合练习-客户管理

创立如下数据库表customer,并完成web下的crud操作,这个是一个客户管理系统

 

 

步骤:

第一步:搭建开发环境

1.1导入开发包

Mysql数据库驱动

web层需要beanUtils开发包和jstl开发包

1.2创建组织程序的包

这里只做dao层的接口解耦,web层和service层不做接口解耦

cn.itcast.domain

cn.itcast.dao

cn.itcast.dao.impl

cn.itcast.service

cn.itcast.web.controller

cn.itcast.web.UI

然后是工具类和异常类

cn.itcast.utils

cn.itcast.exception

还有在web-inf目录中创建一个jsp目录,保存网站页面

1.3创建项目使用的库和表

create database day14_customer character set utf8 collate utf8_general_ci;

use day14_customer;

create table customer

(

id varchar(40) primary key,

name varchar(20) not null,

gender varchar(4) not null,

birthday date,

cellphone varchar(40) not null,

email varchar(100),

preference varchar(100),    //爱好有很多种,爱好应该单独做成一张表,客户和爱好是多对多的关系,一个客户有多个爱好,一个爱好可能对应多个客户,但是今天不搞那么复杂

type varchar(40),    //客户的类型也应该设立单独的表,用户和客户类型是多对一的关系,多个用户对应一个客户类型,这里也不搞复杂了

description varchar(255)

);

1.4创建工程需要的一些常用工具类

JdbcUtils ,WebUtils, DaoException

JdbcUtils可以直接复制day14的,WebUtils用产生UUID等等,DaoExceptiion是包dao层的异常的

 

第二步:开发

2.1先开发实体,不管web层还是service层还是dao层都是基于实体传输数据的,所以先开发实体层

  创建一个保存Customer的实体

package cn.itcast.domain;

import java.util.Date;

public class Customer {
    private String id;
    private String name;
    private String gender;
    private Date birthday;
    private String cellphone;
    private String email;
    private String preference;
    private String type;
    private String description;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getCellphone() {
        return cellphone;
    }
    public void setCellphone(String cellphone) {
        this.cellphone = cellphone;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPreference() {
        return preference;
    }
    public void setPreference(String preference) {
        this.preference = preference;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }   
}

 

2.2开发dao层

dao层先可以先做dao层的实现,在通过抽取dao层作接口,然后重构移动到dao包中去,dao层一般要有5个方法增删改查以及获取所有数据这5个方法

package cn.itcast.dao;

import java.util.List;

import cn.itcast.domain.Customer;
import cn.itcast.domain.QueryResult;

public interface CustomerDao {

    void add(Customer customer);

    void update(Customer customer);

    void delete(String id);

    Customer find(String id);

    public QueryResult pageQuery(int startindex,int pagesize);

}

 

package cn.itcast.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import cn.itcast.dao.CustomerDao;
import cn.itcast.domain.Customer;
import cn.itcast.domain.QueryResult;
import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;

public class CustomerDaoImpl implements CustomerDao {
public void add(Customer customer){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into customer(id,name,gender,birthday,cellphone,email,preference,type,description) values(?,?,?,?,?,?,?,?,?)"; st = conn.prepareStatement(sql); st.setString(1, customer.getId()); st.setString(2, customer.getName()); st.setString(3, customer.getGender()); st.setDate(4, new java.sql.Date(customer.getBirthday().getTime())); //将java.util.Date转换成java.sql.Date st.setString(5, customer.getCellphone()); st.setString(6, customer.getEmail()); st.setString(7, customer.getPreference()); st.setString(8, customer.getType()); st.setString(9, customer.getDescription()); st.executeUpdate(); }catch (Exception e) { throw new DaoException(e); }finally{ JdbcUtils.release(conn, st, rs); } } public void update(Customer customer){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); }catch (Exception e) { throw new DaoException(e); }finally{ JdbcUtils.release(conn, st, rs); } } public void delete(String id){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); }catch (Exception e) { throw new DaoException(e); }finally{ JdbcUtils.release(conn, st, rs); } } public Customer find(String id){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); }catch (Exception e) { throw new DaoException(e); }finally{ JdbcUtils.release(conn, st, rs); } return null; } public List<Customer> getAll(){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "select * from customer"; st = conn.prepareStatement(sql); rs = st.executeQuery(); List list = new ArrayList(); while(rs.next()){ Customer c = new Customer(); c.setBirthday(rs.getDate("birthday")); c.setCellphone(rs.getString("cellphone")); c.setDescription(rs.getString("description")); c.setEmail(rs.getString("email")); c.setGender(rs.getString("gender")); c.setId(rs.getString("id")); c.setName(rs.getString("name")); c.setPreference(rs.getString("preference")); c.setType(rs.getString("type")); list.add(c); } return list; }catch (Exception e) { throw new DaoException(e); }finally{ JdbcUtils.release(conn, st, rs); } } public QueryResult pageQuery(int startindex,int pagesize){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; QueryResult qr = new QueryResult(); try{ conn = JdbcUtils.getConnection(); String sql = "select * from customer limit ?,?"; st = conn.prepareStatement(sql); st.setInt(1, startindex); st.setInt(2, pagesize); rs = st.executeQuery(); List list = new ArrayList(); while(rs.next()){ Customer c = new Customer(); c.setBirthday(rs.getDate("birthday")); c.setCellphone(rs.getString("cellphone")); c.setDescription(rs.getString("description")); c.setEmail(rs.getString("email")); c.setGender(rs.getString("gender")); c.setId(rs.getString("id")); c.setName(rs.getString("name")); c.setPreference(rs.getString("preference")); c.setType(rs.getString("type")); list.add(c); } qr.setList(list); sql = "select count(*) from customer"; st = conn.prepareStatement(sql); rs = st.executeQuery(); if(rs.next()){ qr.setTotalrecord(rs.getInt(1)); } return qr; }catch (Exception e) { throw new DaoException(e); }finally{ JdbcUtils.release(conn, st, rs); } } }

 

2.3开发service层

  service层是和dao层打交道的,所以需要调用dao层,但是注意调用dao类时要用dao接口引用,而且产生dao层也要通过工厂来产生dao层,这样方便以后解耦

所以这里又需要创建dao层,我们这里就没有单独创建工厂包了,就直接在工具包中创建工厂类了,这里还要注意,工厂类一般要作为单例,作为单例是为了保证产生的

所有对象都是由同一个工厂产生的。还有哇在工厂类中要读取配置文件,通过配置文件来说明需要读取哪个dao层,读取配置文件要在单例的构造方法中读取,从而觉得使用哪个数据库

package cn.itcast.utils;

import java.io.InputStream;
import java.util.Properties;
import cn.itcast.dao.CustomerDao;

public class DaoFactory {

    private static CustomerDao dao = null;
    private static DaoFactory instance = new DaoFactory();
    
    private DaoFactory(){
        try{
            InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
            Properties prop = new Properties();
            prop.load(in);
            
            String className = prop.getProperty("CustomerDao");
            dao = (CustomerDao) Class.forName(className).newInstance();
        }catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
    
    public static DaoFactory getInstance(){
        return instance;
    }
    
    public CustomerDao createDao(){            //注意这些地方都是返回的dao层的接口,都是为了便于解耦
        return dao;
    }
}

 

 

2.4开发web层、

开发web层先将jsp页面写出来,首页jsp要分针,分成上下针,上针为head.jsp,下针为body.jsp

上针可以添加客户,还可以查询客户,并且显示的数据在body.jsp中显示,添加客户和查询客户的的界面为servlet,并且在cn.itcast.web.UI包中

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>首页</title>
  </head>
  
  <frameset rows="25%,*">
      <frame name="head" src="${pageContext.request.contextPath}/head.jsp">
      <frame name="body" src="${pageContext.request.contextPath}/body.jsp">
  </frameset>
  
</html>

head.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>页头</title>
  </head>
  
  <body style="text-align: center;">
      <br/>
    <h1>XXX客户关系管理系统</h1>
    
    <br/> <br/>
    
    <a href="${pageContext.request.contextPath }/servlet/AddCustomerUIServlet" target="body">添加客户</a>
    <a href="${pageContext.request.contextPath }/servlet/ListCustomerServlet" target="body">查看客户</a>
  </body>
</html>

body.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>页体</title>
  </head>
  
  <body>
    
  </body>
</html>

然后在UI包中建立web层的添加用户和查询用户的severlet  AddCustomerUIServlet

/day14_customer/src/cn/itcast/web/UI/AddCustomerUIServlet.java

这个severlet拿到数据之后转到addcustomer.jsp页面

package cn.itcast.web.UI;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.text.GapContent;

import cn.itcast.utils.Globals;

public class AddCustomerUIServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //由于在addcustomer.jsp中不适合做业务处理,这里就将获取爱好和客户类型的数据存入到域中带给addcustomer.jsp
        request.setAttribute("preferences", Globals.getAllPreference());
        request.setAttribute("types", Globals.getAllType());
        request.getRequestDispatcher("/WEB-INF/jsp/addcustomer.jsp").forward(request, response);
        
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

/day14_customer/WebRoot/WEB-INF/jsp/addcustomer.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>添加客户</title>
    
    <script type="text/javascript">
        function generateYear(){
            var year = document.getElementById("year");
            for(var i=1901;i<=new Date().getYear();i++){
                var option = document.createElement("option");
                option.value = i;
                option.innerText = i;
                year.appendChild(option);
            }
        }
        
        function generateMonth(){
            var month = document.getElementById("month");
            for(var i=2;i<=12;i++){
                var option = document.createElement("option");
                if(i<10){              //当月小于10的时候月前要加0
                    option.value = '0' + i;
                    option.innerText = '0' + i;
                }else{
                    option.value = i;
                    option.innerText = i;
                }
                month.appendChild(option);
            }
        }
        
        function generateDay(){
            var day = document.getElementById("day");
            for(var i=2;i<=31;i++){
                var option = document.createElement("option");
                if(i<10){
                    option.value = '0' + i;
                    option.innerText = '0' + i;
                }else{
                    option.value = i;
                    option.innerText = i;
                }
                day.appendChild(option);
            }
        }
        
        function init(){
            generateYear();
            generateMonth();
            generateDay();
        }
        
        function makePreferences(){        //对于爱好可能有多个,这个时候有两种方法,一在客户端用javascript将提交的爱好数据的id拼凑成一个字符串发给服务端,服务端直接存入数据库就可以了,二是在服务端用request.getParameterValues('preference')将所有的爱好id获取到,然后将这些id拼成一个字符串存入数据库中,,但是我们今天这里采用javascript
            var pres = document.getElementsByName("pre");    //得到的是一个数组,由于javascript是弱引用,变量可以装任意类型,所以不要加[]
            var preference = "";
            for(var i=0;i<pres.length;i++){
                var pre = pres[i];
                if(pre.checked==true){    //如果这个pre被选中了则执行下面代码
                    var id = pre.value;  //2
                    preference = preference + id + ",";
                }
            }
            preference = preference.substr(0,preference.length-1);  //截取掉多出来的一个逗号
            
            var input = document.createElement("input");//通过创建隐藏域将爱好字符串发送给服务端
            input.type="hidden";
            input.name="preference";
            input.value=preference;
            document.getElementById("form").appendChild(input);
        }
        
        function makeBirthday(){  //生日要作为一个完整的字符串传递                  
            var year = document.getElementById("year").value;
            var month = document.getElementById("month").value;
            var day = document.getElementById("day").value;
            //1980-09-09
            var birthday = year + "-" + month + "-" + day;
            
            var form = document.getElementById("form");    //在form表单下添加一个隐藏域来发送birthday
            var input = document.createElement("input");
            input.type="hidden";
            input.name="birthday";
            input.value=birthday;
            
            form.appendChild(input);
        }
        
        
        function doSubmit(){
            
            makeBirthday();
            makePreferences();
            return true;        //翻译true表示提交
            
        }
    </script>
  </head>
  
  <body onload="init()" style="text-align: center;">  <!--onload事件是表示当页面打开就执行init方法-->
  
      <br/><br/>
      <!--当表单提交的时候会触发onsubmit事件,这时我们返回doSubmit方法-->
      <form id="form" action="${pageContext.request.contextPath }/servlet/AddCustomerServlet" method="post" onsubmit="return doSubmit()">
    <table border="1" width="60%">
        <tr>
            <td>客户姓名</td>
            <td>
                <input type="text" name="name">
            </td>
        </tr>
        
        <tr>
            <td>性别</td>
            <td>
                <input type="radio" name="gender" value="男"><input type="radio" name="gender" value="女"></td>
        </tr>
        
        <tr>
            <td>生日</td>
            <td>
                <select id="year">              <!--由于有makeBirthday方法将年月日作为一个整体发送出去了,所以这里就没有name,没有name就不会发送单独的年月日数据-->
                    <option value="1900">1900</option>  <!--此处要用javascrip来产生出所有年-->
                </select><select id="month">
                    <option value="01">01</option>     <!--此处也要用javascript来产生出所有的月-->
                </select>月          
                
                <select id="day">
                    <option value="01">01</option>      <!--此处同样需要将日期用javascript产生出来-->
                </select></td>
        </tr>

        <tr>
            <td>手机号码</td>
            <td>
                <input type="text" name="cellphone">
            </td>
        </tr>
        
        <tr>
            <td>邮箱地址</td>
            <td>
                <input type="text" name="email">
            </td>
        </tr>
        
        <tr>
        <!-- 对于爱好,类型这类型每年都会增加的,对于这样的数据就不要写死了,
        我们可以将爱好写在数据库中的表中,通过方法动态获取,但是这里也不要这么麻烦了,
        我们这里通过在工具包中建立一个类来模拟爱好表 ,我们可以将爱好存入到list集合里
        当然还必须建立爱好的实体类,将爱好实体存入到list中去-->
            <td>爱好</td>    
            <td> 
                <c:forEach var="pre" items="${preferences}">
                    <input type="checkbox" name="pre" value="${pre.id }">${pre.name }                
                </c:forEach>
            </td>
        </tr>
        
        <tr>
            <td>客户类型</td>
            <td>
                <c:forEach var="type" items="${types}">
                    <input type="radio" name="type" value="${type.id }">${type.name }
                </c:forEach>
            </td>
        </tr>
        
        <tr>
            <td>备注</td>
            <td>
                <textarea rows="5" cols="50" name="description"></textarea>
            </td>
        </tr>
        
        <tr>
            <td>
                <input type="reset" value="清空">
            </td>
            <td>
                <input type="submit" value="添加">
            </td>
        </tr>
    </table>
    </form>
  </body>
</html>

 

 

/day14_customer/src/cn/itcast/utils/Globals.java  这个就是爱好的list和客户类型list,代表爱好表

package cn.itcast.utils;

import java.util.ArrayList;
import java.util.List;

import cn.itcast.domain.Preference;
import cn.itcast.domain.Type;

//全局
public class Globals {
    
    private static List plist = new ArrayList();
    private static List  tlist = new ArrayList();
    
    public static List getAllPreference(){
        
        plist.add(new Preference("1","唱歌"));
        plist.add(new Preference("2","爱春晚"));
        plist.add(new Preference("3","看林志玲"));
        plist.add(new Preference("4","看赵本山"));
        plist.add(new Preference("5","洗桑拿"));
        plist.add(new Preference("6","此处省略23个字"));
        return plist;
    }
    
    public static Preference findPreference(String id){
        
        return null;
    }
    
    public static List getAllType(){
        
        tlist.add(new Type("1","vip客户"));
        tlist.add(new Type("2","重要客户"));
        tlist.add(new Type("3","普通客户"));
        tlist.add(new Type("4","意向客户"));
        return tlist;
    }
    
    public static Type findType(String id){
        
        return null;
    }
    
}

 

 /day14_customer/src/cn/itcast/domain/Preference.java,爱好类

package cn.itcast.domain;

public class Preference {

    private String id;
    private String name;

    public Preference() {      //有一个有参数的就必须要有一个无参数的
        super();
        // TODO Auto-generated constructor stub
    }
    public Preference(String id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    
    
}

 

 /day14_customer/src/cn/itcast/domain/Type.java,客户类型类

package cn.itcast.domain;

public class Type {
    private String id;
    private String name;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Type(String id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public Type() {
        super();
        // TODO Auto-generated constructor stub
    }   
}

 

addcustomer.jsp将添加客户的表单数据发送给了一个severlet,AddCustomerServlet,这个severlet用于处理客户请求

/day14_customer/src/cn/itcast/web/controller/AddCustomerServlet.java

package cn.itcast.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sun.java2d.loops.CustomComponent;

import cn.itcast.domain.Customer;
import cn.itcast.service.BusinessService;
import cn.itcast.utils.WebUtils;

//添加客户
public class AddCustomerServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");    //不要忘记编码问题
        try{
            Customer customer = WebUtils.request2Bean(request, Customer.class);
            customer.setId(WebUtils.generateID());    //设置客户的ID
            BusinessService service = new BusinessService();
            service.addCustomer(customer);
        
            request.setAttribute("message", "添加成功!!");    //添加成功向域中存入添加成功
        }catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("message", "添加失败!!");    //添加失败不但要记录跟踪信息也得向域中存入添加失败
        }
        
        request.getRequestDispatcher("/message.jsp").forward(request, response);//无论添加失败还是成功都得转向message.jsp页面打印添加结果
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

 在severlet这边获取数据可以用一个工具类将数据填充到customer对象中,然后只是将customer传递数据库就可以了、

/day14_customer/src/cn/itcast/utils/WebUtils.java

package cn.itcast.utils;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;

public class WebUtils {

    public static String generateID(){
        return UUID.randomUUID().toString();
    }
    
    
    public static <T> T request2Bean(HttpServletRequest request,Class<T> clazz){
        try{
            T bean = clazz.newInstance();
            Map map = request.getParameterMap();    //获取所有的数据
            ConvertUtils.register(new DateLocaleConverter(), Date.class);//注册日期转换器
            BeanUtils.populate(bean, map);  //这个可以将map中的所有的请求数据存入到bean中去,这种填充必须要求map中的关键字和bean中的关键字一致,还有点要注意map中存入的日期是一个字符串,而bean中存入的日期是一个Date,所有需要转换,所以需要注册日期转化器。如上面
            return bean;    //返回这个bean对象
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
}

 /day14_customer/WebRoot/message.jsp

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'message.jsp' starting page</title>
  </head>
  
  <body>
   ${message }
  </body>
</html>

 

 

 

 

 

接下来来写查看客户

在head.jsp中有一个连接查看客户将连接到/day14_customer/src/cn/itcast/web/controller/ListCustomerServlet.java

不过在做ListCustomerSevlet时先将Dao层完善,将里面的getAll方法写完,还要将service层完善

/day14_customer/src/cn/itcast/dao/impl/CustomerDaoImpl.java(dao层)

package cn.itcast.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import cn.itcast.dao.CustomerDao;
import cn.itcast.domain.Customer;
import cn.itcast.domain.QueryResult;
import cn.itcast.exception.DaoException;
import cn.itcast.utils.JdbcUtils;

public class CustomerDaoImpl implements CustomerDao {

    /*
     * id varchar(40) primary key,
            name varchar(20) not null,
            gender varchar(4) not null,
            birthday date,
            cellphone varchar(40) not null,
            email varchar(100),
            preference varchar(100),
            type varchar(40),
            description varchar(255)
     */
    public void add(Customer customer){
        
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "insert into customer(id,name,gender,birthday,cellphone,email,preference,type,description) values(?,?,?,?,?,?,?,?,?)";
            st = conn.prepareStatement(sql);
            st.setString(1, customer.getId());
            st.setString(2, customer.getName());
            st.setString(3, customer.getGender());
            st.setDate(4, new java.sql.Date(customer.getBirthday().getTime()));        //将java.util.Date转换成java.sql.Date
            st.setString(5, customer.getCellphone());
            st.setString(6, customer.getEmail());
            st.setString(7, customer.getPreference());
            st.setString(8, customer.getType());
            st.setString(9, customer.getDescription());
            st.executeUpdate();
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
        
        
        
    }
    
    public void update(Customer customer){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
        
    }
    
    public void delete(String id){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
        
    }
    
    public Customer find(String id){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
        
        return null;
    }
    
    public List<Customer> getAll(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from customer";
            st = conn.prepareStatement(sql);
            rs = st.executeQuery();
            List list = new ArrayList();
            while(rs.next()){
                Customer c = new Customer();
                c.setBirthday(rs.getDate("birthday"));
                c.setCellphone(rs.getString("cellphone"));
                c.setDescription(rs.getString("description"));
                c.setEmail(rs.getString("email"));
                c.setGender(rs.getString("gender"));
                c.setId(rs.getString("id"));
                c.setName(rs.getString("name"));
                c.setPreference(rs.getString("preference"));
                c.setType(rs.getString("type"));
                list.add(c);
            }
            return list;
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    public QueryResult pageQuery(int startindex,int pagesize){
        
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        
        QueryResult qr = new QueryResult();
        try{
            conn = JdbcUtils.getConnection();
            String sql = "select * from customer limit ?,?";
            st = conn.prepareStatement(sql);
            st.setInt(1, startindex);
            st.setInt(2, pagesize);
            rs = st.executeQuery();
            List list = new ArrayList();
            while(rs.next()){
                Customer c = new Customer();
                c.setBirthday(rs.getDate("birthday"));
                c.setCellphone(rs.getString("cellphone"));
                c.setDescription(rs.getString("description"));
                c.setEmail(rs.getString("email"));
                c.setGender(rs.getString("gender"));
                c.setId(rs.getString("id"));
                c.setName(rs.getString("name"));
                c.setPreference(rs.getString("preference"));
                c.setType(rs.getString("type"));
                list.add(c);
            }
            qr.setList(list);  
            
            sql = "select count(*) from customer";
            st = conn.prepareStatement(sql);
            rs = st.executeQuery();
            
            if(rs.next()){
                qr.setTotalrecord(rs.getInt(1));
            }
            return qr;
        }catch (Exception e) {
            throw new DaoException(e);
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
}

 

/day14_customer/src/cn/itcast/service/BusinessService.java(service层)

package cn.itcast.service;

import cn.itcast.dao.CustomerDao;
import cn.itcast.domain.Customer;
import cn.itcast.domain.PageBean;
import cn.itcast.domain.PageInfo;
import cn.itcast.domain.QueryResult;
import cn.itcast.utils.DaoFactory;

public class BusinessService {
    //此处引用接口调用,而且这里要用工厂来创建dao层,便于将来解耦
    private CustomerDao customerDao = DaoFactory.getInstance().createDao();
    public void addCustomer(Customer customer){
        customerDao.add(customer);
    }
    
    public PageBean pageQuery(PageInfo pageInfo){
        
        QueryResult qr = customerDao.pageQuery(pageInfo.getStartindex(), pageInfo.getPagesize());
        PageBean pageBean = new PageBean();
        pageBean.setCurrentpage(pageInfo.getCurrentpage());
        pageBean.setList(qr.getList());
        pageBean.setPagesize(pageInfo.getPagesize());
        pageBean.setTotalrecord(qr.getTotalrecord());
        
        return pageBean;
    }
    
}

 

/day14_customer/src/cn/itcast/web/controller/ListCustomerServlet.java

package cn.itcast.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.itcast.domain.PageBean;
import cn.itcast.domain.PageInfo;
import cn.itcast.service.BusinessService;
import cn.itcast.utils.WebUtils;

public class ListCustomerServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        PageInfo pageInfo = WebUtils.request2Bean(request, PageInfo.class);
        BusinessService service = new BusinessService();
        PageBean pageBean = service.pageQuery(pageInfo);
        request.setAttribute("pageBean", pageBean);
        
        request.getRequestDispatcher("/WEB-INF/jsp/listcustomer.jsp").forward(request, response);
        
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

 然后再是jsp页面istcustomer.jsp

/day14_customer/WebRoot/WEB-INF/jsp/listcustomer.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>显示所有用户</title>
  </head>
  
  <body style="text-align: center;">
      a<br/><br/>
  
    <table width="90%" border="1">    <!--border='1'和frame=border的区别,frame即使单元格没有数据也会显示边框,border='1'如果单元格没有数据则不会显示边框-->
        <tr>
            <td>客户姓名</td>
            <td>性别</td>
            <td>生日</td>
            <td>手机</td>
            <td>邮箱</td>
            <td>爱好</td>
            <td>类型</td>
            <td>备注</td>
            <td>操作</td>
        </tr>
        
        <c:forEach var="c" items="${pageBean.list}">
            <tr>
                <td>${c.name }</td>
                <td>${c.gender }</td>
                <td>${c.birthday }</td>
                <td>${c.cellphone }</td>
                <td>${c.email }</td>
                <td>${c.preference }</td>
                <td>${c.type }</td>
                <td>${c.description }</td>
                <td>
                    <a href="#">修改客户</a>
                    <a href="#">删除客户</a>
                </td>
            </tr>
        </c:forEach>
    </table>
    
    <script type="text/javascript">
        function gotopage(pagenum){
            var pagesize = document.getElementsByName("pagesize")[0].value;
            window.location.href="${pageContext.request.contextPath}/servlet/ListCustomerServlet?currentpage=" + pagenum + "&pagesize=" + pagesize;
        }
        
        function goWhich(input){
            var pagesize = document.getElementsByName("pagesize")[0].value;
            var pagenum = input.value;
            window.location.href="${pageContext.request.contextPath}/servlet/ListCustomerServlet?currentpage=" + pagenum + "&pagesize=" + pagesize;
        }
    </script>
    
    共[${pageBean.totalrecord }]记录,
    每页<input type="text" name="pagesize" value="${pageBean.pagesize }" style="width: 20px">条,
    共[${pageBean.totalpage }]页,
    当前[${pageBean.currentpage }]页
    &nbsp; &nbsp; &nbsp;
    <a href="javascript:void(0)" onclick="gotopage(${pageBean.previouspage })">上一页</a>
        <c:forEach var="pagenum" items="${pageBean.pagebar}">
            <c:if test="${pageBean.currentpage!=pagenum}">
                <a href="javascript:void(0)" onclick="gotopage(${pagenum })">${pagenum }</a>
            </c:if>
            <c:if test="${pageBean.currentpage==pagenum}">
                <font color="red">${pagenum }</font>
            </c:if>
        </c:forEach>
    <a href="javascript:void(0)" onclick="gotopage(${pageBean.nextpage })">下一页</a>
    
    跳转到<input type="text" name="pagenum" style="width: 30px" id="pagenum">
    <input type="button" value=" GO " onclick="goWhich(document.getElementById('pagenum'))">
  </body>
</html>

 

 以上还要将得到的数据中的爱好和客户类型的数字字符串转换成可辨认内容
具体做法就是在Globals.java中创建方法根据id获取爱好和客户类型
posted @ 2013-10-20 16:58  ysfox  阅读(204)  评论(0)    收藏  举报