JAVAWEB开发之Tomcat内置连接池的配置和使用、DbUtils的使用详解和案例、以及元数据详解...

Tomcat内置连接池

Tomcat服务器内置连接池 使用的是dbcp框架
配置Tomcat内置连接池,通过JNDI方式 去访问Tomcat的内置连接池

JNDI Java命名和目录接口,是JAVAEE一项技术,允许将一个Java对象绑定到一个JNDI容器(Tomcat)中,并且为对象指定一个名称 通过javax.naming包Context对JNDI容器中绑定的对象进行查找,通过指定名称找到绑定的Java对象。
Tomcat如何配置使用连接池?
要想将一个dbcp连接池让Tomcat管理,只需要创建一个context.xml配置文件,在配置文件中配置相关信息。
<Context>
<Resource name="jdbc/EmployeeDB" auth="Container"
type="javax.sql.DataSource" username="root" password="abc"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql:///mydb1"
maxActive="8" maxIdle="4"/>
</Context>
问题一:context.xml文件位置:
(1)在tomcat/conf/context.xml 这时这个连接池是给整个服务器用的
(2)在tomcat/conf/Catalina/localhost 这时这个连接池只给localhost虚拟主机使用
(3)将context.xml文件放置在web应用的META-INF下
注意:不管是否是全局设置,都需要将数据库驱动放置在tomcat/lib 目录下
问题二:怎样从tomcat中获取连接池?
我们在Servlet中获取连接池对象。
Context context = new InitialContext();
Context envCtx = (Context)context.lookup("java:comp/env"); // 固定路径
DataSource dataSource = (DataSource) envCtx.lookup("jdbc/EmployeeDB");
示例如下:
在web项目的 /WebRoot/META-INF 下新建context.xml 内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
	<Resource name="jdbc/EmployeeDB" auth="Container" type="javax.sql.DataSource"
		username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
		url="jdbc:mysql:///mydb1" maxActive="8" maxIdle="4" />
</Context>
在src下新建cn.itcast包 在包内新建测试类
package cn.itcast;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

public class DataSourceServlet extends HttpServlet {

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

		try {
			Context context = new InitialContext();
			Context envCtx = (Context) context.lookup("java:comp/env"); // 固定路径
			DataSource datasource = (DataSource) envCtx
					.lookup("jdbc/EmployeeDB");

			Connection con = datasource.getConnection();
			ResultSet rs = con.createStatement().executeQuery(
					"select * from account");

			while (rs.next()) {
				System.out.println(rs.getInt("id") + "  "
						+ rs.getString("name"));
			}

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

	}

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

}
注意:有一个误区 就是把context.xml 放在项目中 驱动也就放在项目的lib下 tomcat内置连接池是无法找到驱动的
会报错

不管是哪种方式 只要是使用Tomcat内置连接池 都需要将驱动放置在tomcat/lib下
访问Servlet 测试类 效果如下:

元数据

元数据:指数据库中库、表、列的定义信息

DataBaseMetaData 数据库元数据

如何获取一个DataBaseMetaData?
Connection接口中定义了一个方法getMetaData();
(1)通过DataBaseMetaData 获得数据库连接的基本参数
  • getURL():返回一个String类对象,代表数据库的URL。
  • getUserName():返回连接当前数据库管理系统的用户名。
  • getDriverName():返回驱动程序的名称
  • getPrimaryKeys(String catalog, String schema, String table):返回指定表主键的结果集
(2)获取数据库、表、列、主键、外键 定义信息
getTables
getColumns
getPrimaryKeys

ResultSet getPrimaryKeys(String catalog, String schema,String table)throws SQLException
获取表中主键相关描述
每个主键列描述都有以下列:
TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
COLUMN_NAME String => 列名称
KEY_SEQ short => 主键中的序列号(值 1 表示主键中的第一列,值 2 表示主键中的第二列)。
PK_NAME String => 主键的名称(可为 null)

为了方便 还是把上次的JdbcUtils工具类给弄过来
在src下新建jdbc.properties资源文件 内容如下:
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///day18?generateSimpleParameterMetadata=true
username=root
password=abc

#driverClass=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:XE
#username=system
#password=system
JdbcUtils.java
package cn.itcast.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;

public class JdbcUtils {

	private static final String DRIVERCLASS;
	private static final String URL;
	private static final String USERNAME;
	private static final String PASSWORD;

	static {
		DRIVERCLASS = ResourceBundle.getBundle("jdbc").getString("driverClass");
		URL = ResourceBundle.getBundle("jdbc").getString("url");
		USERNAME = ResourceBundle.getBundle("jdbc").getString("username");
		PASSWORD = ResourceBundle.getBundle("jdbc").getString("password");
	}

