一:导包
com.alibaba
druid
1.1.10
二:配置
用的是druid的连接池,jpa的自动建表,mytabis框架
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
mybatis:
type-aliases-package: com.tom.bean
mapper-locations: classpth:mapper/*mapper.xml
druid的额外配置
# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
# 校验SQL,Oracle配置 spring.datasource.validationQuery=SELECT 1 FROM DUAL,如果不配validationQuery项,则下面三项配置无用
spring.datasource.validationQuery=SELECT 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
spring.datasource.useGlobalDataSourceStat=true
三:Mapper,Service,Controller
bean,用的自动建表
@Entity
public class teacher implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private int age;
...
}
mapper,暂时只写两个方法
@Mapper
public interface teachMapper {
@Insert("insert into teacher values(null,#{age},#{name})")
public void save(teacher t);
@Select("select * from teacher where id=#{id}")
public teacher getById(int id);
}
service
@Service
public class teachService {
@Autowired
private teachMapper tm;
public teacher getById(int id) {
return tm.getById(id);
}
public void save(teacher t) {
tm.save(t);
}
}
Controller
@RestController
@RequestMapping("/teacher")
public class teachController {
@Autowired
private teachService ts;
@GetMapping("/{id}")
public teacher get(@PathVariable("id") int id) {
return ts.getById(id);
}
@PostMapping("/save")
public String save(teacher t) {
ts.save(t);
return "保存成功";
}
}
四:druid配置
用druid的原因:一个因为听说它性能很强,另一个主要的原因为可以进行实时监控
@WebFilter(filterName="druidWebStatFilter",urlPatterns="/*",
initParams={
@WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源
})
public class DruidStatFilter extends WebStatFilter {
}
@SuppressWarnings("serial")
@WebServlet(urlPatterns = "/druid/*",
initParams = { @WebInitParam(name = "allow", value = "127.0.0.1"), // IP白名单
@WebInitParam(name = "deny", value = "192.168.0.0"), // IP黑名单 (存在共同时,deny优先于allow)
@WebInitParam(name = "loginUsername", value = "admin"), // 用户名
@WebInitParam(name = "loginPassword", value = "admin"), // 密码
@WebInitParam(name = "resetEnable", value = "false")// 禁用HTML页面上的“Reset All”功能
})
public class DruidStatViewServlet extends StatViewServlet {
}
最后,在启动类上面加上@ServletComponentScan
@SpringBootApplication
//注意要加上@ServletComponentScan注解,否则Servlet无法生效
@ServletComponentScan
public class TomApplication {
public static void main(String[] args) {
SpringApplication.run(TomApplication.class, args);
}
}
五,启动项目,登录http://localhost:8080/druid/index.html 查看监控情况
简直优秀。
配置Redis
spring:
redis:
host: localhost
port: 6379
database: 1
jedis:
pool:
max-idle: 8
min-idle: 1
max-active: 8
max-wait: -1
接下来的步骤:①开启mybatis的二级缓存 ②重写缓存类 ③将mybatis的缓存替换为们重写的
主要的作用如下:
1.所有在映射文件里的 select 语句都将被缓存。
2.所有在映射文件里 insert,update 和 delete 语句会清空缓存。
3.缓存使用“最近很少使用”算法来回收
4.缓存不会被设定的时间所清空。
一:开启二级缓存,配置中加一条就好
mybatis:
configuration:
cache-enabled: true
二:重写缓存类
这里也有一个问题,由于cache不是容器中的类,我们需要获得applicationContext
@Component
public class ApplicationContextHolder implements ApplicationContextAware{
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
*/
public void setApplicationContext(ApplicationContext applicationContext) {
ApplicationContextHolder.applicationContext = applicationContext; // NOSONAR
}
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
checkApplicationContext();
return applicationContext;
}
/**
* 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static T getBean(String name) {
checkApplicationContext();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static T getBean(Class clazz) {
checkApplicationContext();
return (T) applicationContext.getBeansOfType(clazz);
}
/**
* 清除applicationContext静态变量.
*/
public static void cleanApplicationContext() {
applicationContext = null;
}
private static void checkApplicationContext() {
if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
}
}
}
重写缓存类
public class RedisCache implements Cache {
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final String id; // cache instance id
private RedisTemplate redisTemplate;
private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
public RedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
@Override
public String getId() {
return id;
}
/**
* Put query result to redis
*
* @param key
* @param value
*/
@Override
@SuppressWarnings("unchecked")
public void putObject(Object key, Object value) {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
System.out.println("放入结果到缓存");
}
/**
* Get cached query result from redis
*
* @param key
* @return
*/
@Override
public Object getObject(Object key) {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
System.out.println("获取结果从缓存");
return opsForValue.get(key);
}
/**
* Remove cached query result from redis
*
* @param key
* @return
*/
@Override
@SuppressWarnings("unchecked")
public Object removeObject(Object key) {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.delete(key);
System.out.println("从缓存删除了");
return null;
}
/**
* Clears this cache instance
*/
@Override
public void clear() {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.execute((RedisCallback) connection -> {
connection.flushDb();
return null;
});
System.out.println("清空缓存");
}
@Override
public int getSize() {
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
private RedisTemplate getRedisTemplate() {
if (redisTemplate == null) {
redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
}
return redisTemplate;
}
}
我在映射文件中写了增,删,查3个方法
insert into teacher values(null,#{age},#{name})
delete from teacher where id=#{id}
OK!!让我看一下效果
结果为:select会添加数据到redis,insert,update,delete会清空缓存
但是这样子好像有点坑了,除select外的操作都要清空缓存,有待研究