成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Boot攔截器詳解

開(kāi)發(fā) 前端
攔截器在不同框架中有不同的實(shí)現(xiàn)方式。比如,在 Spring MVC 中,可以實(shí)現(xiàn) HandlerInterceptor 接口或繼承 HandlerInterceptorAdapter 類。需要實(shí)現(xiàn) preHandle()、postHandle() 和 afterCompletion() 等方法。

攔截器(Interceptor)與過(guò)濾器(Filter)類似,是面向切面編程的一種具體實(shí)現(xiàn)。你可以使用攔截器執(zhí)行某些任務(wù),比如在控制器處理請(qǐng)求前記錄日志、更新配置等。在 Spring 中,當(dāng)請(qǐng)求發(fā)送到控制器時(shí),在被控制器處理之前,它必須經(jīng)過(guò)攔截器。

攔截器與過(guò)濾器的區(qū)別

攔截器(Interceptor)和過(guò)濾器(Filter)的主要區(qū)別在于作用范圍和實(shí)現(xiàn)方式。

作用范圍

  • 過(guò)濾器作用于整個(gè) Web 應(yīng)用程序,可以過(guò)濾所有請(qǐng)求和響應(yīng)。它是 Servlet 規(guī)范的一部分,由 Servlet 容器管理。
  • 攔截器通常作用于特定框架。比如,在 Spring Boot 中,它主要攔截特定框架的請(qǐng)求處理流程,并在特定框架內(nèi)處理請(qǐng)求。

實(shí)現(xiàn)方式

  • 過(guò)濾器實(shí)現(xiàn) javax.servlet.Filter 接口,并在 web.xml 中或通過(guò)注解進(jìn)行配置。需要實(shí)現(xiàn) init()、doFilter() 和 destroy() 等方法。
  • 攔截器在不同框架中有不同的實(shí)現(xiàn)方式。比如,在 Spring MVC 中,可以實(shí)現(xiàn) HandlerInterceptor 接口或繼承 HandlerInterceptorAdapter 類。需要實(shí)現(xiàn) preHandle()、postHandle() 和 afterCompletion() 等方法。

攔截器的作用

  1. 登錄驗(yàn)證和訪問(wèn)控制:攔截器可用于檢查用戶的登錄狀態(tài)和權(quán)限,并根據(jù)需要執(zhí)行相關(guān)處理。比如,可以使用攔截器驗(yàn)證用戶的登錄狀態(tài)。如果未登錄,則重定向到登錄頁(yè)面或返回相應(yīng)的錯(cuò)誤信息。
  2. 異常處理和統(tǒng)一錯(cuò)誤處理:攔截器可以捕獲并處理請(qǐng)求處理過(guò)程中發(fā)生的異常。可以根據(jù)異常類型執(zhí)行適當(dāng)?shù)奶幚恚热绶祷刈远x錯(cuò)誤頁(yè)面或錯(cuò)誤信息,或執(zhí)行特定的錯(cuò)誤處理邏輯。當(dāng)然,它還有許多其他應(yīng)用場(chǎng)景,這里不再一一列舉。

自定義攔截器

如果你需要自定義攔截器,必須實(shí)現(xiàn) org.springframework.web.servlet.HandlerInterceptor 接口或繼承 org.springframework.web.servlet.handler.HandlerInterceptorAdapter 類,并且需要重寫(xiě)以下三個(gè)方法:

  1. **preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)**:此方法在請(qǐng)求處理之前調(diào)用。該方法在攔截器類中首先執(zhí)行,用于一些預(yù)初始化操作或?qū)Ξ?dāng)前請(qǐng)求進(jìn)行預(yù)處理。你還可以進(jìn)行一些判斷,以確定請(qǐng)求是否應(yīng)該繼續(xù)。此方法的返回值為布爾類型。當(dāng)它返回 false 時(shí),表示請(qǐng)求結(jié)束,后續(xù)的攔截器和控制器將不再執(zhí)行。當(dāng)它返回 true 時(shí),將調(diào)用下一個(gè)攔截器的 preHandle 方法。如果已經(jīng)是最后一個(gè)攔截器,則將調(diào)用當(dāng)前請(qǐng)求的控制器方法。
  2. **postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)**:此方法在當(dāng)前請(qǐng)求處理完成后執(zhí)行,即在控制器方法被調(diào)用之后。但是,它將在 DispatcherServlet 渲染視圖之前被調(diào)用。因此,我們可以在此方法中在控制器處理后對(duì) ModelAndView 對(duì)象進(jìn)行操作。
  3. **afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)**:只有當(dāng)相應(yīng)攔截器類的 postHandle 方法的返回值為 true 時(shí),此方法才會(huì)執(zhí)行。顧名思義,此方法將在整個(gè)請(qǐng)求結(jié)束后執(zhí)行,即在 DispatcherServlet 渲染相應(yīng)視圖之后。此方法主要用于資源清理。