	static {
		try {
			// 将加载驱动操作,放置在静态代码块中.这样就保证了只加载一次.
			Class.forName(DRIVERCLASS);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static Connection getConnection() throws SQLException {
		Connection con = DriverManager.getConnection(URL, USERNAME, PASSWORD);

		// 对Connection进行增强

		// return new MyConnection(con);

		// 使用动态代理来完成

		return con;
	}

	// 关闭操作
	public static void closeConnection(Connection con) throws SQLException {
		if (con != null) {
			con.close();
		}
	}

	public static void closeStatement(Statement st) throws SQLException {
		if (st != null) {
			st.close();
		}
	}

	public static void closeResultSet(ResultSet rs) throws SQLException {
		if (rs != null) {
			rs.close();
		}
	}
}

开始实例演示数据库元数据DataBaseMetaData类的使用
package cn.itcast.metadata;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;

import cn.itcast.utils.JdbcUtils;

public class DataBaseMetaDataTest {
	public static void main(String[] args) throws SQLException {
		Connection con = JdbcUtils.getConnection();
		// 获取DataBaseMetaData
		DatabaseMetaData dmd = con.getMetaData();
		// 获取驱动名称、
		String driverName = dmd.getDriverName();
		System.out.println(driverName);

		// 获取用户名
		String username = dmd.getUserName();
		System.out.println(username);

		// 获取URL
		String url = dmd.getURL();
		System.out.println(url);

		// 获取数据库产品名称
		String databaseProductName = dmd.getDatabaseProductName();
        System.out.println(databaseProductName);
        
        // 获取数据库产品版本
        String version = dmd.getDatabaseProductVersion();
        System.out.println(version);
        
        ResultSet  rs = dmd.getPrimaryKeys(null, null, "account");
	      while(rs.next()){
	    	  System.out.println(rs.getObject(3));
	      }
	}

}

ParameterMetaData 参数元数据

参数元数据主要用于获取:获取SQL语句中占位符的相关信息
获取ParameterMetaData:在PreparedStatement中有一个方法getParameterMetaData()可以获取
SELECT * FROM user where name=? and password=?
ParameterMetaData对象:
getParameterCount() 获取指定参数的个数
getParameterTypeName(int param) 获取指定参数的SQL类型
注意:在获取参数类型时会产生异常
java.sql.SQLException: Parameter metadata not available for the given statement
解决方案:
在url后添加参数
jdbc:mysql:///day18?generateSimpleParameterMetadata=true
添加这个参数后,我们在获取,它的结果也是varchar,原因:是mysql驱动的支持问题。(oracle对此就有很好的 支持)
实例代码如下:
package cn.itcast.metadata;

import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import cn.itcast.utils.JdbcUtils;

public class ParameterMetaDataTest {
	public static void main(String[] args) throws SQLException {
		Connection con = JdbcUtils.getConnection();
		String sql = "select * from account where id=? and name=? ";
		PreparedStatement pst = con.prepareStatement(sql);

		// 获取一个ParameterMetaData
		ParameterMetaData pmd = pst.getParameterMetaData();
		int count = pmd.getParameterCount();
		System.out.println(count);

		String type1 = pmd.getParameterTypeName(1);
		System.out.println(type1);
	}
}

ResultSetMetaData结果集元数据

可以通过ResultSet的getMetaData()方法获取

获得通过ResultSet对象元数据的ResultSetMetaData对象

getColumnCount():返回result对象的列数
getColumnName(int column):获得指定列的名称
getColumnTypeName(int column):获得指定列的类型
示例代码如下:
package cn.itcast.metadata;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

import cn.itcast.utils.JdbcUtils;

public class ResultSetMetaDataTest {

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

		Connection con = JdbcUtils.getConnection();
		ResultSet rs = con.createStatement().executeQuery(
				"select * from account");

		// 得到结果集元数据
		ResultSetMetaData rsmd = rs.getMetaData();

		// System.out.println(rsmd.getColumnCount());//获取结果集中列数量
		//
		// System.out.println(rsmd.getColumnName(2));//获取结果集中指定列的名称.
		//
		// System.out.println(rsmd.getColumnTypeName(3));//获取结果集中指定列的类型。

		int count = rsmd.getColumnCount();

		for (int i = 1; i <= count; i++) {

			System.out.print(rsmd.getColumnName(i)+"("+rsmd.getColumnTypeName(i)+")" + "\t");
		}
		System.out.println();

		while (rs.next()) {
			for (int i = 1; i <= count; i++) {
				System.out.print(rs.getObject(i) + "\t\t");
			}
			System.out.println();
		}
	}
}


Dbutils框架详解

commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。其实就是一个简单的jdbc封装工具,使用dbutils可以简化操作。
注意:使用的时候需要导入jar包
API介绍:
  • org.apache.commons.dbutils.QueryRunner 核心类
  • org.apache.commons.dbutils.ResultSetHandler
  • 工具类:org.apache.commons.dbutils.Dbutils
DbUtils核心:
(1)QueryRunner 框架核心类,所有数据库操作都是必须通过QueryRunner进行的,它是用于执行SQL语句的类
query 用于执行select
update用于执行update delete insert
batch 批处理
(2)ResultSetHandler接口 结果集封装接口,完成将ResultSet结果集封装为一个Java对象用于定义结果集的封 装,它提供九个实现类,可以进行不同的封装。
(3)DbUtils类 是一个工具类 提供驱动管理、事务管理、释放资源等一系列公共方法。

DbUtils类详解

DbUtils类:提供如关闭链接‘、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
  • public static void close(...) throws java.sql.SQLException:DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
  • public static void closeQuietly(...):这一类方法不仅能在Connection、Statement和ResultSet为NULL的情况下悄悄关闭,就是指捕获关闭时抛出的SQLException 不抛出也不进行任何处理。
  • public static void commitAndCloseQuietly(Connection conn):用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
  • public static boolean loadDriver(java.lang.String driverClassName):这一方法装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,不需要捕捉这个异常ClassNotFoundException
使用方法 代码示例如下:
在cn.itcast.domain包下新建Account类(封装数据的Bean类)
package cn.itcast.domain;

public class Account {

