当我们在使用 JDBC 技术的时候,为了减轻服务器的压力,我们通常采用连接池技术,但是我们怎么引用获取连接池?如果将连接池写死在 Dao 层中很不优雅,并且不直观。如果我们采用注解技术,就可以很方便的为每个 Dao 动态注入一个了连接池。这也是 Spring 框架中采用的技术。
为了注入一个连接池,首先我们必须声明一个注解,注解中有连接数据库常用的属性,当然还有一个连接池的类型,因为我们在注入连接池的时候不知道这个 Dao 想要的是一个什么样的连接池,另外我们为了将连接池注入到 Dao 层中,我们必须将 Dao 层与 Service 层解耦,因为如果让 Dao 直接感染了 Service 层,我们就无法控制 Dao 层中的连接池。解耦采用泛型工厂模式,在创建一个 Dao 实例对象的时候为该 Dao 注入一个连接池。在 Dao 对象中维护着一个包含连接池信息注解字段,我们采用反射技术得到该字段上面的注解信息,从而动态创建一个连接池对象给 Dao 使用。
注解:
package cn.dk.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.mchange.v2.c3p0.DataSources;
@Retention(RetentionPolicy.RUNTIME)
public @interface injectDatasource {
String driverclass() default "com.mysql.jdbc.Driver";
String url() default "jdbc:mysql://localhost:3306/user";
String username() default "root";
String password() default "root";
@SuppressWarnings("unchecked")
Class poolType() default DataSources.class;
}
Dao 层
package cn.dk.dao;
import cn.dk.domain.User;
public interface IUserDao {
User login(String username, String password);
}
package cn.dk.dao.impl;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import cn.dk.annotation.injectDatasource;
import cn.dk.dao.IUserDao;
import cn.dk.domain.User;
public class UserDao implements IUserDao {
@injectDatasource private DataSource source;
public User login(String username, String password) {
QueryRunner runner = new QueryRunner(source);
String sql = "select * from user where username=? and password=?";
Object[] params = { username, password };
try {
return (User) runner.query(sql, new BeanHandler(User.class), params);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
泛型工厂
package cn.dk.factory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.DataSources;
import cn.dk.annotation.injectDatasource;
public class DaoFactory {
private static Properties properties = new Properties();
private static DaoFactory factory = new DaoFactory();
private DaoFactory(){
InputStream inputStream = DaoFactory.class.getClassLoader().getResourceAsStream("daoFactory.properties");
try {
properties.load(inputStream);
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
public static DaoFactory newInstance(){
return factory;
}
@SuppressWarnings("unchecked")
public <T> T getDao(Class<T> clazz){
String key = clazz.getSimpleName();
String className = properties.getProperty(key);
try {
T t = (T) Class.forName(className).newInstance();
injectDataSource(t);
return t;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public void injectDataSource(Object obj){
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
injectDatasource annotation = fields[i].getAnnotation(injectDatasource.class);
if(annotation == null)
continue;
try {
Class poolType = annotation.poolType();
if(poolType==ComboPooledDataSource.class){
ComboPooledDataSource source = new ComboPooledDataSource();
source.setDriverClass(annotation.driverclass());
source.setJdbcUrl(annotation.url());
source.setUser(annotation.username());
source.setPassword(annotation.password());
fields[i].set(obj, source);
}else if(poolType==DataSources.class){
InputStream inputStream = DaoFactory.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties dataProperties = new Properties();
dataProperties.load(inputStream);
DataSource source = BasicDataSourceFactory.createDataSource(dataProperties);
fields[i].set(obj, source);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
Service 层
package cn.dk.service;
import cn.dk.dao.IUserDao;
import cn.dk.domain.User;
import cn.dk.factory.DaoFactory;
public class UserService {
private DaoFactory factory = DaoFactory.newInstance();
private IUserDao userDao = factory.getDao(IUserDao.class);
public User login(String username, String password) {
return userDao.login(username, password);
}
}
Web 层
package cn.dk.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.dk.domain.User;
import cn.dk.service.UserService;
@SuppressWarnings("serial")
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
UserService service = new UserService();
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = service.login(username, password);
if(user == null){
request.setAttribute("message", "密码不正确");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}else{
request.getSession().setAttribute("user", user);
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}