springboot+jpa+security+log4j(aop)+redis(aop)

本篇主要介绍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-

猜你喜欢

转载自blog.csdn.net/qq_40150691/article/details/83023189