SpringMVC-2-Spring MVC攔截器詳解:從入門到精通
今日目標(biāo)
能夠編寫攔截器并配置攔截器
1.攔截器【理解】
1 攔截器介紹
1.1 攔截器概念和作用
-
攔截器(Interceptor)是一種動(dòng)態(tài)攔截方法調(diào)用的機(jī)制,在SpringMVC中動(dòng)態(tài)攔截控制器方法的執(zhí)行
- 作用:
-
在指定的方法調(diào)用前后執(zhí)行預(yù)先設(shè)定的代碼
-
阻止原始方法的執(zhí)行
-
總結(jié):增強(qiáng)
-
-
核心原理:AOP思想
1.2 攔截器和過濾器的區(qū)別
-
歸屬不同:Filter屬于Servlet技術(shù),Interceptor屬于SpringMVC技術(shù)
-
攔截內(nèi)容不同:Filter對(duì)所有訪問進(jìn)行增強(qiáng),Interceptor僅針對(duì)SpringMVC的訪問進(jìn)行增強(qiáng)
1.3 攔截器應(yīng)用場(chǎng)景
攔截器本質(zhì)上是面向切面編程(AOP),符合橫切關(guān)注點(diǎn)的功能都可以放在攔截器中來實(shí)現(xiàn),主要的應(yīng)用場(chǎng)景包括:
-
登錄驗(yàn)證,判斷用戶是否登錄。
-
權(quán)限驗(yàn)證,判斷用戶是否有權(quán)限訪問資源,如校驗(yàn)token
-
日志記錄,記錄請(qǐng)求操作日志(用戶ip,訪問時(shí)間等),以便統(tǒng)計(jì)請(qǐng)求訪問量。
-
處理cookie、本地化、國際化、主題等。
-
性能監(jiān)控,監(jiān)控請(qǐng)求處理時(shí)長等。
2 入門案例
2.1 實(shí)現(xiàn)步驟
1?創(chuàng)建web工程(Maven?web結(jié)構(gòu))
2?導(dǎo)入坐標(biāo)(SpringMVC+Servlet)
3?SpringMVCConfig?配置類?配置前綴”/pages/”和后綴”.jsp”
4?ServletConfig?配置類創(chuàng)建IOC容器和攔截請(qǐng)求路徑”/”
5?自定義控制器類(StudentController)
6?開發(fā)視圖頁面/pages/success.jsp
2.2 代碼實(shí)現(xiàn)
【第一步】創(chuàng)建web工程(Maven結(jié)構(gòu))
【第二步】導(dǎo)入坐標(biāo)(SpringMVC+Servlet)
<dependencies>?
?<!--spring-webmvc-->??
?<dependency>?
???<groupId>org.springframework</groupId>??
???<artifactId>spring-webmvc</artifactId>??
???<version>5.3.15</version>?
?</dependency>??
?<!--servlet-->??
?<dependency>?
???<groupId>javax.servlet</groupId>??
???<artifactId>javax.servlet-api</artifactId>??
???<version>4.0.1</version>??
???<scope>provided</scope>?
?</dependency>?
</dependencies>?
【第三步】創(chuàng)建SpringMvc配置文件
/**
*?SpringMVC配置類
*/
@Configuration?//1.標(biāo)識(shí)當(dāng)前是配置類?指定這個(gè)類為配置類,替代application.xml
@ComponentScan("com.zbbmeta")//2.配置掃描web層包?代替<context:component-scan?base-package="com.zbbmeta"?/>
@EnableWebMvc?//如果使用接口的方式,攔截器需要添加這個(gè)注解。不建議使用這種方式,兩種方式只能配置一種,否則會(huì)有沖突
public?class?SpringMvcConfig?{
}
【第四步】創(chuàng)建Web容器初始化的配置類
public?class?ServletConfig??extends?AbstractAnnotationConfigDispatcherServletInitializer?{
????//?暫時(shí)不管,整合Spring才需要
????@Override
????protected?Class<?>[]?getRootConfigClasses()?{
????????return?new?Class[0];
????}
????//在tomcat啟動(dòng)時(shí)調(diào)用,用于創(chuàng)建springmvc框架的IOC容器對(duì)象
????//加載springmvc配置類,?Tomcat會(huì)拿這個(gè)配置類去創(chuàng)建IoC容器,產(chǎn)生springmvc容器(本質(zhì)還是spring容器)
????@Override
????protected?Class<?>[]?getServletConfigClasses()?{
????????return?new?Class[]?{SpringMvcConfig.class};
????}
????//?指定SpringMVC要處理哪些請(qǐng)求,?/表示SpringMVC處理項(xiàng)目中的所有請(qǐng)求,?靜態(tài)資源不要讓SpringMVC處理,要放行
????//設(shè)置DispatcherServlet綁定處理請(qǐng)求的路徑"/",處理除了jsp的所有資源請(qǐng)求
????@Override
????protected?String[]?getServletMappings()?{
????????return?new?String[]?{"/"};
????}
}
【第五步】創(chuàng)建控制器
package?com.zbbmeta.controller;
import?org.springframework.web.bind.annotation.RequestMapping;
import?org.springframework.web.bind.annotation.RestController;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/student")//RequestMapping可以在類或者方法上添加
public?class?StudentController?{
????/**
?????*?查找Student
?????*/
????@RequestMapping("/find")
????public?String?find(HttpServletRequest?request,?HttpServletResponse?response)?{
????????System.out.println("查找Student");
????????return?"find?success";
????}
}
2.3 攔截器代碼實(shí)現(xiàn)
【第一步】定義攔截器
做法:定義一個(gè)類,實(shí)現(xiàn)HandlerInterceptor接口即可
package?com.zbbmeta.Iinterceptor;
import?org.springframework.web.servlet.HandlerInterceptor;
import?org.springframework.web.servlet.ModelAndView;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
public?class?StudentInterceptor?implements?HandlerInterceptor?{
????//原始方法調(diào)用前執(zhí)行的內(nèi)容
????//返回值類型可以攔截控制的執(zhí)行,true放行,false終止
????@Override
????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{
????????System.out.println("=================前置通知=================");
????????return?true;
????}
????//原始方法調(diào)用后執(zhí)行的內(nèi)容
????@Override
????public?void?postHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?ModelAndView?modelAndView)?throws?Exception?{
????????System.out.println("=================后置通知=================");
????}
????//原始方法調(diào)用完成后執(zhí)行的內(nèi)容
????@Override
????public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?Exception?ex)?throws?Exception?{
????????System.out.println("=================最終通知=================");
????}
}
【第二步】配置加載攔截器
配置加載攔截器的方式有兩種我們分別介紹:
加載攔截器方法1:
注:@Configuration注解已經(jīng)包含@Component的功能
-
在上面添加靜態(tài)資源的配置類中重寫addInterceptors方法
-
添加攔截器和多個(gè)攔截路徑:/book和/book/**
-
要注入攔截器對(duì)象
package?com.zbbmeta.config;
import?com.zbbmeta.Iinterceptor.StudentInterceptor;
import?org.springframework.context.annotation.Configuration;
import?org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import?org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public?class?SpringMvcSupport?extends?WebMvcConfigurationSupport?{
????@Override
????protected?void?addInterceptors(InterceptorRegistry?registry)?{
????????//注解攔截器和攔截地址???表示添加?StudentInterceptor??取攔截路徑是?/student/*?所有請(qǐng)求
????????registry.addInterceptor(new?StudentInterceptor()).addPathPatterns("/student/*");
????}
}
加載攔截器方法2:
使用標(biāo)準(zhǔn)接口WebMvcConfigurer簡化開發(fā)(注意:侵入式較強(qiáng))
-
在SpringMvcConfig主配置類上實(shí)現(xiàn)WebMvcConfigurer接口,接口中全是默認(rèn)方法
-
注入攔截器對(duì)象,重寫addInterceptors方法
注:與方式一兩者只能選一種,不然會(huì)有沖突,如果方式一起作用會(huì)導(dǎo)致第二種方式的攔截器不起使用。
即:如果項(xiàng)目中出現(xiàn)了一次 extends WebMvcConfigurationSupport ,其他的 extends WebMvcConfigurationSupport 和 implements WebMvcConfigurer 會(huì)失效 。
/**
?*?SpringMVC配置類
?*/
@Configuration?//1.標(biāo)識(shí)當(dāng)前是配置類?指定這個(gè)類為配置類,替代application.xml
@ComponentScan("com.zbbmeta")//2.配置掃描web層包?代替<context:component-scan?base-package="com.zbbmeta"?/>
@EnableWebMvc?//如果使用接口的方式,攔截器需要添加這個(gè)注解。不建議使用這種方式,兩種方式只能配置一種,否則會(huì)有沖突
public?class?SpringMvcConfig??implements?WebMvcConfigurer?{
????@Override
????public?void?addInterceptors(InterceptorRegistry?registry)?{
????????//注解攔截器和攔截地址???表示添加?StudentInterceptor??取攔截路徑是?/student/*?所有請(qǐng)求
????????registry.addInterceptor(new?StudentInterceptor()).addPathPatterns("/student/*");
????}
}
2.4 攔截器流程分析
3 攔截器參數(shù)
3.1 前置處理
//原始方法調(diào)用前執(zhí)行的內(nèi)容
//返回值類型可以攔截控制的執(zhí)行,true放行,false終止
@Override
public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{
????System.out.println("=================前置通知=================");
????return?true;
}
-
參數(shù)
-
request:請(qǐng)求對(duì)象
-
response:響應(yīng)對(duì)象
-
handler:被調(diào)用的處理器對(duì)象,本質(zhì)上是一個(gè)方法對(duì)象,對(duì)反射技術(shù)中的Method對(duì)象進(jìn)行了再包裝
-
-
返回值 返回值為false,被攔截的處理器將不執(zhí)行。
3.2 后置處理
//原始方法調(diào)用后執(zhí)行的內(nèi)容
@Override
public?void?postHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?ModelAndView?modelAndView)?throws?Exception?{
????System.out.println("=================后置通知=================");
}
-
參數(shù) modelAndView:如果處理器執(zhí)行完成具有返回結(jié)果,可以讀取到對(duì)應(yīng)數(shù)據(jù)與頁面信息,并進(jìn)行跳轉(zhuǎn)
注意:如果處理器方法出現(xiàn)異常了,該方法不會(huì)執(zhí)行
3.3 完成后處理
//原始方法調(diào)用完成后執(zhí)行的內(nèi)容
@Override
public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?Exception?ex)?throws?Exception?{
????System.out.println("=================最終通知=================");
}
-
參數(shù) ex:如果處理器執(zhí)行過程中出現(xiàn)異常對(duì)象,可以針對(duì)異常情況進(jìn)行單獨(dú)處理
注意:無論處理器方法內(nèi)部是否出現(xiàn)異常,該方法都會(huì)執(zhí)行。
**思考:postHandle()和afterCompletion()方法都是處理器方法執(zhí)行之后執(zhí)行,有什么區(qū)別?
4 攔截器鏈配置
4.1 多個(gè)攔截器配置
-
定義第二個(gè)攔截器
package?com.zbbmeta.Iinterceptor;
import?org.springframework.web.servlet.HandlerInterceptor;
import?org.springframework.web.servlet.ModelAndView;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
public?class?StudentInterceptor2?implements?HandlerInterceptor?{
????//原始方法調(diào)用前執(zhí)行的內(nèi)容
????//返回值類型可以攔截控制的執(zhí)行,true放行,false終止
????@Override
????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{
????????System.out.println("=================Student2前置通知=================");
????????return?true;
????}
????//原始方法調(diào)用后執(zhí)行的內(nèi)容
????@Override
????public?void?postHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?ModelAndView?modelAndView)?throws?Exception?{
????????System.out.println("=================Student2后置通知=================");
????}
????//原始方法調(diào)用完成后執(zhí)行的內(nèi)容
????@Override
????public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?Exception?ex)?throws?Exception?{
????????System.out.println("=================Student2最終通知=================");
????}
}
-
配置加載第二個(gè)攔截器
/**
?*?SpringMVC配置類
?*/
@Configuration?//1.標(biāo)識(shí)當(dāng)前是配置類?指定這個(gè)類為配置類,替代application.xml
@ComponentScan("com.zbbmeta")//2.配置掃描web層包?代替<context:component-scan?base-package="com.zbbmeta"?/>
@EnableWebMvc?//如果使用接口的方式,攔截器需要添加這個(gè)注解。不建議使用這種方式,兩種方式只能配置一種,否則會(huì)有沖突
public?class?SpringMvcConfig??implements?WebMvcConfigurer?{
????@Override
????public?void?addInterceptors(InterceptorRegistry?registry)?{
????????//注解攔截器和攔截地址???表示添加?StudentInterceptor??取攔截路徑是?/student/*?所有請(qǐng)求
????????registry.addInterceptor(new?StudentInterceptor()).addPathPatterns("/student/*");
????????registry.addInterceptor(new?StudentInterceptor2()).addPathPatterns("/student/*");
????}
}
提示:可以使用excludePathPatterns()方法排除某些地址不被攔截
-
執(zhí)行效果
4.2 多個(gè)連接器工作流程分析
-
當(dāng)配置多個(gè)攔截器時(shí),形成攔截器鏈
-
攔截器鏈的運(yùn)行順序參照攔截器添加順序?yàn)闇?zhǔn)
-
當(dāng)攔截器中出現(xiàn)對(duì)原始處理器的攔截,后面的攔截器均終止運(yùn)行文章來源:http://www.zghlxwxcb.cn/news/detail-664019.html
-
當(dāng)攔截器運(yùn)行中斷,僅運(yùn)行配置在前面的攔截器的afterCompletion操作文章來源地址http://www.zghlxwxcb.cn/news/detail-664019.html
到了這里,關(guān)于SpringMVC-2-Spring MVC攔截器詳解:從入門到精通的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!