接下來(lái),讓我們通過(guò)實(shí)際代碼學(xué)習(xí)。以用戶登錄權(quán)限驗(yàn)證為例:

用戶登錄權(quán)限驗(yàn)證

1.自定義攔截器

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Component
publicclass LoginInterceptor implements HandlerInterceptor {

    // 在調(diào)用目標(biāo)方法之前執(zhí)行的方法。
    // 返回 true 表示攔截器驗(yàn)證成功,執(zhí)行目標(biāo)方法。
    // 返回 false 表示攔截器驗(yàn)證失敗,不執(zhí)行后續(xù)業(yè)務(wù)邏輯。
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 用戶登錄判斷業(yè)務(wù)。
        HttpSession session = request.getSession(false);
        if (session!= null && session.getAttribute("session_userinfo")!= null) {
            // 用戶已登錄。
            returntrue;
        }
        response.setStatus(401);
        returnfalse;
    }
}

代碼中的 preHandle 方法是攔截器的主要方法,在目標(biāo)方法被調(diào)用之前執(zhí)行。它接收三個(gè)參數(shù):HttpServletRequest 對(duì)象表示當(dāng)前 HTTP 請(qǐng)求,HttpServletResponse 對(duì)象表示當(dāng)前 HTTP 響應(yīng),Object handler 表示被攔截的處理器(通常是控制器中的一個(gè)方法)。

在 preHandle 方法中,首先通過(guò) request.getSession(false)(如果存在)獲取當(dāng)前請(qǐng)求的 HttpSession 對(duì)象,然后判斷這個(gè) HttpSession 對(duì)象是否為 null 以及是否存在名為“session_userinfo”的屬性。

如果這個(gè)條件為真,則表示用戶已登錄,可以繼續(xù)執(zhí)行后續(xù)業(yè)務(wù),所以返回 true。否則,驗(yàn)證失敗,將 HTTP 響應(yīng)的狀態(tài)碼設(shè)置為 401,表示未授權(quán),然后返回 false,不再繼續(xù)執(zhí)行后續(xù)業(yè)務(wù)。

2.將自定義攔截器添加到系統(tǒng)配置中

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
publicclass MyConfig implements WebMvcConfigurer {

    // 注入。
    @Autowired
    private LoginInterceptor loginInterceptor;

    // 添加攔截器。
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
              .addPathPatterns("/**") // 攔截所有 URL。
              .excludePathPatterns("/user/login") // 排除 URL:/user/login(登錄)。
              .excludePathPatterns("/user/reg") // 排除 URL:/user/reg(注冊(cè))。
              .excludePathPatterns("/image/**") // 排除“image”文件夾下的所有文件。
              .excludePathPatterns("/**/*.js") // 排除任意深度目錄下的所有“.js”文件。
              .excludePathPatterns("/**/*.css");
    }
}

在配置類中,重寫(xiě) addInterceptors 方法。此方法用于注冊(cè)攔截器。在這里,通過(guò)調(diào)用 InterceptorRegistry 的 addInterceptor 方法添加攔截器,并設(shè)置攔截路徑和排除路徑。

