application.yml
server:
port: 80
spring:
application:
name: cloud-druid-service
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_cloud?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
http:
encoding:
charset: UTF-8
force-request: true
force-response: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
default-property-inclusion: non_empty
serialization:
fail_on_empty_beans: false
mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml
config-location: classpath:mybatis/mybatis-spring.xml
DruidConfig.java
// 寫(xiě)庫(kù)的時(shí)候都應(yīng)該加上 @ConditionalOnMissingBean 注解,避免同類(lèi)型庫(kù)之間發(fā)生沖突
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnClass(DruidDataSource.class)
@Configuration
public class DruidConfig {
private Logger logger = LoggerFactory.getLogger(DruidConfig.class);
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
try {
// 啟動(dòng)程序時(shí)优妙,在連接池中初始化多少個(gè)連接(10-50已足夠)
dataSource.setInitialSize(50);
// 回收空閑連接時(shí)井辆,將保證至少有 minIdle 個(gè)連接(與 initialSize 相同)
dataSource.setMinIdle(50);
// 連接池中最多支持多少個(gè)活動(dòng)會(huì)話(huà)
dataSource.setMaxActive(10000);
// 程序向連接池中請(qǐng)求連接時(shí),超過(guò) maxWait 的值后益兄,認(rèn)為本次請(qǐng)求失敗脊凰,即連接池抖棘,沒(méi)有可用連接,單位毫秒狸涌,設(shè)置 -1 時(shí)表示無(wú)限等待(建議值為100)
dataSource.setMaxWait(100);
/*
緩存通過(guò)以下兩個(gè)方法發(fā)起的 SQL:
public PreparedStatement prepareStatement(String sql)
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
(建議值為 true)
*/
dataSource.setPoolPreparedStatements(true);
// 每個(gè)連接最多緩存多少個(gè) SQL(建議值為 20)
dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
// 檢查空閑連接的頻率切省,單位毫秒,非正整數(shù)時(shí)表示不進(jìn)行檢查(建議值:2000)
dataSource.setTimeBetweenEvictionRunsMillis(2000);
// 連接池中某個(gè)連接的空閑時(shí)長(zhǎng)達(dá)到 N 毫秒后, 連接池在下次檢查空閑連接時(shí)帕胆,將回收該連接朝捆,要小于防火墻超時(shí)設(shè)置 net.netfilter.nf_conntrack_tcp_timeout_established 的設(shè)置
dataSource.setMinEvictableIdleTimeMillis(600000);
// 配置一個(gè)連接在池中最大生存的時(shí)間,單位是毫秒
dataSource.setMaxEvictableIdleTimeMillis(900000);
// 程序沒(méi)有 close 連接且空閑時(shí)長(zhǎng)超過(guò) minEvictableIdleTimeMillis懒豹,則會(huì)執(zhí)行 validationQuery 指定的 SQL芙盘,以保證該程序連接不會(huì)池 kill 掉,其范圍不超過(guò) minIdle 指定的連接個(gè)數(shù)(建議值為 true)
dataSource.setKeepAlive(true);
// 檢查池中的連接是否仍可用的 SQL 語(yǔ)句脸秽,druid 會(huì)連接到數(shù)據(jù)庫(kù)執(zhí)行該 SQL儒老,如果正常返回,則表示連接可用记餐,否則表示連接不可用
dataSource.setValidationQuery("SELECT 1");
// 當(dāng)程序請(qǐng)求連接驮樊,池在分配連接時(shí),是否先檢查該連接是否有效(高效,并且保證安全性囚衔;建議值為 true)
dataSource.setTestWhileIdle(true);
// 程序申請(qǐng)連接時(shí)铝穷,進(jìn)行連接有效性檢查(低效,影響性能佳魔;建議值為 false)
dataSource.setTestOnBorrow(false);
// 程序返還連接時(shí),進(jìn)行連接有效性檢查(低效晦炊,影響性能鞠鲜;建議值為 false)
dataSource.setTestOnReturn(false);
// 物理連接初始化的時(shí)候執(zhí)行的 sql
Collection<String> connectionInitSqls = new ArrayList<>(10);
connectionInitSqls.add("SELECT 1 FROM DUAL");
dataSource.setConnectionInitSqls(connectionInitSqls);
/*
這里配置的是插件,常用的插件有:
監(jiān)控統(tǒng)計(jì):stat
日志監(jiān)控:log4j2
防御 SQL 注入:wall
*/
dataSource.setFilters("stat,log4j2");
// 是否合并多個(gè) DruidDataSource 的監(jiān)控?cái)?shù)據(jù)
dataSource.setUseGlobalDataSourceStat(true);
// 監(jiān)控統(tǒng)計(jì)
// 是否啟用慢 SQL 記錄
dataSource.addConnectionProperty("druid.stat.logSlowSql", "true");
// 執(zhí)行時(shí)間超過(guò) slowSqlMillis 的就是慢断国,單位毫秒(建議值 500)
dataSource.addConnectionProperty("druid.stat.slowSqlMillis", "500");
// 要求程序從池中 get 到連接后贤姆,N 秒后必須 close,否則 druid 會(huì)強(qiáng)制回收該連接稳衬,不管該連接中是活動(dòng)還是空閑霞捡,以防止進(jìn)程不會(huì)進(jìn)行 close 而霸占連接(建議值為 false,當(dāng)發(fā)現(xiàn)程序有未正常 close 連接時(shí)設(shè)置為 true)
// dataSource.setRemoveAbandoned(false);
// 設(shè)置 druid 強(qiáng)制回收連接的時(shí)限薄疚,當(dāng)程序從池中 get 到連接開(kāi)始算起碧信,超過(guò)此值后,druid將強(qiáng)制回收該連接街夭,單位秒(應(yīng)大于業(yè)務(wù)運(yùn)行最長(zhǎng)時(shí)間)
// dataSource.setRemoveAbandonedTimeout();
// 當(dāng) druid 強(qiáng)制回收連接后砰碴,是否將 stack trace 記錄到日志中(建議值為 true)
// dataSource.setLogAbandoned(true);
// 連接屬性。比如設(shè)置一些連接池統(tǒng)計(jì)方面的配置 druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
// dataSource.setConnectProperties();
// 防御 SQL 注入
WallFilter wallFilter = new WallFilter();
WallConfig config = new WallConfig();
// 是否允許執(zhí)行 DELETE 語(yǔ)句(建議值為 false)
config.setDeleteAllow(false);
// 是否允許刪除表(建議值為 false)
config.setDropTableAllow(false);
wallFilter.setConfig(config);
// 插件代理
List<Filter> proxyFilters = new ArrayList<>(10);
proxyFilters.add(wallFilter);
dataSource.setProxyFilters(proxyFilters);
} catch (SQLException e) {
logger.error(e.toString());
}
return dataSource;
}
@Bean
public ServletRegistrationBean<StatViewServlet> statViewServlet() {
// 監(jiān)控信息顯示頁(yè)面
StatViewServlet statViewServlet = new StatViewServlet();
// 訪(fǎng)問(wèn)監(jiān)控信息顯示頁(yè)面的 url 路徑(建議值為 /druid/* )
String urlPattern = "/druid/*";
ServletRegistrationBean<StatViewServlet> bean =
new ServletRegistrationBean<>(statViewServlet, urlPattern);
Map<String, String> initParams = new HashMap<>();
// 是否允許清空統(tǒng)計(jì)數(shù)據(jù)
initParams.put("resetEnable", "false");
// 登錄監(jiān)控信息顯示頁(yè)面的用戶(hù)名
initParams.put("loginUsername", "admin");
// 登錄監(jiān)控信息顯示頁(yè)面的密碼
initParams.put("loginPassword", "admin");
// 允許訪(fǎng)問(wèn)控制(格式:ip地址板丽、ip地址/子網(wǎng)掩碼位數(shù))逗號(hào)分隔多個(gè)地址
initParams.put("allow", "127.0.0.1");
// 拒絕訪(fǎng)問(wèn)控制(格式:ip地址呈枉、ip地址/子網(wǎng)掩碼位數(shù))逗號(hào)分隔多個(gè)地址
// initParams.put("deny", "");
bean.setInitParameters(initParams);
return bean;
}
@Bean
public FilterRegistrationBean<WebStatFilter> webStatFilter() {
FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>();
// 網(wǎng)絡(luò)監(jiān)控過(guò)濾器(用于采集 web-jdbc 關(guān)聯(lián)監(jiān)控的數(shù)據(jù))
bean.setFilter(new WebStatFilter());
// 過(guò)濾所有的 url 路徑
Collection<String> urlPatterns = new ArrayList<>();
urlPatterns.add("/*");
bean.setUrlPatterns(urlPatterns);
Map<String, String> initParams = new HashMap<>();
// 排除不必要采集的 url 路徑,以逗號(hào)“,”分割
initParams.put("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,*.map,/druid/*");
// 是否使用 session 監(jiān)控功能
initParams.put("sessionStatEnable", "true");
// 是否使用 session 監(jiān)控最大數(shù)量(默認(rèn)是1000)
initParams.put("sessionStatMaxCount", "1000");
// 使得 druid 能夠知道當(dāng)前的 session 的用戶(hù)是誰(shuí)埃碱,根據(jù)需要猖辫,把改值修改為你 user 信息保存在 session 中的 sessionName
initParams.put("principalSessionName", "session_user_key");
// 如果你的 user 信息保存在 cookie 中,你可以配置 principalCookieName砚殿,使得 druid 知道當(dāng)前的 user 是誰(shuí)啃憎,根據(jù)需要,把該值修改為你 user 信息保存在 cookie 中的 cookieName
initParams.put("principalCookieName", "cookie_user_key");
// 是否監(jiān)控單個(gè) url 調(diào)用的 sql 列表
initParams.put("profileEnable", "true");
bean.setInitParameters(initParams);
return bean;
}
}
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者