	private int id;
	private String name;
	private double money;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public double getMoney() {
		return money;
	}

	public void setMoney(double money) {
		this.money = money;
	}

	@Override
	public String toString() {
		return "Account [id=" + id + ", name=" + name + ", money=" + money
				+ "]";
	}

}
新建DbUtilsTest1类 演示DbUtils框架的简单使用:
package cn.itcast.dbutils;

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

import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.junit.Test;

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

public class DbUtilsTest1 {

	// 查询
	@Test
	public void selectTest() throws SQLException {

		String sql = "select * from account";

		QueryRunner runner = new QueryRunner();
		Connection con = JdbcUtils.getConnection();
		List<Account> as = runner.query(con, sql,
				new ResultSetHandler<List<Account>>() {

					public List<Account> handle(ResultSet rs)
							throws SQLException {
						List<Account> as = new ArrayList<Account>();
						while (rs.next()) {

							Account a = new Account();
							a.setId(rs.getInt("id"));
							a.setName(rs.getString("name"));
							a.setMoney(rs.getDouble("money"));

							as.add(a);
						}

						return as;
					}

				});

		for (Account a : as) {
			System.out.println(a);
		}
		
		DbUtils.close(con);
		
	}

	// 添加
	@Test
	public void addTest() throws SQLException {
		String sql = "insert into account values(null,?,?)";
		QueryRunner runner = new QueryRunner();

		int row = runner.update(JdbcUtils.getConnection(), sql, "张三", 1000d);

		System.out.println(row);
	}
}

测试查询


测试更新

QueryRunner类

该类简化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
QueryRunner类提供了两个构造方法:
默认的构造方法(手动管理事务)
需要一个javax.sql.DataSource来作参数的构造方法(自动管理事务)
QueryRunner的获取:
(1)new QueryRunner()
如果是使用这种构造创建的QueryRunner,它的事务是手动控制
(2)new QueryRunner(DataSource ds)
如果是使用这种构造,它的事务是自动事务,简单的说,一条SQL一个事务

QueryRunner中的三个核心方法:
query 查询
update 更新(insert、update、delete)
batch 批处理
对于上述三个方法,它们提供很多重载。
如果QueryRunner在创建时,没有传递DataSource参数,那么在使用query、update、batch方法时,要传递 Connection对象参数
如果QueryRunner在创建时,传递了DataSource参数,那么在使用query、update、batch方法时,不需要传递 Connection参数
(1)更新操作
public int update(Connection conn, String sql, Object... params)
public int update(String sql, Object... params)
(2)查询操作
public Object query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)
public Object query(String sql, ResultSetHandler<T> rsh, Object... params)

配套使用方式:
QueryRunner runner=new QueryRunner();
runner.query(Connection,sql,ResultSetHandler,Object... param);
runner.update(Connection,sql,Object...param);
runner.batch(Connection con,sql,Object[][] objs);

QueryRunner runner=new QueryRunner(DataSource ds);
runner.query(sql,ResultSetHandler,Object... param);
runner.update(sql,Object...param);
runner.batch(sql,Object[][] objs);
关于QueryRunner的详细使用,具体如下:
在使用DbUtils时 所需要的DataSource数据源或者Connection 一般不用自定义的,而使用c3p0连接池进行获取;
所以先导入c3p0的jar文件
在src下的c3p0-config.xml文件中配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql:///mydb1</property>
		<property name="user">root</property>
		<property name="password">root</property>
	</default-config>
</c3p0-config>
封装一个专门获取的数据源的工具类
DataSourceUtils
package cn.itcast.utils;

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

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DataSourceUtils {
	private static ComboPooledDataSource cpds = new ComboPooledDataSource();

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

	public static DataSource getDataSource() {
		return cpds;
	}
}
新建测试类 测试QueryRunner的用法
package cn.itcast.dbutils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;

import cn.itcast.domain.Account;
import cn.itcast.utils.DataSourceUtils;

public class QueryRunnerTest {

	@Test
	// 使用无参数 的QueryRunner
	public void fun1() throws SQLException {
		String sql = "select * from account where id>? and name=? ";
		QueryRunner runner = new QueryRunner(); // 事务手动控制

		Connection con = DataSourceUtils.getConnection();

		// con.setAutoCommit(false);

		List<Account> list = runner.query(con, sql,
				new BeanListHandler<Account>(Account.class),2,"ccc");

		// con.rollback();
		System.out.println(list);
	}

	@Test
	// 使用有参数 的QueryRunner
	public void fun2() throws SQLException {
		String sql = "select * from account where id=?";
		
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource()); // 自动事务
		List<Account> list = runner.query(sql, new BeanListHandler<Account>(
				Account.class),2);
		System.out.println(list);
	}
}


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

模仿QueryRunner类(深入理解其实现机制)

