SpringBoot-AOP

SpringBoot-AOP

使用AOP統(tǒng)一處理請求日志

1.AOP的概念

AOP:AOP是一種編程范式撼港,與語言無關(guān),是一種程序設(shè)計思想

面向切面(AOP) Aspect Oriented Programming
面向?qū)ο?OOP) Object Oriented Programming
面向過程(POP) Procedure Oriented Programming

面向過程到面向?qū)ο螅?/p>

功能:下雨了芦圾,我打開了雨傘
面向過程:假如下雨了蛾派,我打開了雨傘
面向?qū)ο螅禾鞖?->下雨;我-->打傘

即:換個角度看世界个少,換個姿勢處理問題

面向?qū)ο螅宏P(guān)注的是將需求功能垂直劃分為不同的并且相對獨立的洪乍,會封裝成良好的類并且讓他們有屬于自己的行為。
面向切面:利用橫切的技術(shù)夜焦,將面向?qū)ο髽?gòu)建的龐大的類的體系進行水平的切割壳澳,并且將其中會影響到多個類的公共行為封裝成一個可重用的模塊,該模塊就成為切面

AOP的思想:將通用的邏輯從業(yè)務(wù)邏輯中分離出來

2.實現(xiàn)AOP

網(wǎng)絡(luò)請求和數(shù)據(jù)庫操作請求:

1.jpg

使用AOP思想:

2.jpg

3.實現(xiàn)使用AOP記錄每一個http請求

需求:授權(quán)訪問(必須先登錄才能訪問)

第一步:添加依賴:

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

pom.xml:

<?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>

    <!--項目的基本描述-->
    <groupId>com.hcx</groupId>
    <artifactId>girl</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>girl</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>


    <dependencies>
        <!--web項目必須引入的依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--單元測試時需要用到的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

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

    </dependencies>

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

第二步:編寫切面類:

@Aspect
@Component
public class HttpAspect {

    //在http請求到方法之前記錄

    /**
     * @Before注解:在方法執(zhí)行之前執(zhí)行
     * com.hcx包下的girlcontroller里面的girlList方法茫经,不管是什么參數(shù)都會被攔截
     * 所有方法都攔截:execution(public * com.hcx.controller.GirlController.*(..))
     */
    @Before("execution(public * com.hcx.controller.GirlController.girlList(..))")
    public void log(){
        System.out.println("被攔截了");
    }

    @After("execution(public * com.hcx.controller.GirlController.girlList(..))")
    public void doAfter(){
        System.out.println("我是方法執(zhí)行之后被攔截");
    }
}

第三步:攔截controller中的方法:

@RestController
public class GirlController {

    @Autowired
    private GirlRepository girlRepository;

    @Autowired
    private GirlService girlService;

    /**
     * 查詢所有女生
     * @return
     */
    @GetMapping(value = "/girls")
    public List<Girl> girlList(){
        System.out.println("我是girlList方法");
        return girlRepository.findAll();
    }
}

運行結(jié)果:

3.jpg
4.jpg

注意:以上代碼可以看出有重復(fù)巷波,在切面類中優(yōu)化:

HttpAspect:

@Aspect
@Component
public class HttpAspect {

    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class); //該類是org.slf4j的

    //在http請求到方法之前記錄
    /**
     * @Before注解:在方法執(zhí)行之前執(zhí)行
     * com.hcx包下的girlcontroller里面的girlList方法萎津,不管是什么參數(shù)都會被攔截
     * 所有方法都攔截:execution(public * com.hcx.controller.GirlController.*(..))
     */
    /*@Before("execution(public * com.hcx.controller.GirlController.girlList(..))")
    public void log(){
        System.out.println("被攔截了");
    }*/

    /**
     * 公用的方法,使用@Pointcut注解
     */
    @Pointcut("execution(public * com.hcx.controller.GirlController.girlList(..))")
    public void log(){

    }

    @Before("log()")
    public void doBefore(){
//        System.out.println("我是方法執(zhí)行之前被攔截");
        logger.info("前日志信息"); //打印info抹镊、error等日志
    }

    @After("log()")
    public void doAfter(){
//        System.out.println("我是方法執(zhí)行之后被攔截");
        logger.info("后日志信息");
    }
}

GirlController:

@RestController
public class GirlController {

    /**
     * getLogger方法中的參數(shù)與類名對應(yīng)
     */
    private final static Logger logger = LoggerFactory.getLogger(GirlController.class);

    @Autowired
    private GirlRepository girlRepository;

    @Autowired
    private GirlService girlService;

