引言

作为程序员,开发工程中,一套利于测试或者监控的工具很重要,mybatis默认没有提供log4j的打印sql语句的配置。

这对于开发rest服务,提供接口的开发者而言,是在很不好做,再加上mybatis很灵活,使用脚本动态生成sql语句,因此,有时候真不知道运行的sql是不是我们所期望的,过滤的条件是否起作用。

所幸,德鲁伊监控平台是个不错的选择,在性能方面druid连接池也比spring原生的要好,因此也是很多企业开发的首选数据源配置。

在引言阶段,我们先看看目前我配置的结果是否是你想要的,如果不是你所期望的,就别浪费时间往下面看,毕竟大家都时间有限,没必要花费时间看一些对自己没用的东西。

控制台打印的日志,慎重的告诉你,这种大量打印信息不能用于生产坏境,生产环境中这些信息写到tomcat的日志文件中了{tomcat的目录}/logs/catalina.out,如果访问量很大的时候,一天产生几GB的日志不是问题–慎用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.Connection: {conn-10001} pool-connect
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.Statement: {conn-10001, pstmt-20025} created.
select * from t_login_register_st WHERE 1 = 1 and ltime >= ? order by ltime desc limit ?, ?
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.Statement: {conn-10001, pstmt-20025} Parameters : [1463414400, 0, 15]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.Statement: {conn-10001, pstmt-20025} Types : [BIGINT, INTEGER, INTEGER]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.Statement: {conn-10001, pstmt-20025} executed. 6.503031 millis.
select * from t_login_register_st WHERE 1 = 1 and ltime >= ? order by ltime desc limit ?, ?
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} open
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Header: [ltime, login_register, register, register_sent_code, register_edit, register_edit_publish, register_edit_succ, login, foget_passwd, foget_passwd_sent_code, login_succ, login_fail, login_succ_normal, login_succ_qq, login_succ_wx, login_succ_wb, login_succ_foget_passwd, login_fail_normal, login_fail_qq, login_fail_wx, login_fail_wb, login_fail_foget_passwd]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464624000, 604, 216, 117, 113, 109, 106, 931, 59, 9, 790, 150, 279, 148, 254, 93, 32, 117, 9, 26, 2, 2]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464537600, 639, 241, 132, 125, 121, 114, 998, 40, 11, 844, 130, 312, 168, 268, 87, 24, 107, 5, 18, 2, 2]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464451200, 674, 322, 175, 170, 160, 155, 1087, 46, 11, 923, 143, 310, 164, 339, 96, 26, 114, 6, 25, 3, 1]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464364800, 794, 371, 187, 182, 168, 162, 1330, 73, 17, 1153, 178, 307, 257, 455, 120, 34, 137, 11, 25, 6, 3]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464278400, 670, 295, 169, 162, 154, 118, 1197, 88, 12, 977, 229, 338, 185, 320, 120, 33, 135, 33, 54, 25, 1]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464192000, 709, 308, 172, 163, 159, 120, 1214, 56, 8, 1065, 292, 383, 196, 349, 122, 30, 148, 54, 78, 30, 1]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464105600, 666, 285, 153, 148, 141, 139, 1120, 75, 14, 970, 159, 328, 188, 294, 141, 38, 132, 11, 14, 3, 0]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1464019200, 586, 254, 146, 141, 136, 132, 1018, 60, 12, 884, 132, 307, 149, 295, 124, 31, 108, 3, 18, 3, 2]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1463932800, 548, 209, 110, 106, 106, 103, 910, 68, 13, 779, 135, 306, 123, 251, 87, 33, 120, 4, 14, 1, 1]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1463846400, 520, 197, 104, 100, 99, 94, 963, 46, 12, 827, 132, 289, 149, 261, 110, 26, 110, 4, 13, 5, 1]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1463760000, 627, 237, 142, 134, 129, 122, 1190, 80, 23, 999, 173, 348, 182, 304, 137, 45, 137, 11, 22, 3, 2]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1463673600, 678, 280, 150, 144, 133, 128, 1235, 75, 8, 1012, 184, 354, 187, 342, 126, 28, 153, 14, 16, 6, 1]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1463587200, 564, 230, 138, 135, 131, 126, 1063, 53, 11, 901, 122, 337, 161, 274, 116, 27, 102, 3, 15, 3, 4]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1463500800, 552, 212, 119, 112, 108, 106, 986, 46, 6, 833, 134, 332, 146, 254, 92, 23, 122, 6, 5, 1, 2]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} Result: [1463414400, 665, 234, 130, 124, 125, 121, 1165, 65, 13, 979, 159, 409, 143, 303, 116, 33, 145, 4, 6, 3, 2]
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.ResultSet: {conn-10001, pstmt-20025, rs-50025} closed
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.Statement: {conn-10001, pstmt-20025} closed
[03/06/16 11:56:03:003 CST] http-nio-8080-exec-2 DEBUG sql.Connection: {conn-10001} pool-recycle

