2011-11-30 2 views
2

기존 시스템에 감사 기록 ​​모듈을 구현하고 싶습니다. 실제로 기록 된 사용자 정보를 저장하려고합니다. 단지 httpSession뿐입니다. 내가 최대 절전 모드/봄 사용하고hibernate 인터셉터에서 http 세션/요청 받기

/2 스트럿, 실제 로그인 한 사용자 정보를 얻을 내가 그 서비스 빈을 찾거나 HttpServletRequest의 ...

내가이 얻을 수있는 ServletContext를 필요 saveLog 서비스를 호출하기 위해 검색 중이며 ThreadLocal에 세션을 바인딩하는 것으로 보인다 usign Filter가 유일한 방법입니까? something like this 또는 this (last answer)

다른 제안이 있습니까? 이것은 커뮤니 케이 션 패턴 또는 좋은 연습인가?

답변

3

Spring은 현재 요청을 스레드의 현재 스레드에 바인드 할 수 있습니다. DispatcherServlet을 사용하는 경우 자동으로 완료되며 그렇지 않으면 RequestContextFilter을 선언해야합니다.

그럼 당신은 RequestContextHolder를 통해 요청 속성에 액세스 할 수 있습니다.

+0

내가 Envers에보고 된 감사 – Kossel

0

최대 절전 모드의 버전에 따라 세밀한 감사 로깅을 수용 할 수 Envers을 사용할 수 있습니다. 이것은 주어진 개정에 세션 변수에서 '현재 사용자'를 추가 할 수있는 기능이 포함되어

@Entity 
@RevisionEntity(ExampleListener.class) 
public class ExampleRevEntity extends DefaultRevisionEntity { 
    private String username; 

    public String getUsername() { return username; } 
    public void setUsername(String username) { this.username = username; } 
} 

이 잘 당신과 같이 봄에서 호출 할 수있는 이벤트 리스너의 시리즈를 통해 최대 절전 모드와 통합 :

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
... 
    <property name="eventListeners"> 
     <map> 
      <entry key="post-insert" value-ref="enversEventListener"/> 
      <entry key="post-update" value-ref="enversEventListener"/> 
      <entry key="post-delete" value-ref="enversEventListener"/> 
      <entry key="pre-collection-update" value-ref="enversEventListener"/> 
      <entry key="pre-collection-remove" value-ref="enversEventListener"/> 
      <entry key="post-collection-recreate" value-ref="enversEventListener"/> 
     </map> 
    </property> 
</bean> 

그럼 당신은 Envers 쿼리 API를 통해 감사의 개정에 대해 조회 할 수 있습니다. 최대 절전 모드를 사용하는 경우

최근 몇개의 프로젝트에 사용 후, 내 선호하는 감사 기법입니다. 한 사용자가 설치 그대로

applicationContext.getBean("currentUser", User.class); 

:

귀하의 질문에 대답하기 위해, 당신은 그 설정은 최대 절전 모드 요격 또는 Envers RevisionListener 현재 Spring 컨텍스트에서 그것을 찾는하여 '현재 사용자'에 액세스 할 수 있습니다 봄에 범위가 지정된 콩으로

+0

를 예상대로 모든 일, 청취자에게 최대 절전 모드,하지만 지금까지 내가 알고있는 모든 엔티티에 대해 2 개의 테이블을 작성해야하며 원하는 것은 아닙니다. 감사 로그를 하나의 테이블에만 저장하고 싶습니다. – Kossel

+0

여러 테이블 (감사 대상에 대해 1, 감사 기록에 대해 1, 중앙 개정 티켓에 대해 1)을 저장하면 여러 이점이 있습니다.라이브 엔티티에서 감사 내역을 유지하면 성능이 향상되며 도메인과 컨트롤러 코드를 올바르게 분류하여 유지할 수 있습니다. 실제 기록과 기록을 분리합니다. –

0

봄 부팅 용 예제 (spring-boot-starter 1.2.4.RELEASE). 일부 컨트롤러에서

:

@RequestMapping("login") 
public UserBean login(@RequestParam("email") String email, 
         @RequestParam("password") String password, 
         HttpSession session) { 
    // getting usser 
    session.setAttribute("currentUser", user); 
    return user; 
} 

등록 제가 테스트되었습니다

import org.hibernate.event.service.spi.EventListenerRegistry; 
import org.hibernate.event.spi.*; 
import org.hibernate.internal.SessionFactoryImpl; 
import org.hibernate.jpa.HibernateEntityManagerFactory; 
import org.springframework.stereotype.Component; 
import org.springframework.web.context.request.RequestAttributes; 
import org.springframework.web.context.request.RequestContextHolder; 

import javax.annotation.PostConstruct; 
import javax.inject.Inject; 
import javax.persistence.EntityManagerFactory; 

@Component 
public class UiDateListener implements PostLoadEventListener, PreUpdateEventListener { 
    @Inject EntityManagerFactory entityManagerFactory; 

    @PostConstruct 
    private void init() { 
     HibernateEntityManagerFactory hibernateEntityManagerFactory = (HibernateEntityManagerFactory) this.entityManagerFactory; 
     SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) hibernateEntityManagerFactory.getSessionFactory(); 
     EventListenerRegistry registry = sessionFactoryImpl.getServiceRegistry().getService(EventListenerRegistry.class); 
     registry.appendListeners(EventType.POST_LOAD, this); 
     registry.appendListeners(EventType.PRE_UPDATE, this); 
    } 

    @Override 
    public void onPostLoad(PostLoadEvent event) { 
     final Object entity = event.getEntity(); 
     if (entity == null) return; 

     final UserBean currentUser = (UserBean) RequestContextHolder.currentRequestAttributes().getAttribute("currentUser", RequestAttributes.SCOPE_SESSION); 
     // some logic after entity loaded 
    } 

    @Override 
    public boolean onPreUpdate(PreUpdateEvent event) { 
     final Object entity = event.getEntity(); 
     if (entity == null) return false; 

     // some logic before entity persist 

     return false; 
    } 
} 
관련 문제