    /**
     * 查詢所有女生
     * @return
     */
    @GetMapping(value = "/girls")
    public List<Girl> girlList(){
//        System.out.println("我是girlList方法");
        logger.info("我是girlList方法");
        return girlRepository.findAll();
    }
}
5.jpg
6.jpg

記錄http請求:

HttpAspect:

@Aspect
@Component
public class HttpAspect {

    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class); //該類是org.slf4j的
    
    /**
     * 公用的方法锉屈,使用@Pointcut注解
     */
    @Pointcut("execution(public * com.hcx.controller.GirlController.girlList(..))")
    public void log(){

    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint){
        /**
         * 請求路徑:url
         * 請求方式:method
         * 客戶端ip:ip
         * 請求的是哪個類方法:類方法
         * 方法的參數(shù)
         */
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();//注意:選擇的HttpServletRequest選的是javax.servlet.http的
        //url
        logger.info("url={}",request.getRequestURL());
        //method
        logger.info("method={}",request.getMethod());
        //ip
        logger.info("ip={}",request.getRemoteAddr());
        //getDeclaringTypeName():獲取類名,getName:獲取類方法
        logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        //方法的參數(shù)
        logger.info("args={}",joinPoint.getArgs());
    }

    @After("log()")
    public void doAfter(){
//        System.out.println("我是方法執(zhí)行之后被攔截");
        logger.info("后日志信息");
    }

    /**獲取返回的內(nèi)容:
     * {
     "id": 2,
     "cupSize": "B",
     "age": 19
     }
     */
    @AfterReturning(returning = "object",pointcut = "log()")
    public void doAfterReturning(Object object){
        logger.info("response={}",object.toString());
    }
    
}

GirlController:

@RestController
public class GirlController {

    /**
     * getLogger方法中的參數(shù)與類名對應(yīng)
     */
    private final static Logger logger = LoggerFactory.getLogger(GirlController.class);

    @Autowired
    private GirlRepository girlRepository;

    @Autowired
    private GirlService girlService;

    /**
     * 查詢所有女生
     * @return
     */
    @GetMapping(value = "/girls")
    public List<Girl> girlList(){
//        System.out.println("我是girlList方法");
        logger.info("我是girlList方法");
        return girlRepository.findAll();
    }
}

Girl:

@Entity //該注解表示該類在數(shù)據(jù)庫中有對應(yīng)的表 不用創(chuàng)建該表
public class Girl {

    @Id
    @GeneratedValue
    private Integer id;

    private String cupSize;

    /**
     * 給年齡加上限制:年齡必須大于18歲
     * value:值
     * message:提示信息
     */
    @Min(value =18,message = "年齡必須大于18歲")
    private Integer age;

    public Girl() {
    }

    @Override
    public String toString() {
        return "Girl{" +
                "id=" + id +
                ", cupSize='" + cupSize + '\'' +
                ", age=" + age +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCupSize() {
        return cupSize;
    }

    public void setCupSize(String cupSize) {
        this.cupSize = cupSize;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
7.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垮耳,一起剝皮案震驚了整個濱河市颈渊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌终佛,老刑警劉巖儡炼,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異查蓉,居然都是意外死亡乌询,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門豌研,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妹田,“玉大人,你說我怎么就攤上這事鹃共」碛叮” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵霜浴,是天一觀的道長晶衷。 經(jīng)常有香客問我,道長阴孟,這世上最難降的妖魔是什么晌纫? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮永丝,結(jié)果婚禮上锹漱,老公的妹妹穿的比我還像新娘。我一直安慰自己慕嚷,他們只是感情好哥牍,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布竟坛。 她就那樣靜靜地躺著窃肠,像睡著了一般卷拘。 火紅的嫁衣襯著肌膚如雪少漆。 梳的紋絲不亂的頭發(fā)上叔营,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天近速,我揣著相機與錄音溃肪,去河邊找鬼酒朵。 笑死纺涤,一個胖子當著我的面吹牛译暂,可吹牛的內(nèi)容都是我干的抠忘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼外永,長吁一口氣:“原來是場噩夢啊……” “哼崎脉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起伯顶,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤囚灼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后祭衩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灶体,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年掐暮,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝎抽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡路克,死狀恐怖樟结,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情精算,我是刑警寧澤瓢宦,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站灰羽,受9級特大地震影響驮履,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜廉嚼,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一玫镐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧前鹅,春花似錦摘悴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽葱椭。三九已至捂寿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孵运,已是汗流浹背秦陋。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留治笨,地道東北人驳概。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓赤嚼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顺又。 傳聞我的和親對象是個殘疾皇子更卒,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容