连接池 druid

Druid是一个强大的新兴数据库连接池,兼容DBCP,是阿里巴巴做的开源项目.

不仅提供了强悍的数据源实现,还内置了一个比较靠谱的监控组件。 

GitHub项目主页: https://github.com/alibaba/druid

QQ群:  点击链接加入群【阿里开源技术交流

演示地址: http://cncounter.duapp.com/druid/index.html

常见问题回答请参考: https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

一篇CSDN对Druid的介绍  druid简单教程

因为想要监控数据,又不愿意谁都可以访问,所以想要配置个密码.在开源群里一问,就知道原来内部已经有实现了.

先贴完成后的代码:

web.xml 部分:


[html]  view plain copy
  1. <!-- Druid,监控数据库,以及WEB访问连接信息 -->  
  2. <!-- 参考: https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_%E9%85%8D%E7%BD%AEWebStatFilter -->  
  3. <filter>  
  4.     <filter-name>DruidWebStatFilter</filter-name>  
  5.     <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>  
  6.     <init-param>  
  7.         <param-name>exclusions</param-name>  
  8.         <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,*.jsp,/druid/*,/download/*</param-value>  
  9.     </init-param>  
  10.     <init-param>  
  11.         <param-name>sessionStatMaxCount</param-name>  
  12.         <param-value>2000</param-value>  
  13.     </init-param>  
  14.     <init-param>  
  15.         <param-name>sessionStatEnable</param-name>  
  16.         <param-value>true</param-value>  
  17.     </init-param>  
  18.     <init-param>  
  19.         <param-name>principalSessionName</param-name>  
  20.         <param-value>session_user_key</param-value>  
  21.     </init-param>  
  22.     <init-param>  
  23.         <param-name>profileEnable</param-name>  
  24.         <param-value>true</param-value>  
  25.     </init-param>  
  26. </filter>  
  27. <filter-mapping>  
  28.     <filter-name>DruidWebStatFilter</filter-name>  
  29.     <url-pattern>/*</url-pattern>  
  30. </filter-mapping>  
  31. <!-- 配置 Druid 监控信息显示页面 -->  
  32. <servlet>  
  33.     <servlet-name>DruidStatView</servlet-name>  
  34.     <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  
  35.     <init-param>  
  36.         <!-- 允许清空统计数据 -->  
  37.         <param-name>resetEnable</param-name>  
  38.         <param-value>true</param-value>  
  39.     </init-param>  
  40.     <init-param>  
  41.         <!-- 用户名 -->  
  42.         <param-name>loginUsername</param-name>  
  43.         <param-value>druid</param-value>  
  44.     </init-param>  
  45.     <init-param>  
  46.         <!-- 密码 -->  
  47.         <param-name>loginPassword</param-name>  
  48.         <param-value>druid</param-value>  
  49.     </init-param>  
  50. </servlet>  
  51. <servlet-mapping>  
  52.     <servlet-name>DruidStatView</servlet-name>  
  53.     <url-pattern>/druid/*</url-pattern>  
  54. </servlet-mapping>  

下面分享一下如何查找的。


首先,因为使用的是 MAVEN, 所以查看源码时maven会自动帮你下载. 我们在 web.xml 中点击com.alibaba.druid.support.http.StatViewServlet 进入class文件,等一会源码下载好就可以查看. 发现有类似下面这样的代码: 


[java]  view plain copy
  1. public class StatViewServlet extends ResourceSerlvet {  
  2.   
  3.     private final static Log      LOG                     = LogFactory.getLog(StatViewServlet.class);  
  4.   
  5.     private static final long     serialVersionUID        = 1L;  
  6.   
  7.     public static final String    PARAM_NAME_RESET_ENABLE = "resetEnable";  
  8.   
  9.     public static final String    PARAM_NAME_JMX_URL      = "jmxUrl";  
  10.     public static final String    PARAM_NAME_JMX_USERNAME = "jmxUsername";  
  11.     public static final String    PARAM_NAME_JMX_PASSWORD = "jmxPassword";  
  12.   
  13.     private DruidStatService      statService             = DruidStatService.getInstance();  
  14.   
  15.     /** web.xml中配置的jmx的连接地址 */  
  16.     private String                jmxUrl                  = null;  
  17.     /** web.xml中配置的jmx的用户名 */  
  18.     private String                jmxUsername             = null;  
  19.     /** web.xml中配置的jmx的密码 */  
  20.     private String                jmxPassword             = null;  
  21. .........  

可以看出,继承了 StatViewServlet  extends  ResourceSerlvet


而在其中的 jmxUrl、jmxUsername 和 jmxPassword 很显然是连接远程 JMX时使用的,那么我就想着去看看父类: com.alibaba.druid.support.http.ResourceSerlvet