德鲁伊监控平台的视图:

**图一 SQL监控** ![图片描述][1]
**图二 URI监控** ![图片描述][2]

重要的话,重复一遍,如果目前所写对现在的你没用,就算以后可能会用到,你也没必要细看下面所述,到此你已经花费了很多时间了,时间是金钱,伤不起。

如果你坚持要看到这里,请收藏吧!

spring加载properties键值对

其实与spring的配置基本没多大关系,但是因为其加载了数据库的基本信息,所以两个合在一起看一下。

spring-applicationContext.xml的部分配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
">

<task:annotation-driven/>

<context:annotation-config/>

<context:component-scan base-package="cn.test.*"/>

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<!-- 越靠后越有效,取到最后一个有效的未知 -->
<value>classpath:conf/properties/*.properties</value>
</list>
</property>
</bean>
</beans>

properties文件的部分配置:

1
2
3
4
5
mysql.host=127.0.0.1 #你的数据库主机
mysql.port=3306
mysql.database=test # 你的数据库
mysql.user=test # 数据库登录用户
mysql.pwd=123456 # 数据库登录密码

mybatis.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 开启事务注解驱动,管理事务-->
<tx:annotation-driven transaction-manager="txManager"/>

<!-- 在dao层可以使用@Trantional注解管理事务,spring会将注解了事务的类中的所有操作视为事务来管理 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>

<!-- ******前面的这些都是今天的重点,下面是重点的开始,我们配置的数据源是德鲁伊druid数据源,这个才是重点****** -->
<!-- ========================================================-->
<!-- 使用druid作为数据源连接池-->
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close" >
<!-- 数据库的配置,host:主机名,port:端口,database:数据库 -->
<property name="url" value="jdbc:mysql://${mysql.host}:${mysql.port}/${mysql.database}?characterEncoding=utf8" />
<!-- 连接数据的用户名-->
<property name="username" value="${mysql.user}" />
<!-- 连接数据库的密码-->
<property name="password" value="${mysql.pwd}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />

<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="30000" />

<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />

<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />

<property name="testWhileIdle" value="true" />

<!-- 这里建议配置为TRUE,防止取到的连接不可用 -->
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />

<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="false" />

<!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
<property name="validationQuery" value="select 1 " />

<!-- ******重要的配置:监控统计拦截的filters,日志记录 *start* ******-->
<!-- 并在filters属性中配置了log4j,ref中的bean是下面拦截器的配置 -->
<!-- proxyFilters和filters是组合关系,前者是根据bean配置,后者根据别名配置的-->
<!-- stat是statfilter的别名,log4j是logFilter的别名-->
<!-- 监控统计拦截的filters,日志记录,这里开启了stat,wall(sql翻过墙过滤监控),log4j(log4j的监控)配置 -->
<property name="proxyFilters">
<list>
<ref bean="statfilter" />
<ref bean="logFilter" />
</list>
</property>
<property name="filters" value="wall" />
<!-- *end* -->
</bean>

<!-- 慢SQL记录 *start* -->
<bean id="statfilter" class="com.alibaba.druid.filter.stat.StatFilter">
<!-- 开启合并sql -->
<property name="mergeSql" value="true" />
<!-- 开启慢查询语句,1秒 -->
<property name="slowSqlMillis" value="1000" />
<property name="logSlowSql" value="true" />
</bean>

<bean id="logFilter" class="com.alibaba.druid.filter.logging.Log4jFilter">
<!-- <property name="resultSetLogEnabled" value="false" /> -->
<!-- <property name="statementExecutableSqlLogEnable" value="true" /> -->
</bean>
<!-- 慢SQL记录 *end* -->
<!-- ========================================================-->

<!-- 事务增强,这里用的是spring提供的特性-->
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="select*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="has*" read-only="true"/>
<tx:method name="count*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
</tx:attributes>
</tx:advice>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="datasource"/>
</property>
</bean>

<!-- Session Factory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<!-- 下面configLocation这一句是myabtis的其它配置,比如字段值为null的时候,该字段就不返回了,在实际应用中,如果没有其它配置,可以删掉了-->
<property name="configLocation" value="classpath:META-INF/spring/configuration.xml"/>
<!--<property name="mapperLocations" value="classpath:mapper/*mapper.xml"/>-->
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<property name="basePackage" value="cn.test.web.mapper"/>
</bean>
</beans>

上面的配置中,使用<!-- ====== -->包裹的部分时今天配置的重点,其它的配置时开发中的基本配置,也就是说基本的必须配置,不配置不能使用到spring提供的一些特性,当然数据源是必须的配置,但是可以选择spring的数据源连接,不一定是德鲁伊的数据源连接池。

对于配种中看到的<!-- ****** --> 注释的部分更是本文讲的重点,也就是要让程序在控制台打印mybatis的sql语句,这些配置很重要。

1
2
3
4
5
6
<property name="proxyFilters">
<list>
<ref bean="statfilter" />
<ref bean="logFilter" />
</list>
</property>

这里是以代理模式过滤stat和log的,所以用的两个bean分别是stat监控,log日志记录监控。

1
<property name="filters" value="stat,wall,log4j" />

这句的配置才是在控制台打印sql的重点,建议平时开发中,打开该配置,上线的时候关闭掉,原因就是上面提到的,写日志很占空间。

关于druid数据源配置属性的列表,请查看后面:druid连接池配置属性列表详解

web.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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-app_3_0.xsd"
version="3.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/spring/*.xml</param-value>
</context-param>

<!-- 初始化参数,引入log4j配置-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>WEB-INF/classes/log4j.xml</param-value>
</context-param>

<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>

<!-- 开启德鲁伊stat过滤,WebStatFilter用于采集web-jdbc关联监控的数据,注意放在其它的过滤器以及dispatcher前面,很重哦 -->
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>/static/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
</init-param>
<!-- 下面的所有的init-param可以不用配置,使用默认值即可,如果你有处女座情结,删除即可 -->
<!-- 缺省sessionStatMaxCount是1000个。你可以按需要进行配置 -->
<init-param>
<param-name>sessionStatMaxCount</param-name>
<param-value>1000</param-value>
</init-param>
<!-- druid 0.2.7版本开始支持profile,配置profileEnable能够监控单个url调用的sql列表 -->
<init-param>
<param-name>profileEnable</param-name>
<param-value>true</param-value>
</init-param>
<!--
<init-param>
<param-name>principalSessionName</param-name>
<param-value>users.username</param-value>
</init-param> -->

<!-- 你可以关闭session统计功能 -->
<!--
<init-param>
<param-name>sessionStatEnable</param-name>
<param-value>true</param-value>
</init-param> -->
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!--this listener must be defined before the spring listener-->
<listener>
<listener-class>com.alibaba.dubbo.remoting.http.servlet.BootstrapListener</listener-class>
</listener>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- log4j监听器 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

<!-- 德鲁伊监控平台监控器 -->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
<init-param>
<!-- 允许清空统计数据 -->
<param-name>resetEnable</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<!-- 用户名 -->
<param-name>loginUsername</param-name>
<param-value>druid</param-value>
</init-param>
<init-param>
<!-- 密码 -->
<param-name>loginPassword</param-name>
<param-value>druid</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
</web-app>

上面加了注解的配置,是本文配置的重点,其它配置不在这里讲解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 开启德鲁伊stat过滤,WebStatFilter用于采集web-jdbc关联监控的数据-->
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>/static/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

druid对除了静态资源外底所有路由进行监控,该监控采集web-jdbc关联监控的数据。而前面对数据源监控的配置,大部分是sql监控。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<init-param>
<!-- 允许清空统计数据 -->
<param-name>resetEnable</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<!-- 用户名 -->
<param-name>loginUsername</param-name>
<param-value>druid</param-value>
</init-param>
<init-param>
<!-- 密码 -->
<param-name>loginPassword</param-name>
<param-value>druid</param-value>
</init-param>

如果你不希望别人直接查看你的监控,请把查看权限配置加上。如果监控平台被一些不安分的家伙知道,网站面临攻击的可能性就很大,安全性不靠保障,所以建议配置账户信息。

过滤器中的配置,是用来定义我们的监控选项,在以上的监控配置中,上面这段xml代码配置了一个最简单的监控,并采用了大量的默认配置,如果你想使用更丰富的监控配置,可以在druid的github wiki上获取更多的选项,地址:druid Filter 配置

1
2
3
4
5
6
7
8
9
<!-- 德鲁伊监控平台监控器 -->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>

这个是德鲁伊监控平台提供的servlet web服务,启动服务器后,只需要在浏览器中输入:http://127.0.0.1:8080/druid/即可访问引言里面的几个图。

注意,路由根据自己的情况写,如果你直接在idea中配置的,且idea中没有配置context path的话,可以不用项目名。如果配置了,就用配置的名字,比如配置为test,则应该访问http://127.0.0.1:8080/test/druid/

在eclipse中,需要跟项目名的。假如项目时test0,则应该是http://127.0.0.1:8080/test0/druid/。当然了,如果不是这样的话,聪明的你肯定会尝试几次其它形式的路由访问了。

当然还的注意端口号,我这里面默认用了8080,如果你是8090,就换吧。

重轴戏:log4j.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<!-- 注意这里的大小写,配置文件对大小写敏感,主要是后面对该name的引用 -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n"/>
</layout>
</appender>
<appender name="rollingFile" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="logs/server.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{MMdd HH:mm:ss SSS\} %-5p] [%t] %c{3\} - %m%n"/>
</layout>
</appender>

<!-- 配置mybatis打印sql语句 -->

<!-- 这是网上看别人说的,我尝试了,加与不加都没关系,有兴趣自己去尝试
<category name="org.springframework" additivity="false">
<priority value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</category>

<category name="org.springframework.orm.ibatis3" additivity="false">
<priority value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</category>

<category name="org.apache.ibatis" additivity="false">
<priority value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</category>

<category name="java.sql" additivity="false">
<priority value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</category>-->

<!-- ++++++++++++++++++++++++ -->
<!-- druid数据源配置打印日志 start-->
<logger name="druid.sql">
<level value="DEBUG"/>
</logger>
<logger name="druid.sql.DataSource">
<level value="DEBUG"/>
</logger>
<logger name="druid.sql.Connection">
<level value="DEBUG"/>
</logger>
<logger name="druid.sql.Statement">
<level value="DEBUG"/>
</logger>
<logger name="druid.sql.ResultSet">
<level value="DEBUG"/>
</logger>
<!-- druid数据源配置打印日志 end -->
<!-- ++++++++++++++++++++++++ -->

<!-- spring提供的数据源打印日志 -->
<!--
<logger name="com.springframework" additivity="true">
<level value="DEBUG"/>
</logger>
<logger name="com.ibatis" additivity="true">
<level value="DEBUG"/>
</logger>

<logger name="com.ibatis.common.jdbc.SimpleDataSource" additivity="true">
<level value="DEBUG"/>
</logger>
<logger name="com.ibatis.common.jdbc.ScriptRunner" additivity="true">
<level value="DEBUG"/>
</logger>
<logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" additivity="true">
<level value="DEBUG"/>
</logger>
<logger name="Java.sql.Connection" additivity="true">
<level value="DEBUG"/>
</logger>
<logger name="java.sql.Statement" additivity="true">
<level value="DEBUG"/>
</logger>
<logger name="java.sql.PreparedStatement" additivity="true">
<level value="DEBUG"/>
</logger>
<logger name="java.sql.ResultSet" additivity="true">
<level value="DEBUG"/>
</logger>
-->
<root>
<level value="INFO"/>
<!-- 注意ref中的大小写,就是前面配置的appender的name -->
<appender-ref ref="CONSOLE"/>
<!--<appender-ref ref="rollingFile" />-->
</root>
</log4j:configuration>

上面的配置看上去很杂,但是有用的配置用了<!-- ++++++++++++++++++++++++-->包裹起来了,其它的配置都是看网上的配置,有些对配置根本没有,有些事spring数据源监控sql的配置,对于德鲁伊,就包裹部分的足够了,说这句话,并不是让你放弃一些基本配置,基本配置永远不能缺少。

druid连接池配置属性列表详解

配置 缺省值 说明
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/使用ConfigFilter
driverClassName 根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName
initialSize 0 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive 8 最大连接池数量
maxIdle 8 已经不再使用,配置了也没效果
minIdle 最小连接池数量
maxWait 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatements false 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。5.5及以上版本有PSCache,建议开启。
maxOpenPreparedStatements -1 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
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;合并sql的filter:mergeStat
proxyFilters 类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系

补充说明

前面说过,mybatis配置的时候,可以配置sqlSessionFactory的时候通过configLocation属性可以指定mybatis的一些额外配置。

这里分享一段数据库字段值为null时,不返回字段名,而我们希望的是不管值为什么,字段名都应该返回。配置如下:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL MAP Config 3.1//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="callSettersOnNulls" value="true"/>
<setting name="logImpl" value="LOG4J" />
</settings>
</configuration>