本篇主要介绍spring boot 整合redis做数据缓存,log4j做日志,利用的是spring aop切面编程技术,利用注解标识切面。
springboot这里不做介绍
一、首先引入pom.xml配置
<!-- springboot web support -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring web hot develop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- springboot redis support -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- thymeleaf engine -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- security thymeleaf lable -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<!-- security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- spring aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- oracle -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<!-- 阿里巴巴数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- mysql jdbc driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- jpa jar -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- properites -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
二、配置文件我里这用的是yml格式的,tab缩进,如果是properties格式的,请自行配置
spring:
redis:
database: 0
password:
host: 127.0.0.1
port: 6379
lettuce:
pool:
max-active: 8
max-wait: -1
max-idle: 8
min-idle: 0
timeout: 10000
三、redis注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {
static enum CacheableType{
GETORSAVE,
UPDATE
}
/**
* 缓存key配置自动生成key
* @return
*/
String key() default "";
/**
* key取值与第几个参数,默认第一个,配置自动设置key
* @return
*/
CacheableType method() default CacheableType.GETORSAVE;
/**
* 失效时间毫秒
* 默认一分钟失效
* @return
*/
int expireTime() default 60000;
}
四、reidis aop切面
@Aspect
@Component
public class SpringCacheAop {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Around(value="@annotation(com.msw.spring.config.cache.Cacheable)")
public Object Around(ProceedingJoinPoint poin){
Object value = null;
//获取注解类值
Cacheable anno = getAnnotation(poin, Cacheable.class);
//获取入参
String key = getKey(anno,poin);
if(anno.method().equals(Cacheable.CacheableType.UPDATE)){
redisTemplate.delete(key);
try {
value = poin.proceed();
} catch (Throwable e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
redisTemplate.opsForValue().set(key, value, anno.expireTime(),TimeUnit.MILLISECONDS);;
}else if(anno.method().equals(Cacheable.CacheableType.GETORSAVE)){
value = redisTemplate.opsForValue().get(key);
if(value != null){
return value;
}
//获取返回值
try {
value = poin.proceed();
} catch (Throwable e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
redisTemplate.opsForValue().set(key, value, anno.expireTime(),TimeUnit.MILLISECONDS);;
}
return value;
}
/**
* key生成策略
* @param anno
* @param args
* @return
*/
private String getKey(Cacheable anno, ProceedingJoinPoint poin) {
String key = null;
if(poin.getArgs().length > 0){
key = Arrays.toString(poin.getArgs());
}else{
key = poin.getSignature().getName();
}
return DigestUtils.sha1DigestAsHex(key);
}
/**
*
* @Title: getAnnotation
* @Description: 获得Annotation对象
* @param @param <T>
* @param @param jp
* @param @param clazz
* @param @return
* @return T
* @throws
*/
private <T extends Annotation> T getAnnotation(ProceedingJoinPoint jp,Class<T> clazz) {
MethodSignature joinPointObject = (MethodSignature) jp.getSignature();
Method method = joinPointObject.getMethod();
return method.getAnnotation(clazz);
}
@SuppressWarnings("unused")
private <T extends Annotation> List<T> getParameterAnnotations(ProceedingJoinPoint jp,Class<T> clazz){
MethodSignature joinPointObject = (MethodSignature) jp.getSignature();
Method method = joinPointObject.getMethod();
Annotation[][] annotations = method.getParameterAnnotations();
List<T> result = new ArrayList<T>();
for(Annotation[] anno:annotations){
for(Annotation a: anno){
Class<? extends Annotation> annotationType = a.annotationType();
T[] type = annotationType.getDeclaredAnnotationsByType(clazz);
System.out.println(type);
}
}
return result;
}
}
aop基于注解的缓存已经配置成功了,如果需要缓存的接口加上@Cacheable就可以实现缓存了,可以在命令行redis-cli中看到。例如:
public interface UserDao extends JpaRepository<User, Integer>{
@Query("select u from User u where u.username=:username")
@Cacheable
User findByUserName(@Param("username")String username);
}
上面已经配置好了基于注解的缓存,下面配置log4j日志log,这个配置就比较简单了。
@Aspect
@Component
public class SpringAopLog4j {
private final Log logger = LogFactory.getLog(getClass());
//这里就是切入的包名方法
//如这里就是切入controller包所有的类的所有方法
@Pointcut("execution(* com.msw.spring.controller.*.*(..))")
public void pointCut() {}
@Around(value="pointCut()")
public Object Around(ProceedingJoinPoint poin){
try {
return poin.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
@Before(value="pointCut()")
public void Before(JoinPoint joinPoint){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
logger.info("#####################request###########################");
logger.info("URL: "+request.getRequestURI().toString());
logger.info("HTTP_METHOD:"+request.getMethod());
logger.info("IP:"+request.getRemoteAddr());
Enumeration<String> enu = request.getParameterNames();
while(enu.hasMoreElements()) {
String name = (String)enu.nextElement();
logger.info(name+"="+request.getParameter(name));
}
}
@After(value="pointCut()")
public void After(JoinPoint joinPoint){
}
@AfterReturning(value="pointCut()",returning= "rec")
public void AfterReturning(JoinPoint joinPoint, Object rec){
logger.info("response:"+rec);
logger.info("#######################End#############################");
}
@AfterThrowing(value="pointCut()",throwing="ex")
public void AfterThrowing(JoinPoint joinPoint, Exception ex){
}
}
运行就可以看到每一个request都有显示入参出参。
GitHub地址:https://github.com/yzliusha/springboot-security-redis-jpa-oracle-aop-Log4j-cache-