共享一劳永逸的数据库编码解决方案
2007-05-19 09:42:22 来源:WEB开发网我们知道进行编码和转码工作都是集中在JDBC的两个接口PreparedStatement和ResultSet上进行的,主要涉及PreparedStatement的setString方法以及ResultSet的getString方法。前面我们讲过需要加入一个连接封装层来对数据库连接实例进行二次封装,但是怎么通过这个封装来改变PreparedStatement和ResultSet这两个接口的行为呢?这个问题其实也很简单,因为PreparedStatement接口必须通过Connection接口来获取实例,而ResultSet接口又必须从Statement或者PreparedStatement接口来获取实例,有了这样的级联关系,问题也就迎刃而解了。还是利用我在文章《使用JAVA动态代理实现数据库连接池》中使用的动态接口代理技术。首先我们设计Connection接口的代理类_Connection,这个代理类接管了Connection接口中所有可能获取到Statement或者PreparedStatement接口实例的方法,例如:prepareStatement和createStatement。改变这两个方法使之返回的是经过接管后的Statement或者PreparedStatement实例。通过对于Statement接口也有相应的代理类_Statement,这个代理类接管用于获取ResultSet接口实例的所有方法,包括对setString方法的接管以决定是否对字符串进行编码处理。对于接口ResultSet的接管类_ResultSet就相应的比较简单,它只需要处理getString方法即可。
关键代码
前面我们大概介绍了这个解决方案的思路,下面我们给出关键的实现代码包括Connection的代理类,Statement的代理类,ResultSet的代理类。这些代码是在原来关于数据库连接池实现的基础上进行扩充使之增加对自动编码处理的功能。有需要源码打包的可以通过电子邮件跟我联系。
_Connection.java
/*
* Created on 2003-10-23 by Liudong
*/package lius.pool;import java.sql.*;import java.lang.reflect.*;
/ *
*
* 数据库连接的代理类
* @author Liudong
*/
class _Connection implements InvocationHandler{
private Connection conn = null;
private boolean coding = false;
//指定是否进行字符串转码操作
_Connection(Connection conn, boolean coding){
this.conn = conn;
this.coding = coding;
initConnectionParam(this.conn);
}
/**
* Returns the conn.
* @return Connection
*/
public Connection getConnection() {
Class[] interfaces =conn.getClass().getInterfaces();
if(interfaces==null||interfaces.length==0){
interfaces = new Class[1];
interfaces[0] = Connection.class;
}
Connection conn2 = (Connection)Proxy.newProxyInstance(
conn.getClass().getClassLoader(), interfaces,this);
return conn2;
}
/**
* @see java.lang.reflect.InvocationHandler#invoke
*/
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
String method = m.getName();
//调用相应的操作
Object obj = null;
try{
obj = m.invoke(conn, args);
//接管用于获取语句句柄实例的方法
if((CS.equals(method)||PS.equals(method))&&coding)
return new _Statement((Statement)obj,true).getStatement();
} catch(InvocationTargetException e) {
throw e.getTargetException();
}
return obj;
} private final static String PS = "prepareStatement";
private final static String CS = "createStatement";}
_Statement.java
/*
* Created on 2003-10-23 by Liudong
*/
package lius.pool;
import java.sql.*;
import java.lang.reflect.*;
/**
* 数据库语句对象实例的代理类
* @author Liudong
*/
class _Statement implements InvocationHandler{
private Statement statement ; //保存所接管对象的实例
private boolean decode = false; //指定是否进行字符串转码
public _Statement(Statement stmt,boolean decode) {
this.statement = stmt;
this.decode = decode;
}
/**
* 获取一个接管后的对象实例
* @return
*/
public Statement getStatement() {
Class[] interfaces = statement.getClass().getInterfaces();
if(interfaces==null||interfaces.length==0){
interfaces = new Class[1];
interfaces[0] = Statement.class;
}
Statement stmt = (Statement)Proxy.newProxyInstance(
statement.getClass().getClassLoader(),
interfaces,this);
return stmt;
}
/**
* 方法接管
*/
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
String method = m.getName(); //接管setString方法
if(decode && SETSTRING.equals(method)) {
try{
String param = (String)args[1];
if(param!=null)
param = new String(param.getBytes(),"8859_1");
return m.invoke(statement,new Object[]{args[0],param});
} catch(InvocationTargetException e){
throw e.getTargetException(); }
}
//接管executeQuery方法
if(decode && EXECUTEQUERY.equals(method)){
try{
ResultSet rs = (ResultSet)m.invoke(statement,args);
return new _ResultSet(rs,decode).getResultSet();
}catch(InvocationTargetException e){
throw e.getTargetException();
}
}
try{
return m.invoke(statement, args);
} catch(InvocationTargetException e) {
throw e.getTargetException();
}
}
//两个要接管的方法名
private final static String SETSTRING = "setString";
private final static String EXECUTEQUERY = "executeQuery";
}
_ResultSet.java
/*
* Created on 2003-10-23 by Liudong
*/
package lius.pool;
import java.sql.ResultSet;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 数据库结果集的代理类
* @author Liudong
*/
class _ResultSet implements InvocationHandler{
private ResultSet rs = null;
private boolean decode = false;
public _ResultSet(ResultSet rs,boolean decode) {
this.rs = rs;
this.decode = decode;
}
public ResultSet getResultSet(){
Class[] interfaces = rs.getClass().getInterfaces();
if(interfaces==null||interfaces.length==0){
interfaces = new Class[1];
interfaces[0] = ResultSet.class;
}
ResultSet rs2 = (ResultSet)Proxy.newProxyInstance(rs.getClass().getClassLoader(),
interfaces,this);
return rs2;
}
/**
* 结果getString方法
*/
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
String method = m.getName();
if(decode && GETSTRING.equals(method)){
try{
String result = (String)m.invoke(rs,args);
if(result!=null)
return new String(result.getBytes("8859_1"));
return null;
}catch(InvocationTargetException e){
throw e.getTargetException();
}
}
try{
return m.invoke(rs, args);
}catch(InvocationTargetException e){
throw e.getTargetException();
}
}
private final static String GETSTRING = "getString";
}
赞助商链接