SpringMVC攔截器零基礎(chǔ)掌握

SpringMVC 的攔截器 Interceptor 的主要用來攔截指定的用戶請求,并進(jìn)行相應(yīng)的預(yù)處理或后處理。它的主要作用是攔截用戶的請求并進(jìn)行相應(yīng)的處理。比如通過它來進(jìn)行權(quán)限驗(yàn)證,或者是來判斷用戶是否登錄等操作。
其攔截的時間點(diǎn)是在處理器適配器執(zhí)行處理器之前。創(chuàng)建攔截器類需要實(shí)現(xiàn) HandlerInterceptor 接口,然后在配置文件中注冊并指定攔截目標(biāo)。
對于 SpringMVC 攔截器的定義方式有兩種:
- 實(shí)現(xiàn)接口: org.springframework.web.servlet.Handlerlnterceptor
- 繼承適配器: org.springframework.web.servethandler.HandlerInterceptorAdapter
項(xiàng)目準(zhǔn)備
目錄結(jié)構(gòu):

為了便于下面知識結(jié)構(gòu)的講解,先創(chuàng)建好未使用攔截器的項(xiàng)目,步驟如下:
【1】創(chuàng)建 spring-config.xml 文件,代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--邏輯視圖前綴-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--邏輯視圖后綴,匹配模式:前綴+邏輯視圖+后綴,形成完整路徑名-->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置組件掃描器 -->
<context:component-scan base-package="cn.hh.springmvc03"/>
</beans>【2】創(chuàng)建 User 實(shí)體類,代碼如下:
package cn.hh.springmvc03.entity;
import lombok.Data;
@Data
public class User {
String username;
String password;
}
單個攔截器的執(zhí)行流程
項(xiàng)目案例:創(chuàng)建第一個攔截器。
實(shí)現(xiàn)步驟:
【1】新建處理器 UserController,添加方法如下:
//測試攔截器
@RequestMapping("/test1.do")
public String doTestInterceptor(){
System.out.println("執(zhí)行了處理器的方法!");
return "welcome";
}
【2】新建包 cn.hh.springmvc03.intercepter,在包下新建一個自定義攔截器類 Intercepter1,實(shí)現(xiàn) HandlerInterceptor 接口,重寫以下3個方法,代碼如下:
package cn.hh.springmvc03.intercepter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class Intercepter1 implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3)
throws Exception {
System.out.println("執(zhí)行了Intercepter1 ----------afterCompletion");
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
System.out.println("執(zhí)行了Intercepter1 ----------postHandle");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("執(zhí)行了Intercepter1 ----------preHandle");
return true;
}
}
自定義攔截器,需要實(shí)現(xiàn)HandlerInterceptor接口,實(shí)現(xiàn)該接口中的以下三個方法:
- preHandle(request, response, Object handler): 該方法在處理器方法執(zhí)行之前執(zhí)行。其返回值為boolean,若為true,則緊接著會執(zhí)行處理器方法,且會將afterCompletion()方法放入到一個專門的方法棧中等待執(zhí)行。若為false則不會執(zhí)行處理器方法。
- ØpostHandle(request, response, Object handler, modelAndView): 該方法在處理器方法執(zhí)行之后執(zhí)行。處理器方法若最終未被執(zhí)行,則該方法不會執(zhí)行。由于該方法是在處理器方法執(zhí)行完后執(zhí)行,且該方法參數(shù)中包含ModelAndView,所以該方法可以修改處理器方法的處理結(jié)果數(shù)據(jù),且可以修改跳轉(zhuǎn)方向。
- afterCompletion(request, response, Object handler, Exception ex): 當(dāng) preHandle()方法返回 true 時,會將該方法放到專門的方法棧中,等到對請求進(jìn)行響應(yīng)的所有工作完成之后才執(zhí)行該方法。
攔截器中方法與處理器方法的執(zhí)行順序如圖所示。

也可以這樣來看 ,如下圖:

【3】在 spring-config.xml 配置文件中注冊攔截器,代碼如下:
<!-- 注冊攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.hh.springmvc03.intercepter.Intercepter1"/>
</mvc:interceptor>
</mvc:interceptors>
【4】運(yùn)行測試,則控制臺輸出如下:
執(zhí)行了Intercepter1 ----------preHandle
執(zhí)行了處理器的方法!
執(zhí)行了Intercepter1 ----------postHandle
執(zhí)行了Intercepter1 ----------afterCompletion
多個攔截器的執(zhí)行流程
項(xiàng)目案例: 創(chuàng)建多個攔截器。(在上面案例的基礎(chǔ)上編寫以下代碼)
【1】創(chuàng)建Intercepter2,代碼如下所示:
package cn.hh.springmvc03.intercepter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class Intercepter2 implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3)
throws Exception {
System.out.println("執(zhí)行了Intercepter2----------afterCompletion");
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
System.out.println("執(zhí)行了Intercepter2----------postHandle");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("執(zhí)行了Intercepter2----------preHandle");
return true;
}
}
【2】在 spring-config.xml 文件中注冊多個攔截器,代碼如下:
<!-- 注冊多個攔截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.lifeng.intercepter.Intercepter1"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.lifeng.intercepter.Intercepter2"/> </mvc:interceptor> </mvc:interceptors>
【3】運(yùn)行測試,則控制臺輸出如下:
執(zhí)行了Intercepter1 ----------preHandle
執(zhí)行了Intercepter2 ----------preHandle
執(zhí)行了處理器的方法!
執(zhí)行了Intercepter2 ----------postHandle
執(zhí)行了Intercepter1 ----------postHandle
執(zhí)行了Intercepter2 ----------afterCompletion
執(zhí)行了Intercepter1 ----------afterCompletion
當(dāng)有多個攔截器時,形成攔截器鏈。攔截器的執(zhí)行順序與其注冊順序一致。需要再次強(qiáng)調(diào)一點(diǎn)的是當(dāng)某一個攔截器的 preHandle() 方法返回 true 并被執(zhí)行到時,會向一個專門的方法棧中放入該攔截器的 afterCompletion() 方法。
多個攔截器方法與處理器方法的執(zhí)行順序如下圖所示:

