2012-05-18 2 views
3

Я проходил несколько уроков Spring/AOP и несколько ознакомился с соответствующими понятиями.Spring/AOP: Лучший способ реализовать журнал действий в базе данных

Теперь, следуя моим требованиям, мне нужно создать реализацию «Реестр событий», которая сохранит действия пользователя, зарегистрированного в БД, который может варьироваться от подачи заявки на услугу или создания новых пользователей в случае Admin пользователей, и т.д. при вызове любого метода, имеющего аннотацию (скажем @ActivityLog), эта информация должна сохраняться в виде actorId, actionComment, actionTime, actedUponId ... и т.д.

Теперь, если я создаю класс POJO (который сопоставляется с таблицей ActivityLog в БД) и хочет сохранить эти данные изнутри Advice (предпочтительно используя ту же транзакцию, что и метод, метод использует аннотацию @Transactional), как я фактически заполняю переменные в этом POJO? Вероятно, я могу получить от объекта сеанса & actionTime может просто быть new Date(), но как насчет динамических значений для actionComment/actedUponId?

Любая помощь будет блестящей! (Кстати, у меня есть требование, чтобы не использовать Hibernate перехватчики.)

ответ

0

Вы будете получать ссылку на org.aspectj.lang.JoinPoint в вашем advice.You может получить имя целевого метода выполняется с toShortString() .Вы может иметь петли up/property с записями method-name=comments. Эти комментарии могут быть заполнены в POJO.actionComment. Имя метода может быть установлено в POJO.actedUponId.

Я надеюсь, что совет должен выполняться в рамках одной и той же транзакции, если метод доступа к данным будет рекомендован, а метод службы использует @Transactional.

+0

Спасибо за ответ. Интересный подход, но actionComment может исходить от пользователей! Также хотелось добавить, что я предполагаю, что я должен использовать After Advice (хотя не уверен, что он будет использовать ту же транзакцию, что и оригинальный метод)! Спасибо, Sumit – Sumit

+0

BTW actedUponId должен быть пользователем пользователя. Операция (добавление, удаление и т. Д.) Выполняется администратором. – Sumit

+0

Если используется функция spring-security, главный/пользователь должен быть доступен с 'SecurityContextHolder..getUserPrincipal()'. Как вы планируете получить userId? –

2

Вот полный пример:

@Aspect 
@Component 
public class WebMethodAuditor { 

protected final Log logger = LogFactory.getLog(getClass()); 

public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss"; 

@Autowired 
AuditRecordDAO auditRecordDAO; 

@Before("execution(* com.mycontrollers.*.*(..))") 
public void beforeWebMethodExecution(JoinPoint joinPoint) { 
    Object[] args = joinPoint.getArgs(); 
    String methodName = joinPoint.getSignature().getName(); 
    User principal = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
    Timestamp timestamp = new Timestamp(new java.util.Date().getTime()); 
    // only log those methods called by an end user 
    if(principal.getUsername() != null) { 
     for(Object o : args) { 
      Boolean doInspect = true; 
      if(o instanceof ServletRequestDataBinder) doInspect = false; 
      if(o instanceof ExtendedModelMap) doInspect = false; 
      if(doInspect) { 
       if(o instanceof BaseForm) { 
        // only show form objects 
        AuditRecord ar = new AuditRecord(); 
        ar.setUsername(principal.getUsername()); 
        ar.setClazz(o.getClass().getCanonicalName()); 
        ar.setMethod(methodName); 
        ar.setAsString(o.toString()); 
        ar.setAudit_timestamp(timestamp); 
        auditRecordDAO.save(ar); 
       } 
      } 
     } 
    } 
} 

} 
2

Если вы хотите, чтобы получить actionComment и actedUponId из аргументов аннотированных методов (при условии, что они обе строки), вы можете добавить обязательные условия для вашей @Around Pointcut так:

@Around("@annotation(ActivityLog) && args(actionComment,actedUponId)") 
public Object logActivity(ProceedingJoinPoint pjp, 
     String actionComment, String actedUponId) throws Throwable { 
    // ... get other values from context, etc. ... 
    // ... write to log ... 
    pjp.proceed(); 
} 

args связывания в срезе точек может быть использован в частично указанном режиме, в случае, если есть другие аргументы о том, что вы не заинтересованы в, и синке Этот аспект сам по себе является бобом, он может быть подключен ко всему остальному, что происходит обычным образом.

Обратите внимание, что если вы смешиваете декларативное управление транзакциями при одних и тех же вызовах метода, вам нужно правильно определить порядок аспектов. Это делается частично за счет того, что компонент аспект также реализует интерфейс Spring Ordered и контролирует приоритет транзакций через атрибут order до <tx:annotation-driven/>. (Если это невозможно, вы будете вынуждены делать умные вещи с прямой обработкой транзакций, это гораздо более болезненный вариант, чтобы получить право ...)

Смежные вопросы