SpringBoot+Druid整合配置如下
1、pom中引入依賴
<!-- Druid 數據連接池依賴 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.27</version>
</dependency>
2、yml中配置數據源
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://xx.xx.xx.xx:3306/xxx?useUnicode=true&characterEncoding=utf-8
username: root
password: xxxxxxxx
type: com.alibaba.druid.pool.DruidDataSource
# 下面爲連接池的補充設置,應用到上面所有數據源中
# 初始化大小,最小,最大
initialSize: 20
minIdle: 20
maxActive: 100
# 配置獲取連接等待超時的時間
maxWait: 60000
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一個連接在池中最小生存的時間,單位是毫秒
minEvictableIdleTimeMillis: 30000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打開PSCache,並且指定每個連接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置監控統計攔截的filters,去掉後監控界面sql無法統計,'wall'用於防火牆
filters: stat,wall,slf4j
# 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合併多個DruidDataSource的監控數據
#useGlobalDataSourceStat: true
以上配置根據自己的需要修改
3、配置監控系統(此處有兩種方法,這裏只介紹一種,因爲我不喜歡在主類上加太多東西。。。)
使用代碼註冊Servlet
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
@Configuration
public class DruidConfiguration {
private static final Logger logger = LoggerFactory.getLogger(DruidConfiguration.class);
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean //聲明其爲Bean實例
@Primary //在同樣的DataSource中,首先使用被標註的DataSource
public DataSource dataSource(){
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
System.err.println("druid configuration initialization filter: "+ e);
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
@Bean
public ServletRegistrationBean druidServlet() {
logger.info("init Druid Servlet Configuration ");
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
// IP白名單
//servletRegistrationBean.addInitParameter("allow", "192.168.1.xxx,127.0.0.1");
// IP黑名單(共同存在時,deny優先於allow)
//servletRegistrationBean.addInitParameter("deny", "192.168.1.xxx");
//控制檯管理用戶
servletRegistrationBean.addInitParameter("loginUsername", "admin");
servletRegistrationBean.addInitParameter("loginPassword", "admin");
//是否能夠重置數據 禁用HTML頁面上的“Reset All”功能
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
配置了以上內容後,我認爲就可以了,於是訪問localhost:8080/druid,也進入了登錄頁,於是我輸入用戶名和密碼admin,admin,點擊sign in,怎麼點都沒反應,於是搜索爲什麼,發現沒有。。。。只能從系統裏面再調試,折騰一番,發現是SpringSecurity的CSRF導致的。。。
這裏有兩個辦法,一個是關閉CSRF,不過這種辦法不友好,還有就是對druid開放,示例代碼如下:
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.servlet.http.HttpServletRequest;
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/hello").hasRole("USER").and()
//.csrf().disable() //關閉CSRF
.csrf().requireCsrfProtectionMatcher(new RequestMatcher() {
@Override
public boolean matches(HttpServletRequest httpServletRequest) {
String servletPath = httpServletRequest.getServletPath();
if (servletPath.contains("/druid")) {
return false;
}
return true;
}
}).and()
.formLogin().loginPage("/login").defaultSuccessUrl("/hello").and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
再去訪問,解決了。。。。————————更正——————————
上面這樣,會導致將原有的驗證覆蓋掉,會出現GET等原先放行的請求無法成功,需改爲如下:
.csrf().requireCsrfProtectionMatcher(new RequestMatcher() { //放行這幾種請求 private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$"); //放行rest請求,當然後面rest與web將會分開,到時這裏可以刪除 private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("^/rest/.*", null); @Override public boolean matches(HttpServletRequest request) { if(allowedMethods.matcher(request.getMethod()).matches()){ return false; } String servletPath = request.getServletPath(); if (servletPath.contains("/druid")) { return false; } return !unprotectedMatcher.matches(request); } })