只要有一個 preHandler() 方法返回 false,則上部的執(zhí)行鏈將被斷開,其后續(xù)的處理器方法與 postHandle() 方法將無法執(zhí)行。但無論執(zhí)行鏈執(zhí)行情況怎樣,只要方法棧中有方法,即執(zhí)行鏈中只要有 preHandle() 方法返回 true,就會執(zhí)行方法棧中的 afterCompletion() 方法,最終都會給出響應(yīng)。
權(quán)限攔截器(案例分享)
項(xiàng)目案例: 只有經(jīng)過登錄的用戶方可訪問處理器,否則,將返回“無權(quán)訪問”提示。 本例的登錄,由一個 JSP 頁面完成。即在該頁面里將用戶信息放入 session 中。也就是說,只要訪問過該頁面,就說明登錄了。沒訪問過,則為未登錄用戶。
實(shí)現(xiàn)步驟:
【1】web.xml 代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!--配置前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config.xml</param-value>
</init-param>
<!--tomcat啟動就創(chuàng)建該實(shí)例對象-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
【2】spring-config.xml 配置文件代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--實(shí)現(xiàn)更加強(qiáng)大的功能,支持json數(shù)據(jù)格式的解析-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--第5步:配置視圖解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前綴配置-->
<property name="prefix" value="/"></property>
<!--后綴配置-->
<property name="suffix" value=".jsp"></property>
</bean>
<!--第6步:開啟包掃描 base-package 設(shè)置需要掃描的包 -->
<context:component-scan base-package="cn.kgc.springmvc03"></context:component-scan>
<!--靜態(tài)資源的處理 不需要經(jīng)過前端控制器 tomcat-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--配置攔截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/user/login"/>
<mvc:exclude-mapping path="/user/getcode"/>
<bean class="cn.kgc.springmvc03.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!--配置文件上傳組件-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
</beans>【3】UserController 類中添加登陸方法,代碼如下:
//登陸
@RequestMapping("login")
@ResponseBody
public Map<String,Object> login(User user, HttpSession session,@SessionAttribute("code") String attribute){
HashMap<String, Object> map = new HashMap<>();
System.out.println("--------login方法-------"+attribute);
if(user.getCode().equals(attribute)){//驗(yàn)證碼填寫正確
if("tom".equals(user.getUsername())&&"123456".equals(user.getPassword())){//賬號密碼正確
session.setAttribute("user",user);
map.put("code",200);
map.put("msg","登陸成功");
}else{//賬號密碼不正確
map.put("code",500);
map.put("msg","登陸失敗");
}
}else{//驗(yàn)證碼填寫不正確
map.put("code",500);
map.put("msg","驗(yàn)證碼輸入不正確");
}
return map;
}
【4】添加攔截器 LoginInterceptor 代碼如下:
package cn.kgc.springmvc03.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("-------------preHandle方法--------------");
HttpSession session = request.getSession();
Object user = session.getAttribute("user");
if(user==null){
response.sendRedirect("/login.jsp");
return false;
}
return true;
}
}【5】添加前端頁面 login.jsp 代碼如下:
<%--
Created by IntelliJ IDEA.
Time: 9:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="jquery-1.11.1.js"></script>
<script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<form>
<p><input type="text" name="username" placeholder="請輸入用戶名" id="username"></p>
<p><input type="password" name="password" placeholder="請輸入密碼" id="password"></p>
<p><input type="text" name="code" placeholder="請輸入驗(yàn)證碼" id="code"></p>
<p><input type="button" value="登錄" id="login"></p>
</form>
<span id="msg" style="color: red"></span>
</body>
<script>
$("#login").click(function () {
let username=$("#username").val()
let password = $("#password").val()
let code = $("#code").val()
$.get("/user/login",{username,password,code},function (res) {
if(res.code=200){
window.location.href="/main.jsp" rel="external nofollow"
}else{
let info = res.msg
$("#msg").text(info)
}
})
});
</script>
</html>
到此這篇關(guān)于SpringMVC攔截器零基礎(chǔ)掌握的文章就介紹到這了,更多相關(guān)SpringMVC攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA Spring Boot 自動配置實(shí)現(xiàn)原理詳解
這篇文章主要介紹了詳解SpringBoot自動配置原理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2021-09-09
SpringMVC結(jié)構(gòu)簡介及常用注解匯總
這篇文章主要介紹了SpringMVC結(jié)構(gòu)簡介及常用注解匯總,幫助大家更好的理解和學(xué)習(xí)使用SpringMVC,感興趣的朋友可以了解下2021-03-03

