首頁 > 軟體

SpringMVC攔截器零基礎掌握

2023-08-24 18:00:49

SpringMVC 的攔截器 Interceptor 的主要用來攔截指定的使用者請求,並進行相應的預處理或後處理。它的主要作用是攔截使用者的請求並進行相應的處理。比如通過它來進行許可權驗證,或者是來判斷使用者是否登入等操作。

其攔截的時間點是在處理器介面卡執行處理器之前。建立攔截器類需要實現 HandlerInterceptor 介面,然後在組態檔中註冊並指定攔截目標。

對於 SpringMVC 攔截器的定義方式有兩種:

  • 實現介面: org.springframework.web.servlet.Handlerlnterceptor
  • 繼承介面卡: org.springframework.web.servethandler.HandlerInterceptorAdapter

專案准備

目錄結構:

為了便於下面知識結構的講解,先建立好未使用攔截器的專案,步驟如下:

【1】建立 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】建立 User 實體類,程式碼如下:

package cn.hh.springmvc03.entity;
import lombok.Data;
@Data
public class User {
	String username;
	String password;
}

單個攔截器的執行流程

專案案例:建立第一個攔截器。

實現步驟:

【1】新建處理器 UserController,新增方法如下:

	//測試攔截器
	@RequestMapping("/test1.do")
	public String doTestInterceptor(){
		System.out.println("執行了處理器的方法!");
		return "welcome";
	}

【2】新建包 cn.hh.springmvc03.intercepter,在包下新建一個自定義攔截器類 Intercepter1,實現 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("執行了Intercepter1 ----------afterCompletion");
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception {
		System.out.println("執行了Intercepter1 ----------postHandle");
	}
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		System.out.println("執行了Intercepter1 ----------preHandle");
		return true;
	}
}

自定義攔截器,需要實現HandlerInterceptor介面,實現該介面中的以下三個方法:

  • preHandle(request, response, Object handler): 該方法在處理器方法執行之前執行。其返回值為boolean,若為true,則緊接著會執行處理器方法,且會將afterCompletion()方法放入到一個專門的方法棧中等待執行。若為false則不會執行處理器方法。
  • ØpostHandle(request, response, Object handler, modelAndView): 該方法在處理器方法執行之後執行。處理器方法若最終未被執行,則該方法不會執行。由於該方法是在處理器方法執行完後執行,且該方法引數中包含ModelAndView,所以該方法可以修改處理器方法的處理結果資料,且可以修改跳轉方向。
  • afterCompletion(request, response, Object handler, Exception ex): 當 preHandle()方法返回 true 時,會將該方法放到專門的方法棧中,等到對請求進行響應的所有工作完成之後才執行該方法。

攔截器中方法與處理器方法的執行順序如圖所示。

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

【3】在 spring-config.xml 組態檔中註冊攔截器,程式碼如下:

    <!-- 註冊攔截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="cn.hh.springmvc03.intercepter.Intercepter1"/>
        </mvc:interceptor>
    </mvc:interceptors>

【4】執行測試,則控制檯輸出如下:

執行了Intercepter1 ----------preHandle
執行了處理器的方法!
執行了Intercepter1 ----------postHandle
執行了Intercepter1 ----------afterCompletion

多個攔截器的執行流程

專案案例: 建立多個攔截器。(在上面案例的基礎上編寫以下程式碼)

【1】建立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("執行了Intercepter2----------afterCompletion");		
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception {
		System.out.println("執行了Intercepter2----------postHandle");		
	}
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		System.out.println("執行了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】執行測試,則控制檯輸出如下:

執行了Intercepter1 ----------preHandle
執行了Intercepter2 ----------preHandle
執行了處理器的方法!
執行了Intercepter2 ----------postHandle
執行了Intercepter1 ----------postHandle
執行了Intercepter2 ----------afterCompletion
執行了Intercepter1 ----------afterCompletion

當有多個攔截器時,形成攔截器鏈。攔截器的執行順序與其註冊順序一致。需要再次強調一點的是當某一個攔截器的 preHandle() 方法返回 true 並被執行到時,會向一個專門的方法棧中放入該攔截器的 afterCompletion() 方法。

多個攔截器方法與處理器方法的執行順序如下圖所示:

只要有一個 preHandler() 方法返回 false,則上部的執行鏈將被斷開,其後續的處理器方法與 postHandle() 方法將無法執行。但無論執行鏈執行情況怎樣,只要方法棧中有方法,即執行鏈中只要有 preHandle() 方法返回 true,就會執行方法棧中的 afterCompletion() 方法,最終都會給出響應。

許可權攔截器(案例分享)

專案案例: 只有經過登入的使用者方可存取處理器,否則,將返回“無權存取”提示。 本例的登入,由一個 JSP 頁面完成。即在該頁面裡將使用者資訊放入 session 中。也就是說,只要存取過該頁面,就說明登入了。沒存取過,則為未登入使用者。

實現步驟:

【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啟動就建立該範例物件-->
        <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">
    <!--實現更加強大的功能,支援json資料格式的解析-->
    <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  設定需要掃描的包 -->
    <context:component-scan base-package="cn.kgc.springmvc03"></context:component-scan>
    <!--靜態資源的處理 不需要經過前端控制器  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)){//驗證碼填寫正確
            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{//驗證碼填寫不正確
            map.put("code",500);
            map.put("msg","驗證碼輸入不正確");
        }
        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="請輸入驗證碼" 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>

到此這篇關於SpringMVC攔截器零基礎掌握的文章就介紹到這了,更多相關SpringMVC攔截器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com