模仿QueryRunner(关键代码)
1.query方法模仿
public <T> T query(Connection con, String sql, MyResultSetHandler<T> mrs,Object... params) throws SQLException {
PreparedStatement pst = con.prepareStatement(sql); // 得到一个预处理的Statement.
// 问题:sql语句中可能存在参数,需要对参数赋值。
ParameterMetaData pmd = pst.getParameterMetaData();
// 可以得到有几个参数
int count = pmd.getParameterCount();
for (int i = 1; i <= count; i++) {
pst.setObject(i, params[i - 1]);
}
ResultSet rs = pst.executeQuery(); // 得到了结果集,要将结果集封装成用户想要的对象,但是,工具不可能 知道用户需求。
return mrs.handle(rs);
}
2.update方法模仿
public int update(Connection con, String sql, Object... params) throws SQLException {
PreparedStatement pst = con.prepareStatement(sql); // 得到一个预处理的Statement.
// 问题:sql语句中可能存在参数,需要对参数赋值。
ParameterMetaData pmd = pst.getParameterMetaData();
// 可以得到有几个参数
int count = pmd.getParameterCount();
for (int i = 1; i <= count; i++) {
pst.setObject(i, params[i - 1]);
}
int row = pst.executeUpdate();
// 关闭资源
pst.close();
return row;
}

在src下新建cn.itcast.mydbutils包(专门放置我自己模仿DbUtils实现的相关类)
在MyBeanHandler中需要用到BeanUtils 所以导入BeanUtils的两个jar包
commons-beanutils-1.8.3.jar
commons-logging-1.1.1.jar
在包内创建MyResultHandler接口(模仿DbUtils框架中的ResultSetHandler接口)
package cn.itcast.mydbutils;

import java.sql.ResultSet;
import java.sql.SQLException;

public interface MyResultHandler<T> {
	public T handle(ResultSet rs) throws SQLException;
}
创建MyBeanHandler类 (模仿BeanHandler类)
package cn.itcast.mydbutils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

public class MyBeanHandler implements MyResultHandler {
	private Class clazz;

	public MyBeanHandler(Class clazz) {
		this.clazz = clazz;
	}

	// 方式一:依赖于BeanUtils工具类
	public Object handle1(ResultSet rs) throws SQLException {
		Object obj = null;
		Map<String, String[]> map = new HashMap<String, String[]>();

		ResultSetMetaData md = rs.getMetaData();
		int count = md.getColumnCount();
		if (rs.next()) {
			try {
				obj = clazz.newInstance();
				for (int i = 1; i <= count; i++) {
					map.put(md.getColumnName(i),
							new String[] { rs.getString(md.getColumnName(i)) });
				}
				BeanUtils.populate(obj, map);
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}

		}
		return obj;
	}

	// 方式二:从结果集的方向去封装数据
	public Object handle(ResultSet rs) throws SQLException {
		Object obj = null;
		// 得到结果集元数据
		ResultSetMetaData md = rs.getMetaData();
		// 由结果集元数据可以获得所有字段名称
		int count = md.getColumnCount();

		// 遍历结果集 因为最后的需要的结果只是一个Bean对象,所以不用循环
		if (rs.next()) {
			// 利用内省技术进行实现
			try {
				obj = clazz.newInstance();
				BeanInfo bif = Introspector.getBeanInfo(clazz);
				// 得到JavaBean的所有属性描述器
				PropertyDescriptor[] pds = bif.getPropertyDescriptors();
				for (int i = 1; i <= count; i++) {
					// 得到每一列的名称
					String name = md.getColumnName(i);
					for (PropertyDescriptor pd : pds) {
						if (name.equals(pd.getName())) {
							// 使用setXxx方法将结果集中的字段值封装到JavaBean的对应属性上。
							pd.getWriteMethod().invoke(obj, rs.getObject(name));
						}
					}
				}
			} catch (IntrospectionException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			}
		}
		return obj;
	}
}
创建MyQueryRunner类(模仿QueryRunner类)
package cn.itcast.mydbutils;

import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

public class MyQueryRunner {
	private DataSource ds;

	public MyQueryRunner() {
	}

	public MyQueryRunner(DataSource ds) {
		this.ds = ds;
	}

	// 执行select操作
	public <T> T query(Connection con, String sql, MyResultHandler<T> mrs,
			Object... params) throws SQLException {
		// 获取一个预处理的Statement
		PreparedStatement pst = con.prepareStatement(sql);
		// 注意:SQL语句中可能存在参数,需要对参数进行赋值

		ParameterMetaData pmd = pst.getParameterMetaData();

		// 获取参数个数
		int count = pmd.getParameterCount();
		for (int i = 1; i <= count; i++) {
			pst.setObject(i, params[i - 1]);
		}

		// 获取结果集
		ResultSet rs = pst.executeQuery();

		// 注意得到了结果集,需要将结果集封装成用户想要的对象,但是工具不可能知道用户的封装需求

		return mrs.handle(rs);
	}

	// 执行update操作
	public int update(Connection con, String sql, Object... params)
			throws SQLException {
		// 获取一个预处理的Statement对象
		PreparedStatement pst = con.prepareStatement(sql);

		ParameterMetaData pmd = pst.getParameterMetaData();
		// 可以得到几个参数
		int count = pmd.getParameterCount();
		for (int i = 1; i <= count; i++) {
			pst.setObject(i, params[i - 1]);
		}

		int row = pst.executeUpdate();
		// 关闭资源 因为Statement对象指执行一次操作
		pst.close();
		return row;
	}

