0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SpringBoot統(tǒng)一功能處理

jf_ro2CN3Fa ? 來(lái)源:CSDN ? 2023-04-19 14:51 ? 次閱讀

本篇將要學(xué)習(xí) Spring Boot 統(tǒng)一功能處理模塊,這也是 AOP 的實(shí)戰(zhàn)環(huán)節(jié)

用戶登錄權(quán)限的校驗(yàn)實(shí)現(xiàn)接口 HandlerInterceptor + WebMvcConfigurer

異常處理使用注解 @RestControllerAdvice + @ExceptionHandler

數(shù)據(jù)格式返回使用注解 @ControllerAdvice 并且實(shí)現(xiàn)接口 @ResponseBodyAdvice

1. 統(tǒng)一用戶登錄權(quán)限效驗(yàn)

用戶登錄權(quán)限的發(fā)展完善過(guò)程

最初用戶登錄效驗(yàn): 在每個(gè)方法中獲取 Session 和 Session 中的用戶信息,如果存在用戶,那么就認(rèn)為登錄成功了,否則就登錄失敗了

第二版用戶登錄效驗(yàn): 提供統(tǒng)一的方法,在每個(gè)需要驗(yàn)證的方法中調(diào)用統(tǒng)一的用戶登錄身份效驗(yàn)方法來(lái)判斷

第三版用戶登錄效驗(yàn): 使用 Spring AOP 來(lái)統(tǒng)一進(jìn)行用戶登錄效驗(yàn)

第四版用戶登錄效驗(yàn): 使用 Spring 攔截器來(lái)實(shí)現(xiàn)用戶的統(tǒng)一登錄驗(yàn)證

1.1 最初用戶登錄權(quán)限效驗(yàn)

@RestController
@RequestMapping("/user")
publicclassUserController{

@RequestMapping("/a1")
publicBooleanlogin(HttpServletRequestrequest){
//有Session就獲取,沒(méi)有就不創(chuàng)建
HttpSessionsession=request.getSession(false);
if(session!=null&&session.getAttribute("userinfo")!=null){
//說(shuō)明已經(jīng)登錄,進(jìn)行業(yè)務(wù)處理
returntrue;
}else{
//未登錄
returnfalse;
}
}

@RequestMapping("/a2")
publicBooleanlogin2(HttpServletRequestrequest){
//有Session就獲取,沒(méi)有就不創(chuàng)建
HttpSessionsession=request.getSession(false);
if(session!=null&&session.getAttribute("userinfo")!=null){
//說(shuō)明已經(jīng)登錄,進(jìn)行業(yè)務(wù)處理
returntrue;
}else{
//未登錄
returnfalse;
}
}
}

這種方式寫(xiě)的代碼,每個(gè)方法中都有相同的用戶登錄驗(yàn)證權(quán)限,缺點(diǎn)是:

每個(gè)方法中都要單獨(dú)寫(xiě)用戶登錄驗(yàn)證的方法,即使封裝成公共方法,也一樣要傳參調(diào)用和在方法中進(jìn)行判斷

添加控制器越多,調(diào)用用戶登錄驗(yàn)證的方法也越多,這樣就增加了后期的修改成功和維護(hù)成功

這些用戶登錄驗(yàn)證的方法和現(xiàn)在要實(shí)現(xiàn)的業(yè)務(wù)幾乎沒(méi)有任何關(guān)聯(lián),但還是要在每個(gè)方法中都要寫(xiě)一遍,所以提供一個(gè)公共的 AOP 方法來(lái)進(jìn)行統(tǒng)一的用戶登錄權(quán)限驗(yàn)證是非常好的解決辦法。

1.2 Spring AOP 統(tǒng)一用戶登錄驗(yàn)證

統(tǒng)一用戶登錄驗(yàn)證,首先想到的實(shí)現(xiàn)方法是使用 Spring AOP 前置通知或環(huán)繞通知來(lái)實(shí)現(xiàn)

