1. 程式人生 > >Spring AOP 記錄日誌

Spring AOP 記錄日誌

Spring AOP 最常用的地方之一就是記錄日誌,這裡記錄除了記錄日誌描述外,還記錄了方法請求的引數,並將記錄儲存到資料庫。這裡用到了自定義註解,使用如下

1. 建立 log 日誌類,並生產相應的pojo,pojo如下

public class OperationLog implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 7087799444017468909L;
    private Integer id;
    private String userId;
    private
String operatType; private String content; private String remarks; private Date create; // getXXX()和setXXX()省略 }

2. 建立註解類 SystemServiceLog

/**
 * AOP 日誌記錄,自定義註解
 * @author xxx
 * @since JDK1.8
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemServiceLog { // 日誌描述 String description() default ""; // 操作型別 int tableType() default 0; }

省略建立dao和service的程式碼

3. 建立攔截方法,這裡只在請求前攔截

@Aspect
@Component
public class SystemLogAspect {

    @Autowired 
    private OperationLogService operationLogService;

    @Pointcut
("@annotation(com.xxx.common.annotation.SystemServiceLog)") public void serviceAspect() { } @After("serviceAspect()") public void doServiceLog(JoinPoint joinPoint) { // 獲取使用者資訊 Session session = SecurityUtils.getSubject().getSession(); UserInfo user = (UserInfo) session.getAttribute(ShiroDbRealm.SESSIOIN_USER_KEY); OperationLog log = new OperationLog(); try { String content = getServiceMthodDescription(joinPoint); log.setContent(user.getRealName() + content); log.setRemarks(getServiceMethodParams(joinPoint)); log.setUserId(user.getId()); String operatType = getServiceMthodTableType(joinPoint); log.setOperatType(operatType); operationLogService.insert(log); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 獲取註解中對方法的描述資訊 用於service層註解 * @param joinPoint 切點 * @return 方法描述 * @throws ClassNotFoundException */ private String getServiceMthodDescription(JoinPoint joinPoint) throws ClassNotFoundException { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); String description = ""; for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { description = method.getAnnotation(SystemServiceLog.class).description(); break; } } } return description; } /** * 獲取註解方法中的描述資訊 用於 Service 層註解 * @param joinPoint 切點 * @return 方法描述 * @throws ClassNotFoundException */ private String getServiceMthodTableType(JoinPoint joinPoint) throws ClassNotFoundException { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); String description = ""; for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { description = method.getAnnotation(SystemServiceLog.class).description(); break; } } } return description; } /** * 獲取json格式的引數<br> * * @param joinPoint * @return * @since JDK1.8 */ private String getServiceMethodParams(JoinPoint joinPoint) { Object[] arguments = joinPoint.getArgs(); if (arguments == null || arguments.length == 0) { return "無引數"; } List<Object> list = new ArrayList<>(Arrays.asList(arguments)); String params = JsonUtil.getJsonStringFromPOJO(list); return params; } }

4. 在service的實現類的方法上使用自定義註解記錄日誌

@Override
    @Transactional
    @SystemServiceLog(description=Constants.CLIENT_SELECT_LIST, tableType=Constants.USER_TABLE_TYPE)
    public Map<String, Object> queryXXX(String name, String address) {
        Map<String, Object> map = new HashMap<>();
        // 省略
        return map;
    }