	// 执行update操作
	public int update(String sql, Object... params) throws SQLException {
		Connection con = ds.getConnection();

		// 获取一个预处理的Statement对象
		PreparedStatement pst = con.prepareStatement(sql);

		ParameterMetaData pmd = pst.getParameterMetaData();
		// 可以得到几个参数
		int count = pmd.getParameterCount();
		for (int i = 1; i <= count; i++) {
			pst.setObject(i, params[i - 1]);
		}

		int row = pst.executeUpdate();
		// 关闭资源 因为Statement对象指执行一次操作
		pst.close();
		con.close(); // 因为不带Connection参数的方法是一次性事务,需要关闭
		return row;
	}

}
新建测试类 测试如下:
package cn.itcast.mydbutils;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;

import cn.itcast.domain.Account;
import cn.itcast.utils.DataSourceUtils;

public class MyQueryRunnerTest {

	// 测试update方法
	@Test
	public void updateTest() throws SQLException {
		String sql = "delete from account where id=?";
		MyQueryRunner mqr = new MyQueryRunner();
		mqr.update(DataSourceUtils.getConnection(), sql, 4);
	}

	// 测试select
	@Test
	public void selectTest() throws SQLException {
		String sql = "select * from account where id=?";
		MyQueryRunner mqr = new MyQueryRunner();
		Account a = mqr.query(DataSourceUtils.getConnection(), sql,
				new MyResultHandler<Account>() {
					public Account handle(ResultSet rs) throws SQLException {
						Account a = null;
						if (rs.next()) {
							a = new Account();
							a.setId(rs.getInt("id"));
							a.setName(rs.getString("name"));
							a.setMoney(rs.getDouble("money"));
						}
						return a;
					}
				}, 2);
		System.out.println(a);
	}

	// 测试MyBeanHandler
	@Test
	public void beanHandlerTest() throws SQLException{
		String sql = "select * from account where id=?";
		MyQueryRunner mqr = new MyQueryRunner();
		Account a = mqr.query(DataSourceUtils.getConnection(), sql, new MyBeanHandler(Account.class), 1);
	    System.out.println(a);
	}
}
依次测试运行结果如下:

------------------------------------------------------------------------------------------------------------------------

ResultSetHandler(九个默认实现类)

该接口用于处理java.sql.ResultSet, 将数据按要求转换为另一种方式。
ResultSetHandler接口提供了一个单独的方法:Object handle(java.sql.ResultSet rs)
ResultSetHandler在DBUtils框架中提供九个默认实现类,直接使用九个默认实现类,就可以完成常规操作,而不需要自定义结果集封装
  • ArrayHandler:将结果集中第一条记录封装到Object[],数组的每一个元素就是记录中的字段值。
  • ArrayListHandler:将结果集中每一条记录封装到Object[],数组中的每一个元素就是记录中的字段值。再将这些数组装入到List集合。
  • BeanHandler(重点):将结果集中第一条记录封装到一个JavaBean中。
  • BeanListHandler(重点):将结果集中每一条记录封装到JavaBean中,再将JavaBean封装到List集合。
  • ColumnListHandler:将结果集中指定列的值封装到List集合。
  • MapHandler:将结果集中第一条记录封装到Map集合中,集合的key就是字段名称,value就是字段值。
  • MapListHandler:将结果集中每一条记录封装到每一个Map集合中,集合的key就是字段名称,value就是字段值,再 讲这些Map封装到List集合。
  • KeyedHandler:将结果集每行的数据封装成一个Map,再将Map存入另一个Map作为value,指定一列作为key
  • ScalarHandler:进行单值查询 select count(*) from account;
具体代码如下所示:
package cn.itcast.dbutils;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;

import cn.itcast.domain.Account;
import cn.itcast.utils.DataSourceUtils;

// 介绍ResultSetHandler
public class ResultSetHandlerImplTest {
	// ArrayHandler
	@Test
	public void fun1() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		Object[] obj = runner
				.query("select * from account", new ArrayHandler());
		System.out.println(Arrays.toString(obj));
	}

	// ArrayListHandler
	@Test
	public void fun2() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		List<Object[]> objs = runner.query("select * from account",
				new ArrayListHandler());
		for (Object[] obj : objs) {
			System.out.println(Arrays.toString(obj));
		}
	}

	// BeanHandler
	@Test
	public void fun3() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		Account obj = runner.query("select * from account",
				new BeanHandler<Account>(Account.class));
		System.out.println(obj);
	}

	// BeanListHandler
	@Test
	public void fun4() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		List<Account> objs = runner.query("select * from account",
				new BeanListHandler<Account>(Account.class));
		for (Account account : objs) {
			System.out.println(account);
		}
	}

	// ColumnListHandler
	@Test
	public void fun5() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		List<Object> obj = runner.query("select * from account",
				new ColumnListHandler(1));
		List<Object> obj2 = runner.query("select * from account",
				new ColumnListHandler("name"));
		System.out.println(obj);
		System.out.println(obj2);
	}

	// MapHandler
	@Test
	public void fun6() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		Map<String, Object> obj = runner.query("select * from account",
				new MapHandler());
		System.out.println(obj);
	}

	// MapHandler
	@Test
	public void fun7() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		List<Map<String, Object>> objs = runner.query("select * from account",
				new MapListHandler());
		for (Map<String, Object> map : objs) {
			System.out.println(map);
		}
	}

	// KeyedHandler
	@Test
	public void fun8() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		Map<Object, Map<String, Object>> obj = runner.query(
				"select * from account", new KeyedHandler("name"));
		System.out.println(obj);
	}

	// ScalarHandler
	@Test
	public void fun9() throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		long obj = (Long) runner.query("select count(*)  from account",
				new ScalarHandler());
		System.out.println(obj);
	}

	// 按照需求自定义ResultSetHandler
	// 将结果封装到一个JavaBean对象中
	@Test
	public void fun10() throws SQLException {
		String sql = "select * from account where id=?";
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		Account a = runner.query(sql, new ResultSetHandler<Account>() {
			// 重写handle方法,在这个方法中确定,怎样将结果集封装
			public Account handle(ResultSet rs) throws SQLException {
				Account a = null;
				if (rs.next()) {
					a = new Account();
					a.setId(rs.getInt("id"));
					a.setName(rs.getString("name"));
					a.setMoney(rs.getDouble("money"));
				}
				return a;
			}
		}, 2);
		System.out.println(a);
	}
}
依次测试,运行结果如下所示:












