Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。
Druid是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和SQL解析器组成。该项目主要是为了扩展JDBC的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证、统计SQL信息、SQL性能收集、SQL注入检查、SQL翻译等,程序员可以通过定制来实现自己需要的功能。
Druid首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。
Druid支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。
Druid针对Oracle和MySql做了特别优化,比如Oracle的PS Cache内存占用优化,MySql的ping检测优化
首先,强大的监控特性,通过Druid提供的监控功能,可以清楚知道连接池和SQL的工作情况。
其次,方便扩展。Druid提供了Filter-Chain模式的扩展API,可以自己编写Filter拦截JDBC中的任何方法,可以在上面做任何事情,比如说性能监控、SQL审计、用户名密码加密、日志等等。
Druid内置提供了用于监控的StatFilter、日志输出的Log系列Filter、防御SQL注入攻击的WallFilter。
阿里巴巴内部实现了用于数据库密码加密的CirceFilter,以及和Web、Spring关联监控的DragoonStatFilter。
第三,Druid集合了开源和商业数据库连接池的优秀特性,并结合阿里巴巴大规模苛刻生产环境的使用经验进行优化。
Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。
简单SQL语句用时10微秒以内,复杂SQL用时30微秒。
通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter就是通过Druid的SQL Parser分析语义实现的。
Druid的优势是在JDBC最低层进行拦截做判断,不会遗漏。
http://localhost:8080/selectUser.action?id=1
http://localhost:8080/druid/index.html 账号admin,密码admin,在代码中有体现的
4.0.0
com.example
demo
0.0.1-SNAPSHOT
jar
SpringBoot_MyBatis_Diruid
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.4.7.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-devtools
com.alibaba
druid
1.0.18
org.springframework.boot
spring-boot-starter-thymeleaf
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.2.2
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
######################################
###spring datasource
######################################
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
###############################下面Spring的配置文件基本就不用修改了
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.filters=stat,wall,log4j
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
######################################
###spring thymeleaf
######################################
spring.thymeleaf.cache=false
######################################
###MyBatis
######################################
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
druid有一个Servlet和Filter,这里采用编程注入的方式,
package com.example.demo.configBean;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
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 com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
@Configuration
public class DruidConfiguration {
private static final Logger log = LoggerFactory.getLogger(DruidConfiguration.class);
@Bean
public ServletRegistrationBean druidServlet() {
log.info("init Druid Servlet Configuration ");
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(new StatViewServlet());
servletRegistrationBean.addUrlMappings("/druid/*");
Map initParameters = new HashMap();
initParameters.put("loginUsername", "admin");// 用户名
initParameters.put("loginPassword", "admin");// 密码
initParameters.put("resetEnable", "false");// 禁用HTML页面上的“Reset All”功能
initParameters.put("allow", ""); // IP白名单 (没有配置或者为空,则允许所有访问)
// initParameters.put("deny", "192.168.20.38");// IP黑名单
// (存在共同时,deny优先于allow)
servletRegistrationBean.setInitParameters(initParameters);
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
// 添加过滤规则
filterRegistrationBean.addUrlPatterns("/*");
// 添加不需要忽略的格式信息.
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
如果没有配置下面的Bean,它是不会监控到SQL语句的,就是不会有下面箭头指的地方
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
return new DruidDataSource();
}
package com.example.demo.dao;
import org.apache.ibatis.annotations.Mapper;
import com.example.demo.entity.User;
@Mapper
public interface UserMapper {
public User selectByPrimaryKey(Integer id);
}
package com.example.demo.entity;
public class User {
private Integer id;
private String name;
private String username;
private String password;
private Integer sign;
public User() {
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", username=" + username + ", password=" + password + ", sign="
+ sign + "]";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public Integer getSign() {
return sign;
}
public void setSign(Integer sign) {
this.sign = sign;
}
}
package com.example.demo.handler;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.demo.dao.UserMapper;
import com.example.demo.entity.User;
@Controller
public class HelloHandler {
@Autowired
private UserMapper userMapper;
@RequestMapping("/selectUser.action")
public String selectUser(int id,Map map){
User user=userMapper.selectByPrimaryKey(id);
map.put("user", user);
return "/success";
}
}
id, name, username, password, sign
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootMyBatisDruidApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMyBatisDruidApplication.class, args);
}
}