Druid是一个强大的新兴数据库连接池,兼容DBCP,是阿里巴巴做的开源项目.
不仅提供了强悍的数据源实现,还内置了一个比较靠谱的监控组件。
GitHub项目主页: https://github.com/alibaba/druid
QQ群: 点击链接加入群【阿里开源技术交流】
常见问题回答请参考: 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
- <filter>
- <filter-name>DruidWebStatFilterfilter-name>
- <filter-class>com.alibaba.druid.support.http.WebStatFilterfilter-class>
- <init-param>
- <param-name>exclusionsparam-name>
- <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,*.jsp,/druid/*,/download/*param-value>
- init-param>
- <init-param>
- <param-name>sessionStatMaxCountparam-name>
- <param-value>2000param-value>
- init-param>
- <init-param>
- <param-name>sessionStatEnableparam-name>
- <param-value>trueparam-value>
- init-param>
- <init-param>
- <param-name>principalSessionNameparam-name>
- <param-value>session_user_keyparam-value>
- init-param>
- <init-param>
- <param-name>profileEnableparam-name>
- <param-value>trueparam-value>
- init-param>
- filter>
- <filter-mapping>
- <filter-name>DruidWebStatFilterfilter-name>
- <url-pattern>/*url-pattern>
- filter-mapping>
- <servlet>
- <servlet-name>DruidStatViewservlet-name>
- <servlet-class>com.alibaba.druid.support.http.StatViewServletservlet-class>
- <init-param>
- <param-name>resetEnableparam-name>
- <param-value>trueparam-value>
- init-param>
- <init-param>
- <param-name>loginUsernameparam-name>
- <param-value>druidparam-value>
- init-param>
- <init-param>
- <param-name>loginPasswordparam-name>
- <param-value>druidparam-value>
- init-param>
- servlet>
- <servlet-mapping>
- <servlet-name>DruidStatViewservlet-name>
- <url-pattern>/druid/*url-pattern>
- servlet-mapping>
下面分享一下如何查找的。
首先,因为使用的是 MAVEN, 所以查看源码时maven会自动帮你下载. 我们在 web.xml 中点击 com.alibaba.druid.support.http.StatViewServlet 进入class文件,等一会源码下载好就可以查看. 发现有类似下面这样的代码:
[java] view plain copy
- public class StatViewServlet extends ResourceSerlvet {
- private final static Log LOG = LogFactory.getLog(StatViewServlet.class);
- private static final long serialVersionUID = 1L;
- public static final String PARAM_NAME_RESET_ENABLE = "resetEnable";
- public static final String PARAM_NAME_JMX_URL = "jmxUrl";
- public static final String PARAM_NAME_JMX_USERNAME = "jmxUsername";
- public static final String PARAM_NAME_JMX_PASSWORD = "jmxPassword";
- private DruidStatService statService = DruidStatService.getInstance();
- /** web.xml中配置的jmx的连接地址 */
- private String jmxUrl = null;
- /** web.xml中配置的jmx的用户名 */
- private String jmxUsername = null;
- /** web.xml中配置的jmx的密码 */
- private String jmxPassword = null;
- .........
可以看出,继承了StatViewServlet extends ResourceSerlvet
而在其中的 jmxUrl、jmxUsername 和 jmxPassword 很显然是连接远程 JMX时使用的,那么我就想着去看看父类: com.alibaba.druid.support.http.ResourceSerlvet
[java] view plain copy
- @SuppressWarnings("serial")
- public abstract class ResourceSerlvet extends HttpServlet {
- private final static Log LOG = LogFactory.getLog(ResourceSerlvet.class);
- public static final String SESSION_USER_KEY = "druid-user";
- public static final String PARAM_NAME_USERNAME = "loginUsername";
- public static final String PARAM_NAME_PASSWORD = "loginPassword";
- public static final String PARAM_NAME_ALLOW = "allow";
- public static final String PARAM_NAME_DENY = "deny";
- public static final String PARAM_REMOTE_ADDR = "remoteAddress";
- protected String username = null;
- protected String password = null;
- ..........
看到了 username 和 password,很高兴,先配置了试试,但是配置这两个初始化参数后没起作用,于是继续查找. 看到了 service方法,我们知道,Servlet的业务逻辑就是从这里开始的。
[java] view plain copy
- public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- ......
- if (isRequireAuth() //
- && !ContainsUser(request)//
- && !("/login.html".equals(path) //
- || path.startsWith("/css")//
- || path.startsWith("/js") //
- || path.startsWith("/img"))) {
- if (contextPath == null || contextPath.equals("") || contextPath.equals("/")) {
- response.sendRedirect("/druid/login.html");
- } else {
- if ("".equals(path)) {
- response.sendRedirect("druid/login.html");
- } else {
- response.sendRedirect("login.html");
- }
- }
- return;
- }
- ......
发现调用了 isRequireAuth() 方法,看着像是判断是否需要授权验证,于是进去看
[java] view plain copy
- public boolean isRequireAuth() {
- return this.username != null;
- }
那现在知道是 username 在作怪,也设置了,但是没有起作用,于是搜索 username ,
[java] view plain copy
- public void init() throws ServletException {
- initAuthEnv();
- }
- private void initAuthEnv() {
- String paramUserName = getInitParameter(PARAM_NAME_USERNAME);
- if (!StringUtils.isEmpty(paramUserName)) {
- this.username = paramUserName;
- }
- String paramPassword = getInitParameter(PARAM_NAME_PASSWORD);
- if (!StringUtils.isEmpty(paramPassword)) {
- this.password = paramPassword;
- }
- ......
然后发现了初始化验证环境时使用了PARAM_NAME_USERNAME这个参数,顺便的学习了一个新API: getInitParameter 方法获取 Servlet的初始化参数, 是HttpServlet的父类 GenericServlet 类提供的:
[java] view plain copy
- String paramUserName = getInitParameter(PARAM_NAME_USERNAME);
那么很简单,找到 PARAM_NAME_USERNAME 即可:
[java] view plain copy
- public static final String PARAM_NAME_USERNAME = "loginUsername";
- public static final String PARAM_NAME_PASSWORD = "loginPassword";
于是在 web.xml 中换上,OK,成功进行了拦截.
你也可以参考这里: CNCounter项目的web.xml