案例:客户管理系统

登录成功后访问到一个页面success.jsp,在页面后添加一个连接 就是客户信息的CURD操作
(1)客户信息
字段名 说明 类型
Id 编号 varchar(40)
name 客户姓名 varchar(20)
gender 性别 varchar(10)
birthday 生日 date
cellphone 手机 varchar(20)
email 电子邮件 varchar(40)
preference 客户爱好 varchar(100)
type 客户类型 varchar(40)
description 备注 varchar(255)
首先创建一个客户信息表 SQL语句如下:
create table customer(
id varchar(40) primary key,
name varchar(20),
gender varchar(10),
birthday date,
cellphone varchar(20),
email varchar(40),
preference varchar(100),
type varchar(40),
description varchar(255)
);
(2)搭建环境
JavaEE 三层架构
Servlet + JSP + JavaBean + jstl +DBUtils + DAO + MySQL

导入jar包:JSTL、BeanUtils、DBUtils、c3p0、MySQL驱动
JSTL:jstl.jar standard.jar
BeanUtils:commons-beanutils-1.8.3.jar、commons-logging-1.1.1.jar
DBUtils:commons-dbutils-1.4.jar
c3p0:c3p0-0.9.1.2.jar
MySQL驱动:mysql-connector-java-5.0.8-bin.jar

创建包结构
cn.itcast.customer.web 表现层
cn.itcast.customer.service 业务层
cn.itcast.customer.dao 持久层
cn.itcast.customer.utils 工具包
cn.itcast.customer.domain 实体类 JavaBean

(3)编写代码:
1.创建Customer这个javaBean
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;

2.为了测试方便,向customer表中插入数据
insert into customer values("aaa","tom","男","2010-10-10","13856214587","tom@163.com","吃,喝,玩","vip","good man aaa");
insert into customer values("bbb","fox","女","2000-10-10","13888888888","tom@163.com","吃,喝,玩","vip","good man bbb");
insert into customer values("ccc","james","男","1990-10-10","13693151725","tom@163.com","吃,喝,玩","vip","good man ccc");
insert into customer values("ddd","tom","男","2010-10-10","13888888888","tom@163.com","吃,喝,玩","vip","good man ddd");
insert into customer values("eee","fox","女","2000-10-10","13888888888","tom@163.com","吃,喝,玩","vip","good man eee");
insert into customer values("fff","james","男","1990-10-10","13888888888","tom@163.com","吃,喝,玩","vip","good man fff");
3.实现查询所有客户信息操作
3.1.在success.jsp页面添加连接
<a href="${pageContext.request.contextPath}/findAll">查看所有客户信息</a>
3.2.在CustomerFindAllServlet中调用service,在service中调用dao,最后得到一个List<Customer>.
3.3.在showCustomer.jsp页面展示客户信息
<c:forEach items="${cs}" var="c">
<tr>
<td><input type="checkbox">
</td>
<td>${c.id }</td>
<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>编辑</a>&nbsp;&nbsp;&nbsp;<a>删除</a></td>
</tr>
</c:forEach>

----------------------------------------------------------
4.删除操作
4.1.在showCustomer.jsp页面的删除连接上添加参数 客户的id
<a href="${pageContext.request.contextPath}/delByid?id=${c.id}">删除</a>
4.2.创建一个CustomerDelByIdServlet,获取请求参数,调用service中删除方法.
问题:如果删除完成后,怎样处理?
需要重新跳转到查询所有的servlet中,在重新查询数据。
5.编辑
5.1.查询,做回显示
<a href="${pageContext.request.contextPath}/findById?id=${c.id}">编辑</a>
5.1.1.创建CustomerFindByIdServlet,得到要查询的id,调用service,得到Custonmer对象。
5.1.2.将customer对象存储到request域,请求转发到customerInfo.jsp页面。
5.1.3.在customerInfo.jsp页面展示客户信息
注意:客户的id不能修改,所以使用<input type="hidden">
5.2.修改
5.2.1.注意使用BeanUtils时的类型转换问题
5.2.2.注意编码问题
post:request.setCharacterEncoding("utf-8");
get:手动转换 new String(request.getParameter(name).getBytes("iso8859-1"),"utf-8");
5.2.3.进行修改操作
String sql = "update customer setname=?,gender=?,birthday=?,cellphone=?,email=?,
preference=?,type=?,description=? where id=?";
修改完成后,在重新查询一次
response.sendRedirect(request.getContextPath() + "/findAll");

