最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring boot 使用Aop通知打印控制器請(qǐng)求報(bào)文和返回報(bào)文問(wèn)題

 更新時(shí)間:2018年04月11日 08:44:58   作者:淺淺_淺默  
這篇文章主要介紹了spring-boot 使用Aop通知打印控制器請(qǐng)求報(bào)文和返回報(bào)文,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

一、簡(jiǎn)介

開(kāi)發(fā)過(guò)程中我們往往需要寫(xiě)許多例如: 

@GetMapping("/id/get")
  public Result getById( String id) throws Exception{
    log.info("請(qǐng)求參數(shù)為:"+id);
    verify(new VerifyParam("部門id", id));
    Result result = new Result("通過(guò)id獲取部門信息成功!", service.queryById(id));
    log.info("返回報(bào)文為:"+result.toString());
    return result;
  }

打印請(qǐng)求參數(shù)以及返回參數(shù)的方法,而這些操作存在于每個(gè)方法之中,使得我們代碼較為冗余,為此我們可以通過(guò)動(dòng)態(tài)代理將打印參數(shù)和打印返回報(bào)文作為切面,使用切入點(diǎn)表達(dá)式將其切入至每個(gè)方法之中。

二、步驟

1、引入Aop相關(guān)的依賴:

<!--AOP相關(guān)的依賴-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

引入依賴后spring-aop會(huì)加載其需要的依賴,spring默認(rèn)使用aspectJ實(shí)現(xiàn)通知

其中aspectjweaver.jar中包含了解析aspectJ切入點(diǎn)表達(dá)式的文件,使用切入點(diǎn)表達(dá)式處理事務(wù)的時(shí)候也需要加入此依賴。

2、配置:

1)、創(chuàng)建配置類:

/**
 * @功能描述:用于controller層操作的AOP類
 * @author Administrator
 */
@Component // 將對(duì)象交由spring進(jìn)行管理
@Aspect // 代表此類為一個(gè)切面類
public class ControllerAop {
}

其中@Aspect 注解代表其為一個(gè)切面管理類,可以在其下定義切入點(diǎn)表達(dá)式,aspectJ框架會(huì)進(jìn)行解析。

2)、定義切入點(diǎn)表達(dá)式:

@Pointcut("execution(public * com.hzt.manage.*.web.controller..*.*(..))") // 切入點(diǎn)表達(dá)式
  public void privilege() {
  }

其中,@Pointcut代表此方法為一個(gè)切入點(diǎn)表達(dá)式。其value值為切入點(diǎn)表達(dá)式,其中value可以省略其大致格式為:

  @注解(表達(dá)標(biāo)簽+表達(dá)式格式)
的格式,Spring AOP支持的AspectJ切入點(diǎn)指示符如下:

1、 execution:用于匹配方法執(zhí)行的連接點(diǎn);

2、within:用于匹配指定類型內(nèi)的方法執(zhí)行;

3、this:用于匹配當(dāng)前AOP代理對(duì)象類型的執(zhí)行方法;注意是AOP代理對(duì)象的類型匹配,這樣就可能包括引入接口也類型匹配;

4、target:用于匹配當(dāng)前目標(biāo)對(duì)象類型的執(zhí)行方法;注意是目標(biāo)對(duì)象的類型匹配,這樣就不包括引入接口也類型匹配;

5、args:用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)為指定類型的執(zhí)行方法;

6、@within:用于匹配所以持有指定注解類型內(nèi)的方法;

7、@target:用于匹配當(dāng)前目標(biāo)對(duì)象類型的執(zhí)行方法,其中目標(biāo)對(duì)象持有指定的注解;

8、@args:用于匹配當(dāng)前執(zhí)行的方法傳入的參數(shù)持有指定注解的執(zhí)行;

9、@annotation:用于匹配當(dāng)前執(zhí)行方法持有指定注解的方法;

10、bean:Spring AOP擴(kuò)展的,AspectJ沒(méi)有對(duì)于指示符,用于匹配特定名稱的Bean對(duì)象的執(zhí)行方法;