@Aspect//當(dāng)前類是一個(gè)切面
@Component
publicclassUserAspect{
//定義切點(diǎn)方法Controller包下、子孫包下所有類的所有方法
@Pointcut("execution(*com.example.springaop.controller..*.*(..))")
publicvoidpointcut(){}

//前置通知
@Before("pointcut()")
publicvoiddoBefore(){}

//環(huán)繞通知
@Around("pointcut()")
publicObjectdoAround(ProceedingJoinPointjoinPoint){
Objectobj=null;
System.out.println("Around方法開(kāi)始執(zhí)行");
try{
obj=joinPoint.proceed();
}catch(Throwablee){
e.printStackTrace();
}
System.out.println("Around方法結(jié)束執(zhí)行");
returnobj;
}
}

但如果只在以上代碼 Spring AOP 的切面中實(shí)現(xiàn)用戶登錄權(quán)限效驗(yàn)的功能,有這樣兩個(gè)問(wèn)題:

沒(méi)有辦法得到 HttpSession 和 Request 對(duì)象

我們要對(duì)一部分方法進(jìn)行攔截,而另一部分方法不攔截,比如注冊(cè)方法和登錄方法是不攔截的,也就是實(shí)際的攔截規(guī)則很復(fù)雜,使用簡(jiǎn)單的 aspectJ 表達(dá)式無(wú)法滿足攔截的需求

1.3 Spring 攔截器

針對(duì)上面代碼 Spring AOP 的問(wèn)題,Spring 中提供了具體的實(shí)現(xiàn)攔截器:HandlerInterceptor,攔截器的實(shí)現(xiàn)有兩步:

1.創(chuàng)建自定義攔截器,實(shí)現(xiàn) Spring 中的 HandlerInterceptor 接口中的 preHandle方法

2.將自定義攔截器加入到框架的配置中,并且設(shè)置攔截規(guī)則

給當(dāng)前的類添加 @Configuration 注解

實(shí)現(xiàn) WebMvcConfigurer 接口

重寫(xiě) addInterceptors 方法

注意:一個(gè)項(xiàng)目中可以同時(shí)配置多個(gè)攔截器

(1)創(chuàng)建自定義攔截器

/**
*@Description:自定義用戶登錄的攔截器
*@Date2023/2/1313:06
*/
@Component
publicclassLoginInterceptimplementsHandlerInterceptor{
//返回true表示攔截判斷通過(guò),可以訪問(wèn)后面的接口
//返回false表示攔截未通過(guò),直接返回結(jié)果給前端
@Override
publicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,
Objecthandler)throwsException{
//1.得到HttpSession對(duì)象
HttpSessionsession=request.getSession(false);
if(session!=null&&session.getAttribute("userinfo")!=null){
//表示已經(jīng)登錄
returntrue;
}
//執(zhí)行到此代碼表示未登錄,未登錄就跳轉(zhuǎn)到登錄頁(yè)面
response.sendRedirect("/login.html");
returnfalse;
}
}

(2)將自定義攔截器添加到系統(tǒng)配置中,并設(shè)置攔截的規(guī)則

addPathPatterns:表示需要攔截的 URL,**表示攔截所有?法

excludePathPatterns:表示需要排除的 URL

說(shuō)明:攔截規(guī)則可以攔截此項(xiàng)?中的使? URL,包括靜態(tài)?件(圖??件、JS 和 CSS 等?件)。

/**
*@Description:將自定義攔截器添加到系統(tǒng)配置中,并設(shè)置攔截的規(guī)則
*@Date2023/2/1313:13
*/
@Configuration
publicclassAppConfigimplementsWebMvcConfigurer{

@Resource
privateLoginInterceptloginIntercept;

@Override
publicvoidaddInterceptors(InterceptorRegistryregistry){
//registry.addInterceptor(newLoginIntercept());//可以直接new也可以屬性注入
registry.addInterceptor(loginIntercept).
addPathPatterns("/**").//攔截所有url
excludePathPatterns("/user/login").//不攔截登錄注冊(cè)接口
excludePathPatterns("/user/reg").
excludePathPatterns("/login.html").
excludePathPatterns("/reg.html").
excludePathPatterns("/**/*.js").
excludePathPatterns("/**/*.css").
excludePathPatterns("/**/*.png").
excludePathPatterns("/**/*.jpg");
}
}