[java]  view plain copy
  1. @SuppressWarnings("serial")  
  2. public abstract class ResourceSerlvet extends HttpServlet {  
  3.   
  4.     private final static Log   LOG                 = LogFactory.getLog(ResourceSerlvet.class);  
  5.   
  6.     public static final String SESSION_USER_KEY    = "druid-user";  
  7.     public static final String PARAM_NAME_USERNAME = "loginUsername";  
  8.     public static final String PARAM_NAME_PASSWORD = "loginPassword";  
  9.     public static final String PARAM_NAME_ALLOW    = "allow";  
  10.     public static final String PARAM_NAME_DENY     = "deny";  
  11.     public static final String PARAM_REMOTE_ADDR   = "remoteAddress";  
  12.   
  13.     protected String           username            = null;  
  14.     protected String           password            = null;  
  15. ..........  

看到了 username 和 password,很高兴,先配置了试试,但是配置这两个初始化参数后没起作用,于是继续查找. 看到了 service方法,我们知道,Servlet的业务逻辑就是从这里开始的。



[java]  view plain copy
  1. public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  2.     ......  
  3.     if (isRequireAuth() //  
  4.         && !ContainsUser(request)//  
  5.         && !("/login.html".equals(path) //  
  6.              || path.startsWith("/css")//  
  7.              || path.startsWith("/js"//  
  8.         || path.startsWith("/img"))) {  
  9.         if (contextPath == null || contextPath.equals("") || contextPath.equals("/")) {  
  10.             response.sendRedirect("/druid/login.html");  
  11.         } else {  
  12.             if ("".equals(path)) {  
  13.                 response.sendRedirect("druid/login.html");  
  14.             } else {  
  15.                 response.sendRedirect("login.html");  
  16.             }  
  17.         }  
  18.         return;  
  19.     }  
  20. ......  

发现调用了   isRequireAuth()  方法,看着像是判断是否需要授权验证,于是进去看



[java]  view plain copy
  1. public boolean isRequireAuth() {  
  2.     return this.username != null;  
  3. }  


那现在知道是 username 在作怪,也设置了,但是没有起作用,于是搜索 username ,

[java]  view plain copy
  1. public void init() throws ServletException {  
  2.     initAuthEnv();  
  3. }  
  4.   
  5. private void initAuthEnv() {  
  6.     String paramUserName = getInitParameter(PARAM_NAME_USERNAME);  
  7.     if (!StringUtils.isEmpty(paramUserName)) {  
  8.         this.username = paramUserName;  
  9.     }  
  10.   
  11.     String paramPassword = getInitParameter(PARAM_NAME_PASSWORD);  
  12.     if (!StringUtils.isEmpty(paramPassword)) {  
  13.         this.password = paramPassword;  
  14.     }  
  15.   ......  
然后发现了初始化验证环境时使用了PARAM_NAME_USERNAME这个参数,顺便的学习了一个新API: getInitParameter 方法获取 Servlet的初始化参数, 是HttpServlet的父类 GenericServlet 类提供的:
[java]  view plain copy
  1. String paramUserName = getInitParameter(PARAM_NAME_USERNAME);  
那么很简单,找到  PARAM_NAME_USERNAME  即可:
[java]  view plain copy
  1. public static final String PARAM_NAME_USERNAME = "loginUsername";  
  2. public static final String PARAM_NAME_PASSWORD = "loginPassword";  
于是在 web.xml 中换上,OK,成功进行了拦截.

https://github.com/alibaba/druid/wiki/DruidDataSource 配置属性列表

配置

缺省值

说明

name

配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。
如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this)

jdbcUrl

连接数据库的url,不同数据库不一样。例如:
mysql : jdbc:mysql://10.20.153.104:3306/druid2 
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto

username

连接数据库的用户名

password

连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter

driverClassName

根据url自动识别

这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName

initialSize

0

初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection

maxActive

8

最大连接池数量

maxIdle

8

已经不再使用,配置了也没效果

minIdle

最小连接池数量

maxWait

获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。

poolPreparedStatements

false

是否缓存preparedStatement,也就是PSCachePSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。

maxOpenPreparedStatements

-1

要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在OraclePSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100

validationQuery

用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuerynulltestOnBorrowtestOnReturntestWhileIdle都不会其作用。

testOnBorrow

true

申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

testOnReturn

false

归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能

testWhileIdle

false

建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

timeBetweenEvictionRunsMillis

有两个含义:
1) Destroy
线程会检测连接的间隔时间 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明

numTestsPerEvictionRun

不再使用,一个DruidDataSource只支持一个EvictionRun

minEvictableIdleTimeMillis

connectionInitSqls

物理连接初始化的时候执行的sql

exceptionSorter

根据dbType自动识别

当数据库抛出一些不可恢复的异常时,抛弃连接

filters

属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall

proxyFilters

类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filtersproxyFilters,是组合关系,并非替换关系

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9399028/viewspace-1821979/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/9399028/viewspace-1821979/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值