11、reference pointcut:表示引用其他命名切入點(diǎn),只有@ApectJ風(fēng)格支持,Schema風(fēng)格不支持。

args中定義了切入點(diǎn)表達(dá)式方法執(zhí)行時(shí)候的參數(shù):

  @Pointcut(value="execution(public * com.hzt.manage.*.web.controller..*.*(..))&&args(param)",argNames="param") // 切入點(diǎn)表達(dá)式
  public void privilege1(String param) {
  }

我們重點(diǎn)介紹 execution 方法連接點(diǎn)的表達(dá)式,其大概結(jié)構(gòu)為:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

1、修飾符匹配(modifier-pattern?)(可省略)

2、返回值匹配(ret-type-pattern)可以為*表示任何返回值 ,如 (String) 代表只篩選返回String類型的切入點(diǎn) ,全路徑的類名等(不可省略)

3、類路徑匹配(declaring-type-pattern?)如*.manage代表一級(jí)包為任意,二級(jí)包為manage的名稱。*..manage代表所有manage包下的子類包。com..*.comtroller代表com包下所有的controller包等,*代表所有包都匹配。(不可省略)

4、方法名匹配(name-pattern)可以指定方法名 或者 *代表所有, get* 代表以get開(kāi)頭的所有方法,也可指定前綴*get代表任意后綴為get的方法(不可省略)

5、參數(shù)匹配((param-pattern))可以指定具體的參數(shù)類型,多個(gè)參數(shù)間用“,”隔開(kāi),各個(gè)參數(shù)也可以用“*”來(lái)表示匹配任意類型的參數(shù),如(String)表示匹配一個(gè)String參數(shù)的方法;(*,String) 表示匹配有兩個(gè)參數(shù)的方法,第一個(gè)參數(shù)可以是任意類型,而第二個(gè)參數(shù)是String類型;可以用(..)表示任意參數(shù)(不可省略)

6、異常類型匹配(throws-pattern?)

3、定義切面方法

@Around("privilege()")
  public Object around(ProceedingJoinPoint pjd) throws Throwable {
    // 獲取方法名
    String className = pjd.getSignature().getClass().getName();
    // 獲取執(zhí)行的方法名稱
    String methodName = pjd.getSignature().getName();
    /** 初始化日志打印 */
    Logger log = LoggerFactory.getLogger(className);
    // 定義返回參數(shù)
    Object result = null;
    // 記錄開(kāi)始時(shí)間
    long start = System.currentTimeMillis();
    // 獲取方法參數(shù)
    Object[] args = pjd.getArgs();
    String params = "前端請(qǐng)求參數(shù)為:";
    //獲取請(qǐng)求參數(shù)集合并進(jìn)行遍歷拼接
    for (Object object : args) {
      params += object.toString() + ",";
    }
    params = params.substring(0, params.length() - 1);
    //打印請(qǐng)求參數(shù)參數(shù)
    log.info(className+"類的"+methodName + "的" + params);
    // 執(zhí)行目標(biāo)方法
    result = pjd.proceed();
    // 打印返回報(bào)文
    log.info("方法返回報(bào)文為:" + (result instanceof Result ? (Result) result : result));
    // 獲取執(zhí)行完的時(shí)間
    log.info(methodName + "方法執(zhí)行時(shí)長(zhǎng)為:" + (System.currentTimeMillis() - start));
    return result;
  }

5、@Around 環(huán)繞通知,如上代碼所示便是環(huán)繞通知,其有ProceedingJoinPoint參數(shù)

其中 pjd.proceed();方法代表去執(zhí)行目標(biāo)方法,并獲得一個(gè)Object類型的返回值 ,我們可以對(duì)返回值進(jìn)行加工處理,如裝飾加工等。

return的值為方法執(zhí)行的結(jié)果。上述代碼中首先獲取類名、方法名、方法請(qǐng)求參數(shù)等,進(jìn)行打印的拼接,并且記錄方法執(zhí)行的開(kāi)始時(shí)間,并進(jìn)行打印至日志。