1.4 練習(xí):登錄攔截器

要求

登錄、注冊(cè)頁(yè)面不攔截,其他頁(yè)面都攔截

當(dāng)?shù)卿洺晒?xiě)入 session 之后,攔截的頁(yè)面可正常訪問(wèn)

在 1.3 中已經(jīng)創(chuàng)建了自定義攔截器 和 將自定義攔截器添加到系統(tǒng)配置中,并設(shè)置攔截的規(guī)則

(1)下面創(chuàng)建登錄和首頁(yè)的 html

38026caa-de7c-11ed-bfe3-dac502259ad0.png

(2)創(chuàng)建 controller 包,在包中創(chuàng)建 UserController,寫(xiě)登錄頁(yè)面和首頁(yè)的業(yè)務(wù)代碼

@RestController
@RequestMapping("/user")
publicclassUserController{

@RequestMapping("/login")
publicbooleanlogin(HttpServletRequestrequest,Stringusername,Stringpassword){
booleanresult=false;
if(StringUtils.hasLength(username)&&StringUtils.hasLength(password)){
if(username.equals("admin")&&password.equals("admin")){
HttpSessionsession=request.getSession();
session.setAttribute("userinfo","userinfo");
returntrue;
}
}
returnresult;
}

@RequestMapping("/index")
publicStringindex(){
return"HelloIndex";
}
}

(3)運(yùn)行程序,訪問(wèn)頁(yè)面,對(duì)比登錄前和登錄后的效果

3811586e-de7c-11ed-bfe3-dac502259ad0.png381bb926-de7c-11ed-bfe3-dac502259ad0.png

1.5 攔截器實(shí)現(xiàn)原理

有了攔截器之后,會(huì)在調(diào)? Controller 之前進(jìn)?相應(yīng)的業(yè)務(wù)處理,執(zhí)?的流程如下圖所示

382522e0-de7c-11ed-bfe3-dac502259ad0.png

實(shí)現(xiàn)原理源碼分析

所有的 Controller 執(zhí)行都會(huì)通過(guò)一個(gè)調(diào)度器 DispatcherServlet 來(lái)實(shí)現(xiàn)

382c5cd6-de7c-11ed-bfe3-dac502259ad0.png

而所有方法都會(huì)執(zhí)行 DispatcherServlet 中的 doDispatch 調(diào)度?法,doDispatch 源碼分析如下:

3833f4a0-de7c-11ed-bfe3-dac502259ad0.png

通過(guò)源碼分析,可以看出,Sping 中的攔截器也是通過(guò)動(dòng)態(tài)代理和環(huán)繞通知的思想實(shí)現(xiàn)的

1.6 統(tǒng)一訪問(wèn)前綴添加

所有請(qǐng)求地址添加 api 前綴,c 表示所有

@Configuration
publicclassAppConfigimplementsWebMvcConfigurer{
//所有的接口添加api前綴
@Override
publicvoidconfigurePathMatch(PathMatchConfigurerconfigurer){
configurer.addPathPrefix("api",c->true);
}
}
383ead96-de7c-11ed-bfe3-dac502259ad0.png

2. 統(tǒng)一異常處理

給當(dāng)前的類上加 @ControllerAdvice 表示控制器通知類

給方法上添加 @ExceptionHandler(xxx.class),表示異常處理器,添加異常返回的業(yè)務(wù)代碼

@RestController
@RequestMapping("/user")
publicclassUserController{
@RequestMapping("/index")
publicStringindex(){
intnum=10/0;
return"HelloIndex";
}
}

在 config 包中,創(chuàng)建 MyExceptionAdvice 類

@RestControllerAdvice//當(dāng)前是針對(duì)Controller的通知類(增強(qiáng)類)
publicclassMyExceptionAdvice{
@ExceptionHandler(ArithmeticException.class)
publicHashMaparithmeticExceptionAdvice(ArithmeticExceptione){
HashMapresult=newHashMap<>();
result.put("state",-1);
result.put("data",null);
result.put("msg","算出異常:"+e.getMessage());
returnresult;
}
}