具體來(lái)說(shuō),通過(guò)調(diào)用 addInterceptor(loginInterceptor) 添加 LoginInterceptor 攔截器。然后使用 addPathPatterns 方法指定需要攔截的 URL 路徑模式。這里,“/**”用于表示攔截所有 URL。使用 excludePathPatterns 方法排除一些不會(huì)被攔截的特定 URL 路徑。

3.用戶控制器

@RestController
@RequestMapping("/user")
publicclass UserController {

    @RequestMapping("/login")
    public String login() {
        return"login";
    }

    @RequestMapping("/index")
    public String index() {
        return"index";
    }

    @RequestMapping("/reg")
    public String reg() {
        return"reg";
    }
}

使用瀏覽器訪問(wèn)路徑/user/login 的結(jié)果輸出如下:圖片

然后,使用瀏覽器訪問(wèn)路徑/user/index 的結(jié)果輸出如下:

圖片可以看到,返回了 401 錯(cuò)誤,這是預(yù)期的結(jié)果。

然后,使用瀏覽器訪問(wèn)路徑/user/reg 的結(jié)果輸出如下:

圖片

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

在 WebMvcConfigurer 接口中,configurePathMatch 方法用于配置路徑匹配規(guī)則。這里我們給所有請(qǐng)求地址添加前綴“pre”。

@Configuration
public class MyConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("pre", new Predicate<Class<?>>() {
            @Override
            public boolean test(Class<?> aClass) {
                return true;
            }
        });
    }
}

在這個(gè)例子中,傳遞給 addPathPrefix 方法的前綴是“pre”,Predicate 對(duì)象是一個(gè)實(shí)現(xiàn)了 Predicate<Class<?>>接口的匿名內(nèi)部類。Predicate 接口是 Java 8 中引入的一個(gè)函數(shù)式接口,其 test 方法用于判斷傳入的類是否滿足條件。

在這個(gè)匿名內(nèi)部類中,重寫(xiě) test 方法使其始終返回 true,這意味著所有類都滿足條件,并且將添加統(tǒng)一的訪問(wèn)前綴。

因此,通過(guò)這段代碼的配置,所有請(qǐng)求路徑都將在前面添加“pre”前綴。比如,如果原始路徑是“example”,添加前綴后的路徑變?yōu)椤?pre/example”。這樣可以實(shí)現(xiàn)對(duì)請(qǐng)求路徑的統(tǒng)一處理。

注意:如果添加了前綴,攔截器的排除路徑也應(yīng)該相應(yīng)更改。

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(loginInterceptor)
          .excludePathPatterns("/pre/user/login") // 排除 URL:/user/login(登錄)。
          .excludePathPatterns("/pre/user/reg") // 排除 URL:/user/reg(注冊(cè))。
          .addPathPatterns("/**") // 攔截所有 URL。
          .excludePathPatterns("/pre/image/**") // 排除“image”文件夾下的所有文件。
          .excludePathPatterns("/pre/**/*.js") // 排除任意深度目錄下的所有“.js”文件。
          .excludePathPatterns("/pre/**/*.css");
}

配置本地資源映射路徑

實(shí)現(xiàn) WebMvcConfigurer 接口并重寫(xiě) addResourceHandlers(ResourceHandlerRegistry registry) 方法,其中:

  • addResourceHandler() 添加訪問(wèn)路徑;
  • addResourceLocations() 添加映射的真實(shí)路徑。映射的真實(shí)路徑末尾必須跟“/”,否則無(wú)法映射。“/”在 Windows 和 Linux 中都適用。

示例代碼:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
publicclass MyWebMVCConfig implements WebMvcConfigurer {

    @Value("${file.location}") // D:/test/
    private String fileLocation;

    @Value("${file.path}") // /file/**
    private String filePath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 當(dāng)資源處理器匹配時(shí),將 URL 映射到位置,即本地文件夾。
        registry.addResourceHandler(filePath).addResourceLocations("file:///" + fileLocation); // 這里的最后一個(gè)“/”不能省略。
    }
}

這段代碼將配置一個(gè)攔截器。如果訪問(wèn)路徑是 addResourceHandler 中的路徑,那么它將被映射到 addResourceLocations 參數(shù)中的路徑。這樣,其他人就可以訪問(wèn)服務(wù)器上的本地文件,如本地圖片或本地音樂(lè)視頻。

統(tǒng)一異常處理

猜猜訪問(wèn)以下代碼后會(huì)返回什么?

@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/login")
    public String login() {
        Object object = null;
        object.hashCode();
        return "login";
    }
}

答案是:

圖片有沒(méi)有一種方法可以在發(fā)生異常時(shí)返回有用信息,而不是這樣混亂的錯(cuò)誤消息?這就是統(tǒng)一異常處理。

@ControllerAdvice
@ResponseBody
public class MyExceptionAdvice {
    @ExceptionHandler(NullPointerException.class)
    public HashMap<String, Object> handleNPE(NullPointerException e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", 1001);
        result.put("msg", "npe:" + e.getMessage());
        result.put("data", null);
        return result;
    }
}
  1. @ControllerAdvice 注解表示這個(gè)類是一個(gè)全局異常處理器。它將捕獲應(yīng)用程序中拋出的異常并執(zhí)行相應(yīng)的處理邏輯。
  2. @ExceptionHandler(NullPointerException.class) 注解指定處理 NullPointerException 類型異常的方法 handleNPE()。
  3. handleNPE() 方法的參數(shù)是一個(gè) NullPointerException 類型的異常對(duì)象,表示具體捕獲的異常實(shí)例。
  4. handleNPE() 方法返回一個(gè) HashMap<String, Object>對(duì)象,用于封裝異常處理結(jié)果。

