spring-data-aop 進行切面編程日誌記錄

spring-data-aop

用途主要是記錄日誌和作切面加強
項目demo: https://github.com/woyaochengweidaniu/spring

項目啓動直接訪問接口便可在控制檯看到效果--------------------java

依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lcm</groupId>
    <artifactId>aop</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>aop</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.1.6.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.5.11</version>
        </dependency>
        <!-- 解析 UserAgent 信息 -->
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>1.21</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.6.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

切點能夠用註解 也能夠用表達式

1建立註解
package com.lcm.aop.annon;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * 建立註解
 * RetentionPolicy.RUNTIME   生命週期   運行時
 *ElementType.METHOD   標記在什麼地方    方法上
 *
 * @author lcm
 * @date created in 2019 7 11
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OpLog {

    String operation() default "";

    String target() default "";
}

建立切面

package com.lcm.aop.aspectj;


import com.lcm.aop.annon.OpLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * <p>進行註解式切面編程</p>
 * @author lcm
 * @date created in 2019 7 11
 *
 */
@Slf4j
@Aspect
@Component
public class OpreationLog {


    /**
     *<p>只須要在方法上添加註解便可</p>
     */
    @Pointcut("@annotation(com.lcm.aop.annon.OpLog)")
    public void operation(){}


    /**
     * <p>帶有log的註解而且切入點是operation  返回的是Object</p>
     * @param joinPoint
     * @param opLog
     * @param o
     */
    @AfterReturning(value = "operation()&&@annotation(opLog)",returning = "o")
    public void AfterReturning(JoinPoint joinPoint, OpLog opLog, Object o){

        log.info("操做類型:{}",opLog.operation());
        log.info("操做目標:{}",opLog.target());
        log.info("返回對象:{}",o);

        Object[] args = joinPoint.getArgs();
        for (Object object:args) {

            log.info("參數:{}",object);

        }


    }
}

建立service

package com.lcm.aop.service;

import com.lcm.aop.annon.OpLog;
import org.springframework.stereotype.Service;

/**
 * @author lcm
 */
@Service
public class TestSerivce {


    @OpLog(operation = "刪除",target = "訂單")
    public Object delete(String id){
        System.out.println(id);
        return "success";

    }

}

建立controller

package com.lcm.aop.api;

import com.lcm.aop.service.TestSerivce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author lcm
 */
@RestController
public class ApiController {

    @Autowired
    private TestSerivce serivce;

    /**
     * 測試方法
     *
     * @param id 測試參數
     */
    @GetMapping("/test2")
    public Object test2(String  id) {
        Object delete = serivce.delete(id);
        return delete;
    }

}

2使用表達式進行切點切入

package com.lcm.aop.aspectj;

import cn.hutool.json.JSONUtil;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Objects;

/**
 * @author lcm
 * <P>記錄切面日誌</P>
 * @date created in 2019 7 11
 * @author lcm
 * @deprecated 切面不只能夠作日誌 還能夠作方法加強
 *
 */
@Aspect
@Component
@Slf4j
public class AopLog {
    private static final String START_TIME = "request-start";

    /**
     * 切入點
     */
    @Pointcut("execution(public * com.lcm.aop.controller.*Controller.*(..))")
    public void log() {

    }

    /**
     * 前置操做
     *
     * @param point 切入點
     */
    @Before("log()")
    public void beforeLog(JoinPoint point) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        log.info("【請求 URL】:{}", request.getRequestURL());
        log.info("【請求 IP】:{}", request.getRemoteAddr());
        log.info("【請求類名】:{},【請求方法名】:{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName());

        Map<String, String[]> parameterMap = request.getParameterMap();
        log.info("【請求參數】:{},", JSONUtil.toJsonStr(parameterMap));
        Long start = System.currentTimeMillis();
        request.setAttribute(START_TIME, start);
    }

    /**
     * 環繞操做
     *
     * @param point 切入點
     * @return 原方法返回值
     * @throws Throwable 異常信息
     */
    @Around("log()")
    public Object aroundLog(ProceedingJoinPoint point) throws Throwable {
        Object result = point.proceed();
        log.info("【返回值】:{}", JSONUtil.toJsonStr(result));
        return result;
    }

    /**
     * 後置操做
     */
    @AfterReturning("log()")
    public void afterReturning() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        Long start = (Long) request.getAttribute(START_TIME);
        Long end = System.currentTimeMillis();
        log.info("【請求耗時】:{}毫秒", end - start);

        String header = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgent.parseUserAgentString(header);
        log.info("【瀏覽器類型】:{},【操做系統】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header);
    }
}

建立controller

package com.lcm.aop.controller;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.lcm.aop.service.TestSerivce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 測試 Controller
 * </p>
 *
 * @package: com.xkcoding.log.aop.controller
 * @description: 測試 Controller
 * @author: yangkai.shen
 * @date: Created in 2018/10/1 10:10 PM
 * @copyright: Copyright (c) 2018
 * @version: V1.0
 * @modified: yangkai.shen
 */
@RestController
public class TestController {
    @Autowired
    private TestSerivce serivce;

    /**
     * 測試方法
     *
     * @param who 測試參數
     * @return {@link Dict}
     */
    @GetMapping("/test1")
    public Dict test1(String who) {
        return Dict.create().set("who", StrUtil.isBlank(who) ? "me" : who);
    }



}

啓動項目而後訪問端口 若是端口號指定了,就按照指定的端口號訪問

瀏覽器輸入:http://localhost:8081/test1
瀏覽器輸入:http://localhost:8081/test2git

相關文章
相關標籤/搜索