也可以這樣寫(xiě),效果是一樣的

@ControllerAdvice
publicclassMyExceptionAdvice{
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
publicHashMaparithmeticExceptionAdvice(ArithmeticExceptione){
HashMapresult=newHashMap<>();
result.put("state",-1);
result.put("data",null);
result.put("msg","算數(shù)異常:"+e.getMessage());
returnresult;
}
}
38442406-de7c-11ed-bfe3-dac502259ad0.png

如果再有一個(gè)空指針異常,那么上面的代碼是不行的,還要寫(xiě)一個(gè)針對(duì)空指針異常處理器

@ExceptionHandler(NullPointerException.class)
publicHashMapnullPointerExceptionAdvice(NullPointerExceptione){
HashMapresult=newHashMap<>();
result.put("state",-1);
result.put("data",null);
result.put("msg","空指針異常異常:"+e.getMessage());
returnresult;
}
@RequestMapping("/index")
publicStringindex(HttpServletRequestrequest,Stringusername,Stringpassword){
Objectobj=null;
System.out.println(obj.hashCode());
return"HelloIndex";
}
38495d86-de7c-11ed-bfe3-dac502259ad0.png

但是需要考慮的一點(diǎn)是,如果每個(gè)異常都這樣寫(xiě),那么工作量是非常大的,并且還有自定義異常,所以上面這樣寫(xiě)肯定是不好的,既然是異常直接寫(xiě) Exception 就好了,它是所有異常的父類,如果遇到不是前面寫(xiě)的兩種異常,那么就會(huì)直接匹配到 Exception

當(dāng)有多個(gè)異常通知時(shí),匹配順序?yàn)楫?dāng)前類及其?類向上依次匹配

@ExceptionHandler(Exception.class)
publicHashMapexceptionAdvice(Exceptione){
HashMapresult=newHashMap<>();
result.put("state",-1);
result.put("data",null);
result.put("msg","異常:"+e.getMessage());
returnresult;
}

可以看到優(yōu)先匹配的還是前面寫(xiě)的 空指針異常

3852b372-de7c-11ed-bfe3-dac502259ad0.png

3. 統(tǒng)一數(shù)據(jù)格式返回

3.1 統(tǒng)一數(shù)據(jù)格式返回的實(shí)現(xiàn)

1.給當(dāng)前類添加 @ControllerAdvice

2.實(shí)現(xiàn) ResponseBodyAdvice 重寫(xiě)其方法

supports 方法,此方法表示內(nèi)容是否需要重寫(xiě)(通過(guò)此?法可以選擇性部分控制器和方法進(jìn)行重寫(xiě)),如果要重寫(xiě)返回 true

beforeBodyWrite 方法,方法返回之前調(diào)用此方法

@ControllerAdvice
publicclassMyResponseAdviceimplementsResponseBodyAdvice{

//返回一個(gè)boolean值,true表示返回?cái)?shù)據(jù)之前對(duì)數(shù)據(jù)進(jìn)行重寫(xiě),也就是會(huì)進(jìn)入beforeBodyWrite方法
//返回false表示對(duì)結(jié)果不進(jìn)行任何處理,直接返回
@Override
publicbooleansupports(MethodParameterreturnType,ClassconverterType){
returntrue;
}

//方法返回之前調(diào)用此方法
@Override
publicObjectbeforeBodyWrite(Objectbody,MethodParameterreturnType,MediaTypeselectedContentType,ClassselectedConverterType,ServerHttpRequestrequest,ServerHttpResponseresponse){
HashMapresult=newHashMap<>();
result.put("state",1);
result.put("data",body);
result.put("msg","");
returnresult;
}
}
@RestController
@RequestMapping("/user")
publicclassUserController{

@RequestMapping("/login")
publicbooleanlogin(HttpServletRequestrequest,Stringusername,Stringpassword){
booleanresult=false;
if(StringUtils.hasLength(username)&&StringUtils.hasLength(password)){
if(username.equals("admin")&&password.equals("admin")){
HttpSessionsession=request.getSession();
session.setAttribute("userinfo","userinfo");
returntrue;
}
}
returnresult;
}

@RequestMapping("/reg")
publicintreg(){
return1;
}
}
385dbbd2-de7c-11ed-bfe3-dac502259ad0.png

