Day14
JDBC开发
一。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

一、查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象。
二、程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。






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(); } } }
——————————————————————————————————————————————————————————





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








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(); } } } */ } } }
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"); } } }




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); } }
1、把xml换成数据库,重写UserDao。
2、定义DAO接口,并定义Dao工厂,实现service层和dao层的解耦。
3、自定义dao异常。
4、防范sql注入攻击
1、statement存在sql注入攻击问题,例如登陆用户名采用' or 1=1 or username=‘
2、对于防范 SQL 注入,可以采用PreparedStatement取代Statement。
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)
);




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

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



1、statement存在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

* statement和preparedStatement的区别
* 1.preparedStatement是statement的孩子。
* 2.preparedStatement可以预防sql注入的问题
* 3.preparedStatement向数据库发送的是预编译后的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); } } }
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 } }
创立如下数据库表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 }]页 <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获取爱好和客户类型