分页
1. pom.xml配置
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-aop</ artifactId>
</ dependency>
< dependency>
< groupId> com.github.pagehelper</ groupId>
< artifactId> pagehelper-spring-boot-starter</ artifactId>
< version> 1.2.12</ version>
</ dependency>
2.application.properties
# -------------------- pagehelper B ---------------------------
pagehelper.helper-dialect= mysql
#pagehelper.reasonable=true
#pagehelper.support-methods-arguments=true
#pagehelper.params=count=countSql
# -------------------- pagehelper E ---------------------------
3.PageBean.java, PagingInterceptor.java,拷入项目中
3.1、PageBean.java
package com. example. sbdemo03. util ;
import org. springframework. util. StringUtils ;
import javax. servlet. http. HttpServletRequest ;
import java. util. Map ;
public class PageBean {
private int page = 1 ;
private int rows = 10 ;
private int total = 0 ;
private boolean pagination = true ;
private String url;
private Map < String , String [ ] > parameterMap;
public Map < String , String [ ] > getParameterMap ( ) {
return parameterMap;
}
public void setParameterMap ( Map < String , String [ ] > parameterMap) {
this . parameterMap = parameterMap;
}
public String getUrl ( ) {
return url;
}
public void setUrl ( String url) {
this . url = url;
}
public void setRequest ( HttpServletRequest request) {
if ( ! StringUtils . isEmpty ( request. getParameter ( "page" ) ) ) {
this . setPage ( Integer . valueOf ( request. getParameter ( "page" ) ) ) ;
}
if ( ! StringUtils . isEmpty ( request. getParameter ( "rows" ) ) ) {
this . setRows ( Integer . valueOf ( request. getParameter ( "rows" ) ) ) ;
}
if ( ! StringUtils . isEmpty ( request. getParameter ( "pagination" ) ) ) {
this . setPagination ( Boolean . valueOf ( request. getParameter ( "pagination" ) ) ) ;
}
this . url = request. getRequestURI ( ) ;
Map < String , String [ ] > mm = request. getParameterMap ( ) ;
this . parameterMap = request. getParameterMap ( ) ;
}
public int getPage ( ) {
return page;
}
public void setPage ( int page) {
this . page = page;
}
public int getRows ( ) {
return rows;
}
public void setRows ( int rows) {
this . rows = rows;
}
public int getTotal ( ) {
return total;
}
public void setTotal ( int total) {
this . total = total;
}
public int getStartIndex ( ) {
return ( this . page - 1 ) * this . rows;
}
public boolean isPagination ( ) {
return pagination;
}
public void setPagination ( boolean pagination) {
this . pagination = pagination;
}
public int getTotalPageNum ( ) {
if ( this . getTotal ( ) % this . rows == 0 ) {
return this . getTotal ( ) / this . rows;
} else {
return this . getTotal ( ) / this . rows + 1 ;
}
}
public int getPreviousPageNum ( ) {
return this . page - 1 > 0 ? this . page - 1 : this . page;
}
public int getNextPageNum ( ) {
return this . page + 1 < this . getTotalPageNum ( ) ? this . page + 1 : this . getTotalPageNum ( ) ;
}
@Override
public String toString ( ) {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]" ;
}
}
3.2、PagingInterceptor.java
package com. example. sbdemo03. util ;
import com. github. pagehelper. PageHelper ;
import com. github. pagehelper. PageInfo ;
import org. aspectj. lang. ProceedingJoinPoint ;
import org. aspectj. lang. annotation. Around ;
import org. aspectj. lang. annotation. Aspect ;
import org. springframework. stereotype. Component ;
import java. util. List ;
@Component
@Aspect
public class PagingInterceptor {
@Around ( value = "@annotation(com.example.sbdemo03.annotation.Paging))" )
public Object paging ( ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object [ ] args = proceedingJoinPoint. getArgs ( ) ;
PageBean pageBean = getPageBean ( args) ;
if ( pageBean != null && pageBean. isPagination ( ) ) {
PageHelper . startPage ( pageBean. getPage ( ) , pageBean. getRows ( ) ) ;
}
Object rv = proceedingJoinPoint. proceed ( ) ;
if ( pageBean != null && pageBean. isPagination ( ) && rv != null ) {
PageInfo pageInfo = new PageInfo ( ( List ) rv) ;
pageBean. setTotal ( Long . valueOf ( pageInfo. getTotal ( ) ) . intValue ( ) ) ;
}
return rv;
}
private PageBean getPageBean ( Object [ ] args) {
PageBean pageBean = null ;
for ( Object arg : args) {
if ( arg instanceof PageBean ) {
pageBean = ( PageBean ) arg;
}
}
return pageBean;
}
}
3.4 自定义注解
package com. zking. sbdemo03. annotation ;
import java. lang. annotation. ElementType ;
import java. lang. annotation. Retention ;
import java. lang. annotation. RetentionPolicy ;
import java. lang. annotation. Target ;
@Retention ( RetentionPolicy . RUNTIME)
@Target ( ElementType . METHOD)
public @interface Paging {
}
druid数据库连接池
阿里开源的数据库连接池,使用java开发,提供强大的监控和扩展功能,可以替换DBCP和C3P0连接池,性能要比其他的连接池要好。
1、pom.xml
< dependency>
< groupId> com.alibaba</ groupId>
< artifactId> druid-spring-boot-starter</ artifactId>
< version> 1.1.21</ version>
</ dependency>
2、application.properties
#-- -- -- -- -- -- -- -- -- -- - druid config B -- -- -- -- -- -- -- -- -- -- -- --
#config druid
spring. datasource. type= com. alibaba. druid. pool. DruidDataSource
#初始化时建立物理连接的个数
spring. datasource. druid. initial- size= 5
#最小连接池数量
spring. datasource. druid. min- idle= 5
#最大连接池数量 maxIdle已经不再使用
spring. datasource. druid. max- active= 20
#获取连接时最大等待时间,单位毫秒
spring. datasource. druid. max- wait= 60000
#申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
spring. datasource. druid. test- while - idle= true
#既作为检测的间隔时间又作为testWhileIdel执行的依据
spring. datasource. druid. time- between- eviction- runs- millis= 60000
#销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接
spring. datasource. druid. min- evictable- idle- time- millis= 30000
#用来检测连接是否有效的sql 必须是一个查询语句
#mysql中为 select 1
#oracle中为 select 1 from dual
spring. datasource. druid. validation- query= select 1
#申请连接时会执行validationQuery检测连接是否有效, 开启会降低性能, 默认为true
spring. datasource. druid. test- on- borrow= false
#归还连接时会执行validationQuery检测连接是否有效, 开启会降低性能, 默认为true
spring. datasource. druid. test- on- return = false
#当数据库抛出不可恢复的异常时, 抛弃该连接
#spring. datasource. druid. exception- sorter= true
#是否缓存preparedStatement, mysql5. 5 + 建议开启
spring. datasource. druid. pool- prepared- statements= true
#当值大于0 时poolPreparedStatements会自动修改为true
spring. datasource. druid. max- pool- prepared- statement- per- connection- size= 20
#配置扩展插件
spring. datasource. druid. filters= stat, wall
#通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring. datasource. druid. connection- properties= druid. stat. mergeSql= true ; druid. stat. slowSqlMillis= 500
#合并多个DruidDataSource 的监控数据
spring. datasource. druid. use- global- data- source- stat= true
# WebStatFilter 配置,说明请参考Druid Wiki ,配置_配置WebStatFilter
#是否启用StatFilter 默认值true
spring. datasource. druid. web- stat- filter. enabled= true
spring. datasource. druid. web- stat- filter. url- pattern=
redis
1、pom.xml
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-data-redis</ artifactId>
</ dependency>
2、application.properties
# -- -- -- -- -- -- -- -- -- -- redis config B -- -- -- -- -- -- -- -- -- -- -- -- -
# Redis 数据库索引(默认为0 )
spring. redis. database= 0
# Redis 服务器地址
spring. redis. host= 192.168 .0 .24
# Redis 服务器连接端口
spring. redis. port= 6379
# Redis 服务器连接密码(默认为空)
spring. redis. password=
# 连接池最大连接数(使用负值表示没有限制)
spring. redis. jedis. pool. max- active= 100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring. redis. jedis. pool. max- wait= - 1 ms
# 连接池中的最大空闲连接
spring. redis. jedis. pool. max- idle= 10
# 连接池中的最小空闲连接
spring. redis. jedis. pool. min- idle= 0
# 连接超时时间(毫秒)
spring. redis. jedis. timeout= 1000
# -- -- -- -- -- -- -- -- -- -- redis config E -- -- -- -- -- -- -- -- -- -- -- -- -
3、redis缓存的一些注意事项
只应将热数据放到缓存中
所有缓存信息都应设置过期时间
缓存过期时间应当分散以避免集中过期(防止雪崩)
缓存key应具备可读性
应避免不同业务出现同名缓存key
可对key进行适当的缩写以节省内存空间
选择合适的数据结构
确保写入缓存中的数据是完整且正确的
避免使用耗时较长的操作命令,如:keys *
Redis默认配置中操作耗时超过10ms即视为慢查询
一个key对应的数据不应过大
对于string类型,一个key对应的value大小应控制在10K以内,1K左右更优hash类型,不应超过5000行
避免缓存穿透
数据库中未查询到的数据,可在Redis中设置特殊标识,以避免因缓存中无数据而导致每次请求均达到数据库
缓存层不应抛出异常
缓存应有降级处理方案,缓存出了问题要能回源到数据库进行处理
可以进行适当的缓存预热
对于上线后可能会有大量读请求的应用,在上线之前可预先将数据写入缓存中
读的顺序是先缓存,后数据库;写的顺序是先数据库,后缓存
数据一致性问题
数据源发生变更时可能导致缓存中数据与数据源中数据不一致,应根据实际业务需求来选择适当的缓存更新策略:
主动更新:在数据源发生变更时同步更新缓存数据或将缓存数据过期。一致性高,维护成本较高。
被动删除:根据缓存设置的过期时间有Redis负责数据的过期删除。一致性较低,维护成本较低。