3.2 @ControllerAdvice 源碼分析

通過(guò)對(duì) @ControllerAdvice 源碼的分析我們可以知道上面統(tǒng)一異常和統(tǒng)一數(shù)據(jù)返回的執(zhí)行流程

(1)先看 @ControllerAdvice 源碼

386660ac-de7c-11ed-bfe3-dac502259ad0.png

可以看到 @ControllerAdvice 派生于 @Component 組件而所有組件初始化都會(huì)調(diào)用 InitializingBean 接口

(2)下面查看 initializingBean 有哪些實(shí)現(xiàn)類

在查詢過(guò)程中發(fā)現(xiàn),其中 Spring MVC 中的實(shí)現(xiàn)子類是 RequestMappingHandlerAdapter,它里面有一個(gè)方法 afterPropertiesSet()方法,表示所有的參數(shù)設(shè)置完成之后執(zhí)行的方法

386cc3e8-de7c-11ed-bfe3-dac502259ad0.png

(3)而這個(gè)方法中有一個(gè) initControllerAdviceCache 方法,查詢此方法

3877f98e-de7c-11ed-bfe3-dac502259ad0.png

發(fā)現(xiàn)這個(gè)方法在執(zhí)行時(shí)會(huì)查找使用所有的 @ControllerAdvice 類,發(fā)送某個(gè)事件時(shí),調(diào)用相應(yīng)的 Advice 方法,比如返回?cái)?shù)據(jù)前調(diào)用統(tǒng)一數(shù)據(jù)封裝,比如發(fā)生異常是調(diào)用異常的 Advice 方法實(shí)現(xiàn)的。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 控制器
    +關(guān)注

    關(guān)注

    112

    文章

    16361

    瀏覽量

    178045
  • URL
    URL
    +關(guān)注

    關(guān)注

    0

    文章

    139

    瀏覽量

    15340
  • CSS
    CSS
    +關(guān)注

    關(guān)注

    0

    文章

    109

    瀏覽量

    14375
  • API接口
    +關(guān)注

    關(guān)注

    1

    文章

    84

    瀏覽量

    10438
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    173

    瀏覽量

    179

