springboot~jpa審計欄位的自動填充

张占岭發表於2024-05-30

在使用 Spring Data JPA 中的 @CreatedDate 註解時,如果希望自動填充建立時間欄位,通常需要結合 @EntityListeners(AuditingEntityListener.class) 註解一起使用。這是因為 @CreatedDate 等審計註解通常與審計事件監聽器(AuditingEntityListener)一起工作,用於處理實體的審計資訊。

審計欄位-自動填充

當您定義一個實體類(例如 EntityBase)並希望使用 @CreatedDate 註解來自動設定建立時間時,可以按照以下步驟操作:

  1. 在實體類中新增 @CreatedDate 註解,實體可抽象成一個類,如EntityBase,AuditBase等
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class EntityBase {

	/**
	 * 建立人
	 */
	@Column(name = "created_by")
	@CreatedBy
	private String createdBy;

	/**
	 * 修改人
	 */
	@Column(name = "updated_by")
	@LastModifiedBy
	private String updatedBy;

	/**
	 * 建立時間
	 */
	@Column(name = "created_time")
	@CreatedDate
	private java.time.LocalDateTime createdTime;

	/**
	 * 更新時間
	 */
	@Column(name = "update_time")
	@LastModifiedDate
	private java.time.LocalDateTime updateTime;

}
  1. 確保審計事件監聽器生效
    確保 AuditingEntityListener 能夠正確監聽實體類的審計事件,並在儲存實體物件時自動填充相應的審計資訊,包括建立時間等。

  2. 實現AuditorAware介面,返回當前登入的使用者,以便填充create_by欄位,同時開啟審計功能@EnableJpaAuditing:

@EnableJpaAuditing
@Component
public class AuditorAwareImpl implements AuditorAware {

	@Override
	public Optional getCurrentAuditor() {
		return Optional.of("lind");
	}

}

透過以上步驟,您可以在訂閱 EntityBase 實體類時使用 @CreatedDate 註解,並結合 @EntityListeners(AuditingEntityListener.class) 註解來自動填充建立時間欄位,從而實現審計功能。

AuditorAware獲取請求頭資訊

要在實現 AuditorAware 介面的 getCurrentAuditor() 方法中獲取當前請求頭(HTTP Header)中的變數,您可以藉助 Spring 提供的 RequestContextHolderServletRequestAttributes 來訪問當前請求的上下文資訊。具體步驟如下:

  1. 獲取當前請求的 HttpServletRequest 物件

    • 首先,您需要從 RequestContextHolder.getRequestAttributes() 獲取當前請求的 ServletRequestAttributes 物件。
    • 然後透過 ServletRequestAttributes 物件獲取當前的 HttpServletRequest 物件。
  2. 從 HttpServletRequest 中獲取請求頭資訊

    • HttpServletRequest 物件中,您可以使用 getHeader() 方法來獲取指定名稱的請求頭資訊。

下面是一個示例程式碼,演示瞭如何在 AuditorAwaregetCurrentAuditor() 方法中獲取當前請求頭中的變數:

import org.springframework.data.domain.AuditorAware;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

@EnableJpaAuditing
@Component
public class CustomAuditorAware implements AuditorAware<String> {

    @Override
    public Optional<String> getCurrentAuditor() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            String customHeaderValue = request.getHeader("Custom-Header");
            return Optional.ofNullable(customHeaderValue);
        }
        return Optional.empty();
    }
}

如果是基於netty的WEB框架,需要使用下面程式碼獲取請求頭引數

@EnableJpaAuditing
@Component
public class AuditorAwareImpl implements AuditorAware<String> {

	@Override
	public Optional<String> getCurrentAuditor() {
		Object request = RpcContext.getServiceContext().getRequest();
		if (request != null) {
			NettyRequestFacade requestFacade = (NettyRequestFacade) request;
			if (requestFacade != null && requestFacade.getHeader("preferred_username") != null) {
				return Optional.of(requestFacade.getHeader("preferred_username"));
			}
		}
		return Optional.of("none");
	}

}

在上述程式碼中,我們透過 RequestContextHolder 獲取當前請求的上下文資訊,並從中提取出請求頭中名為 Custom-Header 的自定義變數值。最後將該值作為審計人員資訊返回。

請注意,在使用 RequestContextHolder 時,確保上下文中包含請求資訊,否則可能會出現空指標異常。另外,這種方式適用於基於 Spring MVC 或 Spring WebFlux 的應用。

相關文章