=================================================================================
解决关于回显示时的问题:
性别 应该使用radio
使用自定义标签
1.定义标签类 extends SimpleTagSupport
2.定义tld文件
<tag>
<name>sex</name><!-- 标签名称 -->
<tag-class>cn.itcast.customer.tag.GenderTag</tag-class><!-- 标签类 -->
<body-content>empty</body-content><!-- 标签体中内容 -->
<attribute>
<name>gender</name> <!-- 属性名称 -->
<required>true</required> <!-- 属性必须有 -->
<rtexprvalue>true</rtexprvalue><!-- 属性值可以接收el表达式 -->
</attribute>
</tag>
3.在页面上使用
3.1.使用taglib导入
3.2.使用
<my:sex gender="${c.gender}" />
-------------------------------------------------------------------------------------------------------
项目目录结构如下:

具体代码如下:
CustomerDao.java
package cn.itcast.customer.dao;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import cn.itcast.customer.domain.Customer;
import cn.itcast.customer.utils.DataSourceUtils;

public class CustomerDao {
	// 查询所有客户
	public List<Customer> findAll() throws SQLException {
		String sql = "select * from customer";

		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		return runner.query(sql, new BeanListHandler<Customer>(Customer.class));
	}

	public void delById(String id) throws SQLException {
		String sql = "delete from customer where id=?";

		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		runner.update(sql, id);
	}

	public Customer findById(String id) throws SQLException {
		String sql = "select * from customer where id=?";
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		return runner.query(sql, new BeanHandler<Customer>(Customer.class), id);
	}

	public void update(Customer c) throws SQLException {

		String sql = "update customer set name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=? where id=?";

		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());

		runner.update(sql, c.getName(), c.getGender(), c.getBirthday(),
				c.getCellphone(), c.getEmail(), c.getPreference(), c.getType(),
				c.getDescription(), c.getId());
	}

}
Customer.java
package cn.itcast.customer.domain;

import java.util.Date;

public class Customer {

	// Id 编号 varchar(40)
	// name 客户姓名 varchar(20)
	// gender 性别 varchar(10)
	// birthday 生日 date
	// cellphone 手机 varchar(20)
	// email 电子邮件 varchar(40)
	// preference 客户爱好 varchar(100)
	// type 客户类型 varchar(40)
	// description 备注 varchar(255)

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

	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", gender=" + gender
				+ ", birthday=" + birthday + ", cellphone=" + cellphone
				+ ", email=" + email + ", preference=" + preference + ", type="
				+ type + ", description=" + description + "]";
	}

}
CustomerService.java
package cn.itcast.customer.service;

import java.sql.SQLException;
import java.util.List;

import cn.itcast.customer.dao.CustomerDao;
import cn.itcast.customer.domain.Customer;

public class CustomerService {

	private CustomerDao dao=new CustomerDao();
	
	//查询所有客户信息操作
	public List<Customer> findAll() throws SQLException {
		
		return dao.findAll();
	}
	//根据id删除
	public void delById(String id) throws SQLException {
		
		dao.delById(id);
	}
	//根据id查询
	public Customer findById(String id) throws SQLException {
		return dao.findById(id);
	}
	//修改客户信息
	public void update(Customer c) throws SQLException {

		dao.update(c);
	}

}
GenderTag.java
package cn.itcast.customer.tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class GenderTag extends SimpleTagSupport {

	private String gender;

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	@Override
	public void doTag() throws JspException, IOException {

		StringBuffer buff = new StringBuffer();

		if ("男".equals(gender)) {
			buff.append("<input type='radio' name='gender' value='男' checked='checked'>男<input type='radio' name='gender' value='女'>女<br>");
		} else {
			buff.append("<input type='radio' name='gender' value='男'>男<input type='radio' name='gender' value='女' checked='checked'>女<br>");
		}

		this.getJspContext().getOut().write(buff.toString());

	}
}
DataSourceUtils.java

package cn.itcast.customer.utils;

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

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DataSourceUtils {

	private static ComboPooledDataSource cpds = new ComboPooledDataSource();

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

	public static DataSource getDataSource() {
		return cpds;
	}

}
CustomerDelByIdServlet.java
package cn.itcast.customer.web.servlet;

import java.io.IOException;
import java.sql.SQLException;

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

import cn.itcast.customer.service.CustomerService;

public class CustomerDelByIdServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		// 1.得到要删除的id
		String id = request.getParameter("id");

		// 2.调用service中根据id删除的方法
		CustomerService service = new CustomerService();

		try {
			service.delById(id);

			// 跳转到CustomerFindAllServlet,就是要重新查询一次
			response.sendRedirect(request.getContextPath() + "/findAll");
			return;
		} catch (SQLException e) {
			e.printStackTrace();
			response.getWriter().write("删除失败");
			return;
		}

	}

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

}
CustomerFindAllServlet.java
package cn.itcast.customer.web.servlet;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

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

import cn.itcast.customer.domain.Customer;
import cn.itcast.customer.service.CustomerService;

public class CustomerFindAllServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");

		// 调用servic中查询所有方法
		CustomerService service = new CustomerService();
		try {
			List<Customer> cs = service.findAll();

			request.setAttribute("cs", cs);

			request.getRequestDispatcher("/showCustomer.jsp").forward(request,
					response);
			return;
		} catch (SQLException e) {
			e.printStackTrace();
			response.getWriter().write("查询客户信息失败");
			return;
		}

	}

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

}
CustomerFindByIdServlet.java
package cn.itcast.customer.web.servlet;

import java.io.IOException;
import java.sql.SQLException;

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

