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

本文主要是介绍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();// 获取DataBaseMetaDataDatabaseMetaData dmd = con.getMetaData();// 获取驱动名称、String driverName = dmd.getDriverName();System.out.println(driverName);// 获取用户名String username = dmd.getUserName();System.out.println(username);// 获取URLString 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);// 获取一个ParameterMetaDataParameterMetaData 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;}@Overridepublic 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 {// 查询@Testpublic 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);}// 添加@Testpublic 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// 使用无参数 的QueryRunnerpublic 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// 使用有参数 的QueryRunnerpublic 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 {// 获取一个预处理的StatementPreparedStatement 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方法@Testpublic void updateTest() throws SQLException {String sql = "delete from account where id=?";MyQueryRunner mqr = new MyQueryRunner();mqr.update(DataSourceUtils.getConnection(), sql, 4);}// 测试select@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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@Testpublic 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对象中@Testpublic 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;}@Overridepublic 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;}@Overridepublic 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.得到要删除的idString 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.得到要查询的idString 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>

运行结果如下:












这篇关于JAVAWEB开发之Tomcat内置连接池的配置和使用、DbUtils的使用详解和案例、以及元数据详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115219

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现