2015년 11월 18일 수요일

Spring AOP + AspectJ annotation + Redis 샘플 #2

이번 포스팅에서는 예제에서 사용한 Redis 설정에 대해서 기술한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">

 <bean id="connectionFactory"
  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
  <property name="hostName" value="#{redisProp['hostName']}" />
  <property name="port" value="#{redisProp['port']}" />
  <property name="poolConfig" ref="jedisPoolConfig"></property>
 </bean>
 <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
  <property name="connectionFactory" ref="connectionFactory" />
 </bean>

 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
  <property name="maxTotal" value="20"></property>
 </bean>
 <context:component-scan base-package="com.example.redis" />
 <util:properties id="redisProp" location="classpath:/properties.xml" >
 </util:properties>
</beans>

Util: properties 와 SpEL 사용방법
http://secondmemory.kr/271
Resources경로에 아래의 xml 프로퍼티를 추가하자.



 192.168.0.105
 8000

Method 정보를 저장하는 Dto 생성
package com.example.redis;

public class RankDto {
 private int rank;
 private String methodName;
 private int callCount;

 public int getRank() {
  return this.rank;
 }

 public void setRank(int rank) {
  this.rank = rank;
 }

 public String getMethodName() {
  return this.methodName;
 }

 public void setMethodName(String methodName) {
  this.methodName = methodName;
 }

 public int getCallCount() {
  return this.callCount;
 }

 public void setCallCount(int callCount) {
  this.callCount = callCount;
 }
}

호출되는 함수 Dto를 저장할 Repository 인터페이스
public abstract interface ActionHistoryRepo<Key, Value> {
 public abstract void addAction(Value paramValue);

 public abstract List<RankDto> getRank();

 public abstract void deleteAction(Key paramKey);
}

Repository 인터페이스의 구현 클래스
이 예제에서는 실행되는 함수의 실행 횟수를 저장하고 통계를 내기 위해서 Redis Zset 타입을 이용하여 구현한다.
ZSet 사용법은 아래의 사이트를 참고하자
http://www.tutorialspoint.com/redis/redis_sorted_sets.htm
@Repository("actionHistory")
public class HistorySaver implements ActionHistoryRepo<String, String> {
       //Redis ZSet을 사용하기 위한 고정키
 private final String redisKey = "MethodRank";
 
 @Autowired
 private RedisTemplate<String, String> stringRedisTemplate;

 public void addAction(String value) {
  int score = 1;
     // 개체가 없으면 자동으로 생성 한 후 스코어에 +1         
  this.stringRedisTemplate.opsForZSet().incrementScore("MethodRank",
    value, score);
 }

 public List<RankDto> getRank() {
                //Range를 사용하면 내림차순이 기본으로 설정된다. Reverse Range를 사용하여 오름차순 순서로 뽑아내자.
  Set<String> rankset = this.stringRedisTemplate.opsForZSet()
    .reverseRange(redisKey , 0L, -1L);
  List<RankDto> rankList = new ArrayList();

  Iterator<String> iters = rankset.iterator();
  int ranky = 1;
  while (iters.hasNext()) {
   RankDto dto = new RankDto();
   dto.setMethodName((String) iters.next());

   Double rank = this.stringRedisTemplate.opsForZSet().score(
     redisKey , dto.getMethodName());
   dto.setCallCount(rank.intValue());
   dto.setRank(ranky);
   rankList.add(dto);
   ranky++;
  }
  return rankList;
 }

 public void deleteAction(String key) {
  this.stringRedisTemplate.delete(key);
 }
}
구현된 결과물을 Tomcat was를 이용해서 실행해 보자.
http://localhost:8080/aop/act1

http://localhost:8080/aop/rank

소스코드 주소는 다음과 같다.
https://github.com/wargen99/wargen-repo.git

아주 간단하게 AOP를 이용하여 사이트 내의 서비스 메소드가 호출되는 통계를 저장하는 예제를 만들어 보았다.
아주 기초적인 예제지만 이를 응용하여 다양한 관점에서 데이터를 저장하고 이를 재활용할 수 있는 점을 확인하면 좋을 듯 하다.

댓글 없음:

댓글 쓰기