import cn.itcast.customer.domain.Customer;
import cn.itcast.customer.service.CustomerService;

public class CustomerFindByIdServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");

		// 1.得到要查询的id
		String id = request.getParameter("id");

		// 2.调用service中根据id查询的方法.
		CustomerService service = new CustomerService();
		try {
			Customer c = service.findById(id);

			request.setAttribute("c", c);

			request.getRequestDispatcher("/customerInfo.jsp").forward(request,
					response);
			return;

		} catch (SQLException e) {
			e.printStackTrace();
			response.getWriter().write("根据id查询失败");
			return;
		}
	}

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

}

CustomerUpdateServlet.java
package cn.itcast.customer.web.servlet;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;

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

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;

import cn.itcast.customer.domain.Customer;
import cn.itcast.customer.service.CustomerService;

public class CustomerUpdateServlet extends HttpServlet {

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

		// 处理请求编码,
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		// 1.得到所有请求参数 ,封装到javaBean中.

		Customer c = new Customer();

		DateConverter dc = new DateConverter(); // 这是一个日期类型转换器.
		dc.setPattern("yyyy-MM-dd");

		try {
			ConvertUtils.register(dc, java.util.Date.class);
			BeanUtils.populate(c, request.getParameterMap());
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		// 调用service中修改操作
		CustomerService service = new CustomerService();

		try {
			service.update(c);

			// 跳转到CustomerFindAllServlet,就是要重新查询一次
			response.sendRedirect(request.getContextPath() + "/findAll");
			return;

		} catch (SQLException e) {
			e.printStackTrace();
			response.getWriter().write("修改失败");
			return;
		}

	}

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

}
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql:///mydb1</property>
		<property name="user">root</property>
		<property name="password">root</property>
	</default-config>

</c3p0-config>
	
gender.tld
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
	<tlib-version>1.0</tlib-version>
	<short-name>my</short-name>
	<uri>http://www.itcast.cn/tag</uri>

	<tag>
		<name>sex</name><!-- 标签名称 -->
		<tag-class>cn.itcast.customer.tag.GenderTag</tag-class><!-- 标签类 -->
		<body-content>empty</body-content><!-- 标签体中内容 -->

		<attribute>
			<name>gender</name> <!-- 属性名称 -->
			<required>true</required> <!-- 属性必须有 -->
			<rtexprvalue>true</rtexprvalue><!-- 属性值可以接收el表达式 -->
		</attribute>
	</tag>

</taglib>
customerInfo.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib  prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib  prefix="my" uri="http://www.itcast.cn/tag"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  
  <body>
	
	
	<form action="${pageContext.request.contextPath}/update" method="post">
		<input type="hidden" name="id" value="${c.id}">
		
		客户姓名:<input type="text" name="name" value="${c.name}"><br>
		
		客户性别:
			<my:sex gender="${c.gender}"/>
			
		<%--<c:if test="${c.gender=='男'}">
			<input type="radio" name="gender" value="男" checked="checked">男
			<input type="radio" name="gender" value="女">女
		</c:if>
		<c:if test="${c.gender!='男'}">
			<input type="radio" name="gender" value="男">男
			<input type="radio" name="gender" value="女" checked="checked">女
		</c:if>		
		--%>
		
	
		
		客户生日:<input type="text" name="birthday" value="${c.birthday}"><br>
		客户电话:<input type="text" name="cellphone" value="${c.cellphone}"><br>
		客户邮箱:<input type="text" name="email" value="${c.email}"><br>
		客户爱好:<input type="text" name="preference" value="${c.preference}"><br>
		客户类型:<input type="text" name="type" value="${c.type}"><br>
		客户备注:<input type="text" name="description" value="${c.description}"><br>
		<input type="submit" value="修改">
	</form>
	

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

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

<title>My JSP 'index.jsp' starting page</title>

<script type="text/javascript">
	function del(id) {
		
		var flag = window.confirm("确认删除吗");
		
		if (flag) {
			//确认删除
			location.href = "${pageContext.request.contextPath}/delById?id="
					+ id;
		}
	}
</script>
</head>

<body>

	<c:if test="${empty cs}">
		无客户信息
	</c:if>


	<c:if test="${not empty cs}">
		<table border="1" align="center" width="65%">
			<tr>
				<td><input type="checkbox">
				</td>
				<td>客户编号</td>
				<td>客户姓名</td>
				<td>客户性别</td>
				<td>客户生日</td>
				<td>客户电话</td>
				<td>客户邮箱</td>
				<td>客户爱好</td>
				<td>客户类型</td>
				<td>客户备注</td>
				<td>操作</td>
			</tr>

			<c:forEach items="${cs}" var="c">
				<tr>
					<td><input type="checkbox">
					</td>
					<td>${c.id }</td>
					<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="${pageContext.request.contextPath}/findById?id=${c.id}">编辑</a>
					
					 <a href="javascript:void(0)"
						οnclick="del('${c.id}')">删除</a></td>
				</tr>
			</c:forEach>
				<tr>
					<td colspan="11">
						<a>删除选中</a>
					</td>
				</tr>
		</table>
	</c:if>

</body>
</html>
success.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 'index.jsp' starting page</title>
  </head>
  
  <body>

	<a href="${pageContext.request.contextPath}/findAll">查看所有客户信息</a>
  </body>
</html>

运行结果如下:












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值