原文標(biāo)題:SpringBoot 統(tǒng)一功能處理:用戶登錄權(quán)限校驗(yàn)-攔截器、異常處理、數(shù)據(jù)格式返回

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    SpringBoot中的Druid介紹

    SpringBoot中Druid數(shù)據(jù)源配置
    發(fā)表于 05-07 09:21

    SpringBoot知識(shí)總結(jié)

    SpringBoot干貨學(xué)習(xí)總結(jié)
    發(fā)表于 08-01 10:40

    怎么學(xué)習(xí)SpringBoot

    SpringBoot學(xué)習(xí)之路(X5)- 整合JPA
    發(fā)表于 06-10 14:52

    springboot集成mqtt

    springboot集成mqtt,大綱.數(shù)據(jù)入庫(kù)1.數(shù)據(jù)入庫(kù)解決方案二.開(kāi)發(fā)實(shí)時(shí)訂閱發(fā)布展示頁(yè)面1.及時(shí)通訊技術(shù)2.技術(shù)整合
    發(fā)表于 07-16 07:53

    怎樣去使用springboot

    怎樣去使用springboot呢?學(xué)習(xí)springboot需要懂得哪些?
    發(fā)表于 10-25 07:13

    SpringBoot應(yīng)用啟動(dòng)運(yùn)行run方法

    )、refreshContext(context);SpringBoot刷新IOC容器【創(chuàng)建IOC容器對(duì)象,并初始化容器,創(chuàng)建容器中的每個(gè)組件】;如果是web應(yīng)用創(chuàng)建**AnnotationConfigEmbeddedWebApplicationContext**,否則
    發(fā)表于 12-20 06:16

    怎樣去設(shè)計(jì)個(gè)基于springboot+freemark+jpa+MySQL的在線電影訂票系統(tǒng)

    本系統(tǒng)是由springboot+freemark+jpa+MySQL實(shí)現(xiàn)的在線電影訂票系統(tǒng),主要的亮點(diǎn)功能有:支持短信發(fā)送接口、支付寶在線支付接口、座位鎖定及并發(fā)處理、排片時(shí)間沖突檢測(cè)等。本系統(tǒng)主要
    發(fā)表于 01-03 07:22

    Springboot是如何獲取自定義異常并進(jìn)行返回的

    源碼剖析Springboot是如何獲取自定義異常并進(jìn)行返回的。來(lái)吧!第步:肯定是在Springboot啟動(dòng)的過(guò)程中進(jìn)行的異常處理初始化,于是就找到了handlerExceptionR
    發(fā)表于 03-22 14:15

    公司這套架構(gòu)統(tǒng)一處理try...catch真香!

    有大量的冗余代碼,而且還影響代碼的可讀性。這樣就需要定義個(gè)全局統(tǒng)一異常處理器,以便業(yè)務(wù)層再也不必處理異常。
    的頭像 發(fā)表于 02-27 10:47 ?479次閱讀

    什么是 SpringBoot?

    本文從為什么要有 `SpringBoot`,以及 `SpringBoot` 到底方便在哪里開(kāi)始入手,逐步分析了 `SpringBoot` 自動(dòng)裝配的原理,最后手寫(xiě)了個(gè)簡(jiǎn)單的 `sta
    的頭像 發(fā)表于 04-07 11:28 ?1315次閱讀
    什么是 <b class='flag-5'>SpringBoot</b>?

    SpringBoot的核心注解1

    今天跟大家來(lái)探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達(dá)到零配置
    的頭像 發(fā)表于 04-07 14:34 ?707次閱讀
    <b class='flag-5'>SpringBoot</b>的核心注解1

    SpringBoot的核心注解2

    今天跟大家來(lái)探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達(dá)到零配置
    的頭像 發(fā)表于 04-07 14:34 ?1964次閱讀
    <b class='flag-5'>SpringBoot</b>的核心注解2

    使用springboot完成流程的業(yè)務(wù)功能

    使用springboot開(kāi)發(fā)流程使用的接口完成流程的業(yè)務(wù)功能 基于 Spring Boot + MyBatis Plus + Vue Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC
    的頭像 發(fā)表于 05-15 17:40 ?731次閱讀
    使用<b class='flag-5'>springboot</b>完成流程的業(yè)務(wù)<b class='flag-5'>功能</b>

    springboot統(tǒng)一異常處理

    限流對(duì)于個(gè)微服務(wù)架構(gòu)系統(tǒng)來(lái)說(shuō)具有非常重要的意義,否則其中的某個(gè)微服務(wù)將成為整個(gè)系統(tǒng)隱藏的雪崩因素,為什么這么說(shuō)?
    的頭像 發(fā)表于 07-25 16:11 ?662次閱讀
    <b class='flag-5'>springboot</b><b class='flag-5'>統(tǒng)一</b>異常<b class='flag-5'>處理</b>

    SpringBoot攔截器與統(tǒng)一功能處理實(shí)戰(zhàn)

    Spring AOP是個(gè)基于面向切面編程的框架,用于將橫切性關(guān)注點(diǎn)(如日志記錄、事務(wù)管理)與業(yè)務(wù)邏輯分離,通過(guò)代理對(duì)象將這些關(guān)注點(diǎn)織入到目標(biāo)對(duì)象的方法執(zhí)行前后、拋出異常或返回結(jié)果時(shí)等特定位置執(zhí)行,從而提高程序的可復(fù)用性、可維護(hù)性和靈活性。
    的頭像 發(fā)表于 08-27 10:44 ?871次閱讀
    <b class='flag-5'>SpringBoot</b>攔截器與<b class='flag-5'>統(tǒng)一</b><b class='flag-5'>功能</b><b class='flag-5'>處理</b>實(shí)戰(zhàn)