然后執(zhí)行方法,獲取到方法返回結(jié)果,進(jìn)行打印執(zhí)行時(shí)間和執(zhí)行結(jié)果。

最后返回執(zhí)行結(jié)果。即使用Aop打印請(qǐng)求報(bào)文和返回報(bào)文的aop切面編碼結(jié)束。

其中@Around代表其為一個(gè)環(huán)繞通知方法,其有以下幾種類型:

1、@Before前置通知,擁有請(qǐng)求參數(shù) JoinPoint ,用來(lái)連接當(dāng)前連接點(diǎn)的連接細(xì)節(jié),一般包括方法名和參數(shù)值。在方法執(zhí)行前進(jìn)行執(zhí)行方法體,不能改變方法參數(shù),也不能改變方法執(zhí)行結(jié)果。

  @Before(value = "privilege()")
  public void before(JoinPoint joinPoint) {
  }

2、@After 后置通知:在目標(biāo)方法執(zhí)行之后,無(wú)論是否發(fā)生異常,都進(jìn)行執(zhí)行的通知。在后置通知中,不能訪問(wèn)目標(biāo)方法的執(zhí)行結(jié)果(因?yàn)橛锌赡馨l(fā)生異常),不能改變方法執(zhí)行結(jié)果。

@Before(value = "privilege()")
  public void after(JoinPoint joinPoint) {    
  }

3、@AfterReturning 返回通知,在目標(biāo)方法執(zhí)行結(jié)束時(shí),才執(zhí)行的通知,同后置方法相同。其能訪問(wèn)方法執(zhí)行結(jié)果(因?yàn)檎?zhí)行)和方法的連接細(xì)節(jié),但是不能改變方法執(zhí)行結(jié)果。

  @AfterReturning(value = "privilege()")
  public void afterReturing(JoinPoint joinPoint,Object result) {
  }

result中存放的為方法的返回值。

4、@AfterThrowing 異常通知:在目標(biāo)方法出現(xiàn)異常時(shí)才會(huì)進(jìn)行執(zhí)行的代碼。 throwing屬性代表方法體執(zhí)行時(shí)候拋出的異常,其值一定與方法中Exception的值需要一致。

  @AfterThrowing(value="privilege()",throwing="ex")
  public void exce(JoinPoint joinPoint, Exception ex) {    
  }

三、測(cè)試

編寫(xiě)一個(gè)Controller方法

@RestController
@RequestMapping("/api/v1/dept")
public class DeptController extends BaseController{
  /** 日志記錄類 */
  private Logger log = LoggerFactory.getLogger(getClass());
  /** 自家的service */
  @Autowired
  private DeptService service;
  /**
   * @功能描述:根據(jù)id查詢部門內(nèi)容的方法
   * @return Dept
   */
  @GetMapping("/id/get")
  public Result getById( String id) throws Exception{
    verify(new VerifyParam("部門id", id));
    return new Result("通過(guò)id獲取部門信息成功!", service.queryById(id));
  }
}

如此我們的controller層中的方法就大大的簡(jiǎn)潔了。

測(cè)試結(jié)果:

2018-04-10 22:59:27.468  INFO 1460 --- [nio-8088-exec-5] nProceedingJoinPoint$MethodSignatureImpl : getById的前端請(qǐng)求參數(shù)為:22
2018-04-10 22:59:27.470  INFO 1460 --- [nio-8088-exec-5] nProceedingJoinPoint$MethodSignatureImpl : 方法返回報(bào)文為:Result [result_code=suc, result_message=通過(guò)id獲取部門信息成功!, data=Dept [id=22, no=22, name=22, manager=22, description=22, phone=22, createTime=Thu Apr 19 23:38:37 CST 2018, editTime=null]]
2018-04-10 22:59:27.470  INFO 1460 --- [nio-8088-exec-5] nProceedingJoinPoint$MethodSignatureImpl : getById方法執(zhí)行時(shí)長(zhǎng)為:2