這段代碼的作用是,當(dāng)捕獲到 NullPointerException 異常時(shí),執(zhí)行 handleNPE() 方法并返回一個(gè)包含異常處理結(jié)果的 HashMap 對(duì)象。這個(gè)結(jié)果將以 JSON 格式返回給客戶端。

訪問(wèn) localhost:8080/user/login 的結(jié)果如下:

圖片

當(dāng)有多個(gè)異常處理器時(shí),處理順序如下: 異常處理器按照它們?cè)诖a中定義的順序執(zhí)行。如果一個(gè)異常匹配多個(gè)異常處理器,將首先執(zhí)行與異常類型更具體匹配的那個(gè)。如果沒(méi)有具體匹配,則可能考慮更通用的異常處理器。

比如,如果有一個(gè)針對(duì)異常的特定子類的異常處理器和另一個(gè)針對(duì)更通用的超類異常的異常處理器,將優(yōu)先執(zhí)行針對(duì)特定子類的處理器。

@ControllerAdvice
@ResponseBody
publicclass MyExceptionAdvice {

    @ExceptionHandler(NullPointerException.class)
    public HashMap<String, Object> handleNPE(NullPointerException e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", -1);
        result.put("msg", "npe:" + e.getMessage());
        result.put("data", null);
        return result;
    }

    @ExceptionHandler(Exception.class)
    public HashMap<String, Object> handleAllException(Exception e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", -1);
        result.put("msg", "Exception:" + e.getMessage());
        result.put("data", null);
        return result;
    }
}

再次嘗試訪問(wèn)/user/login。圖片

結(jié)論是:如果有匹配,子類優(yōu)先。如果沒(méi)有匹配,查找父類。

責(zé)任編輯:武曉燕 來(lái)源: 程序猿技術(shù)充電站
相關(guān)推薦

2011-11-21 14:21:26

SpringMVCJava框架

2012-02-03 13:27:16

2009-06-24 16:00:00

2009-09-27 17:37:32

Hibernate攔截

2025-05-12 04:00:00

2023-09-05 08:58:07

2011-05-16 10:14:11

Hibernate

2025-05-09 08:20:50

2009-07-08 17:02:11

JDK實(shí)現(xiàn)調(diào)用攔截器

2020-03-25 17:55:30

SpringBoot攔截器Java

2009-06-25 15:54:42

Struts2教程攔截器

2009-02-04 14:19:38

2013-11-04 09:35:38

Firefox插件攔截FLASH

2017-04-26 11:00:34

Spring BootHelloWorld詳解

2024-12-16 08:10:00

Spring開(kāi)發(fā)

2009-06-19 18:26:38

Spring事務(wù)配置

2024-01-08 08:33:53

AOPSpring攔截器

2023-11-30 07:00:56

SpringBoot處理器

2024-12-27 08:39:10

2021-11-03 17:04:11

攔截器操作Servlet
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久看看 | 天天干天天操天天射 | 精品国产乱码久久久久久丨区2区 | 亚洲欧美日韩精品久久亚洲区 | 国产午夜精品一区二区三区在线观看 | 狠狠狠 | 精品国产乱码久久久久久闺蜜 | 国产精品s色| 国产欧美日韩一区 | 精品福利视频一区二区三区 | 久久国产精品亚洲 | 一级全黄少妇性色生活免费看 | 狠狠干2020 | 做a视频在线观看 | 亚洲国产精品一区二区久久 | 爱爱无遮挡 | 蜜桃一区二区三区 | 国产精品久久久久aaaa九色 | 色偷偷888欧美精品久久久 | 中文字幕高清 | 国产一区二区视频免费在线观看 | 久久久久久免费毛片精品 | 日韩欧美精品在线 | 久久首页 | 亚洲乱码一区二区三区在线观看 | 国产成人精品久久二区二区 | 久草综合在线 | 激情五月婷婷 | 国产精品视频一区二区三区四蜜臂 | 免费在线日韩 | 色视频欧美 | 久久99精品久久久久久国产越南 | aaaa日韩 | 亚洲欧美日韩高清 | 大学生a级毛片免费视频 | 国产一区| 鲁大师一区影视 | 2021狠狠天天天 | 亚洲成人精品国产 | 色婷婷av99xx| 久久久久久国产精品免费免费狐狸 |