如此便能很雅觀簡(jiǎn)潔隱式的打印請(qǐng)求參數(shù)、返回結(jié)果和執(zhí)行時(shí)間等!

相關(guān)文章

  • JavaWeb中上傳和下載文件實(shí)例代碼

    JavaWeb中上傳和下載文件實(shí)例代碼

    這篇文章主要介紹了JavaWeb中上傳和下載文件實(shí)例代碼,需要的朋友可以參考下
    2017-06-06
  • SpringBoot使用@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)的并行執(zhí)行

    SpringBoot使用@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)的并行執(zhí)行

    在SpringBoot中,如果使用@Scheduled注解來(lái)定義多個(gè)定時(shí)任務(wù),默認(rèn)情況下這些任務(wù)將會(huì)被安排在一個(gè)單線程的調(diào)度器中執(zhí)行,這意味著,這些任務(wù)將會(huì)串行執(zhí)行,而不是并行執(zhí)行,本文介紹了SpringBoot使用@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)的并行執(zhí)行,需要的朋友可以參考下
    2024-06-06
  • 淺談Java編程中string的理解與運(yùn)用

    淺談Java編程中string的理解與運(yùn)用

    這篇文章主要介紹了淺談Java編程中string的理解與運(yùn)用,還是比較不錯(cuò)的,這里分享給大家,供需要的朋友參考。
    2017-11-11
  • springboot使用Hutool的JschUtil及下載安裝步驟

    springboot使用Hutool的JschUtil及下載安裝步驟

    這篇文章主要為大家介紹了springboot使用Hutool的JschUtil的方法及下載安裝詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Echarts+SpringMvc顯示后臺(tái)實(shí)時(shí)數(shù)據(jù)

    Echarts+SpringMvc顯示后臺(tái)實(shí)時(shí)數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了Echarts+SpringMvc顯示后臺(tái)實(shí)時(shí)數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • 淺談Spring中單例Bean是線程安全的嗎

    淺談Spring中單例Bean是線程安全的嗎

    這篇文章主要介紹了淺談Spring中單例Bean是線程安全的嗎?具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • 詳解mybatis generator代碼生成器的使用

    詳解mybatis generator代碼生成器的使用

    MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代碼生成器。這篇文章主要介紹了mybatis generator代碼生成器的使用,需要的朋友可以參考下
    2021-09-09
  • mybatis-plus 如何操作json字段

    mybatis-plus 如何操作json字段

    這篇文章主要介紹了mybatis-plus 如何操作json字段,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 一文搞懂SpringBoot如何利用@Async實(shí)現(xiàn)異步調(diào)用

    一文搞懂SpringBoot如何利用@Async實(shí)現(xiàn)異步調(diào)用

    異步調(diào)用幾乎是處理高并發(fā),解決性能問(wèn)題常用的手段,如何開(kāi)啟異步調(diào)用?SpringBoot中提供了非常簡(jiǎn)單的方式,就是一個(gè)注解@Async。今天我們重新認(rèn)識(shí)一下@Async,以及注意事項(xiàng)
    2022-09-09
  • 淺談Java8 的foreach跳出循環(huán)break/return

    淺談Java8 的foreach跳出循環(huán)break/return

    這篇文章主要介紹了Java8 的foreach跳出循環(huán)break/return,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07

最新評(píng)論

武邑县| 赣州市| 南宫市| 苍梧县| 隆子县| 安义县| 海兴县| 大关县| 枣庄市| 宁河县| 临安市| 融水| 江门市| 乐昌市| 临夏县| 富川| 仁怀市| 象山县| 抚宁县| 河北省| 巴林右旗| 永泰县| 淳安县| 改则县| 屯昌县| 科技| 翁源县| 镇康县| 喜德县| 南通市| 都江堰市| 景德镇市| 周至县| 嘉祥县| 惠州市| 牡丹江市| 万载县| 玛沁县| 澎湖县| 越西县| 高雄县|