最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Boot?攔截器幫助解鎖5種常用場(chǎng)景(推薦)

 更新時(shí)間:2026年01月16日 09:22:34   作者:奮斗的狍子007  
在SpringBoot中,攔截器用于在請(qǐng)求處理前后插入自定義邏輯,實(shí)現(xiàn)權(quán)限校驗(yàn)、日志記錄、性能監(jiān)控等功能,本文給大家介紹Spring?Boot?攔截器幫助解鎖5大實(shí)用場(chǎng)景,感興趣的朋友跟隨小編一起看看吧

一、Spring Boot中攔截器是什么

 在Spring Boot中,攔截器(Interceptor)是一種基于A(yíng)OP(面向切面編程)思想的組件,用于在請(qǐng)求處理前后插入自定義邏輯,實(shí)現(xiàn)權(quán)限校驗(yàn)、日志記錄、性能監(jiān)控等非業(yè)務(wù)功能。

  其核心作用是在不修改業(yè)務(wù)代碼的前提下,對(duì)請(qǐng)求進(jìn)行統(tǒng)一處理,類(lèi)似于Servlet中的Filter,但更貼近Spring MVC的體系。

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

三、攔截器主要方法

在實(shí)現(xiàn)攔截器時(shí),HandlerInterceptor接口提供了三個(gè)主要方法,它們?cè)谡?qǐng)求處理的不同階段發(fā)揮著重要作用。

preHandle
  這個(gè)方法在請(qǐng)求進(jìn)入Controller之前被調(diào)用 。它的返回值是一個(gè)布爾類(lèi)型,如果返回true,請(qǐng)求將繼續(xù)被處理,進(jìn)入Controller。
   如果返回false,請(qǐng)求將被攔截,后續(xù)的Controller方法將不會(huì)被執(zhí)行。在這個(gè)方法中,我們通??梢赃M(jìn)行一些前置的處理操作,比如用戶(hù)認(rèn)證、權(quán)限校驗(yàn)、日志記錄等。?

postHandle
  當(dāng)Controller方法執(zhí)行完畢后,視圖渲染之前,這個(gè)方法會(huì)被調(diào)用 。

  在這個(gè)方法中,我們可以對(duì)ModelAndView進(jìn)行一些操作,比如添加額外的模型數(shù)據(jù),修改視圖名稱(chēng)等。需要注意的是,如果在preHandle方法中返回了false,這個(gè)方法將不會(huì)被執(zhí)行。?

afterCompletion
  在整個(gè)請(qǐng)求處理完成,包括視圖渲染之后,這個(gè)方法會(huì)被調(diào)用。無(wú)論請(qǐng)求處理過(guò)程中是否發(fā)生異常,只要preHandle方法返回true,這個(gè)方法就會(huì)被執(zhí)行。

  我們可以在這個(gè)方法中進(jìn)行一些資源清理、記錄日志等收尾工作。如果請(qǐng)求處理過(guò)程中發(fā)生了異常,異常信息會(huì)通過(guò) ex 參數(shù)傳遞進(jìn)來(lái),我們可以根據(jù)這個(gè)參數(shù)進(jìn)行相應(yīng)的異常處理。

@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在請(qǐng)求處理之前執(zhí)行的邏輯
        System.out.println("preHandle被調(diào)用,請(qǐng)求即將進(jìn)入Controller");
        return true; // 返回true表示放行請(qǐng)求,返回false則攔截請(qǐng)求
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在請(qǐng)求處理之后,視圖渲染之前執(zhí)行的邏輯
        System.out.println("postHandle被調(diào)用,Controller方法已執(zhí)行完畢,視圖即將渲染");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在整個(gè)請(qǐng)求處理完成,包括視圖渲染之后執(zhí)行的邏輯
        System.out.println("afterCompletion被調(diào)用,整個(gè)請(qǐng)求已處理完畢");
    }
}
@Configuration
public class WebMvcConfig1 implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
               .addPathPatterns("/**") // 攔截所有請(qǐng)求
                .excludePathPatterns("/static/**"); // 排除/static目錄下的靜態(tài)資源請(qǐng)求
    }
}

四、5 種常見(jiàn)的攔截器使用場(chǎng)景

1.用戶(hù)認(rèn)證攔截器

  用戶(hù)認(rèn)證攔截器的作用就是在用戶(hù)請(qǐng)求進(jìn)入 Controller 之前,驗(yàn)證用戶(hù)的登錄狀態(tài)。如果用戶(hù)已經(jīng)登錄,允許請(qǐng)求繼續(xù)處理。如果用戶(hù)未登錄,則返回錯(cuò)誤信息或者重定向到登錄頁(yè)面。

@Component
public class JwtHandlerInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtTokenProvider jwtTokenProvider;
    @Autowired
    private UserInfoService userInfoService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 取出token
        String token = request.getHeader("token");
        if (!jwtTokenProvider.validateToken(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("{\"error\": \"Token已失效,請(qǐng)重新登錄\"}");
            return false;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 判斷方法上是否有NoAuth注解,如果有則跳過(guò)認(rèn)證
        if (method.isAnnotationPresent(NoAuth.class)) {
            return true;
        }
        String username = jwtTokenProvider.getUsernameFromJWT(token);
        User user = userInfoService.getUserInfoByUserName(username);
        if (user == null) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("{\"error\": \"用戶(hù)不存在\"}");
            return false;
        }
        // 判斷角色權(quán)限
        HasRoles hasRoles = handlerMethod.getMethodAnnotation(HasRoles.class);
        if (!Objects.isNull(hasRoles)) {
            // 檢查用戶(hù)是否有所需角色
            String[] roles = hasRoles.value();
            boolean hasRole = false;
            // 角色校驗(yàn) ...
            if (!hasRole) {
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                response.getWriter().write("{\"error\": \"權(quán)限不足\"}");
                return false;
            }
        }
        // 將用戶(hù)信息放入請(qǐng)求屬性
        request.setAttribute("currentUser", user);
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

  在WebMvcConfig配置類(lèi)中,將JwtHandlerInterceptor注冊(cè)到Spring的攔截器鏈中,并設(shè)置攔截路徑為所有請(qǐng)求,排除了登錄和注冊(cè)接口,因?yàn)檫@兩個(gè)接口不需要用戶(hù)登錄就可以訪(fǎng)問(wèn)。

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JwtHandlerInterceptor())
                .addPathPatterns("/**")// 攔截所有請(qǐng)求
                .excludePathPatterns("/login","/register");// 排除登錄和注冊(cè)接口
    }
}

  通過(guò)這樣的配置,就可以實(shí)現(xiàn)對(duì)用戶(hù)登錄狀態(tài)的驗(yàn)證,確保只有登錄用戶(hù)才能訪(fǎng)問(wèn)受保護(hù)的資源。

2.日志記錄攔截器

  日志記錄對(duì)于系統(tǒng)的運(yùn)維和故障排查非常重要。日志記錄攔截器可以在請(qǐng)求處理的前后記錄請(qǐng)求的相關(guān)信息,比如請(qǐng)求的 URL、請(qǐng)求方法、請(qǐng)求參數(shù)、客戶(hù)端 IP 等。這些日志信息可以幫助我們了解系統(tǒng)的運(yùn)行情況,分析用戶(hù)行為,在出現(xiàn)問(wèn)題時(shí)快速定位問(wèn)題。

@Component
public class RequestLoggingInterceptor implements HandlerInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(RequestLoggingInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("Request URL: {}, Method: {}, IP: {}", request.getRequestURI(), request.getMethod(), request.getRemoteAddr());
        // 記錄請(qǐng)求參數(shù)
        Map<String, String[]> paramMap = request.getParameterMap();
        StringBuilder params = new StringBuilder();
        if (!paramMap.isEmpty()) {
            for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
                params.append(entry.getKey())
                        .append("=")
                        .append(String.join(",", entry.getValue()))
                        .append("&");
            }
            if (params.length() > 0) {
                params.deleteCharAt(params.length() - 1);
            }
        }
        // 記錄請(qǐng)求體(僅POST/PUT/PATCH請(qǐng)求)
        String method = request.getMethod();
        String requestBody = "";
        if (HttpMethod.POST.matches(method) ||
                HttpMethod.PUT.matches(method) ||
                HttpMethod.PATCH.matches(method)) {
            // 使用包裝請(qǐng)求對(duì)象來(lái)多次讀取請(qǐng)求體
            ContentCachingRequestWrapper wrappedRequest =
                    new ContentCachingRequestWrapper(request);
            // 為了觸發(fā)內(nèi)容緩存,我們需要獲取一次輸入流
            if (wrappedRequest.getContentLength() > 0) {
                wrappedRequest.getInputStream().read();
                requestBody = new String(wrappedRequest.getContentAsByteArray(),
                        wrappedRequest.getCharacterEncoding());
            }
        }
        logger.info("Request URL: {}, Method: {}, IP: {},params: {},requestBody: {}", request.getRequestURI(), request.getMethod(), request.getRemoteAddr(), params, requestBody);
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("Request to {} has been completed", request.getRequestURI());
        if (ex != null) {
            logger.error("An exception occurred during request handling", ex);
        }
    }
}

3.性能監(jiān)控?cái)r截器

  性能監(jiān)控對(duì)于優(yōu)化系統(tǒng)性能至關(guān)重要。性能監(jiān)控?cái)r截器可以用來(lái)計(jì)算和記錄請(qǐng)求的處理時(shí)間,通過(guò)分析這些時(shí)間數(shù)據(jù),我們可以找出系統(tǒng)中的性能瓶頸,進(jìn)而進(jìn)行針對(duì)性的優(yōu)化。

@Component
public class PerformanceInterceptor implements HandlerInterceptor {
    private static final ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long startTime = System.currentTimeMillis();
        startTimeThreadLocal.set(startTime);
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 計(jì)算請(qǐng)求處理時(shí)間
        long endTime = System.currentTimeMillis();
        long startTime = startTimeThreadLocal.get();
        long executeTime = endTime - startTime;
        System.out.println("Request URL: " + request.getRequestURL() + ", Execution Time: " + executeTime + "ms");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        startTimeThreadLocal.remove();
    }
}

4.接口限流攔截器

  在高并發(fā)場(chǎng)景下,接口限流是保護(hù)系統(tǒng)的重要手段 。接口限流攔截器可以限制單位時(shí)間內(nèi)對(duì)某個(gè)接口的訪(fǎng)問(wèn)次數(shù),防止因大量請(qǐng)求導(dǎo)致系統(tǒng)資源耗盡,從而保證系統(tǒng)的穩(wěn)定性和可用性 。

@Component
public class AccessLimitInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, Integer> redisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
        if (accessLimit == null) {
            return true;
        }
        int seconds = accessLimit.seconds();
        int maxCount = accessLimit.maxCount();
        boolean needLogin = accessLimit.needLogin();
        if (needLogin) {
            // 檢查用戶(hù)登錄狀態(tài),這里省略具體實(shí)現(xiàn)
            // 如果未登錄,返回錯(cuò)誤信息
            return false;
        }
        String key = request.getRemoteAddr() + request.getRequestURI();
        Integer count = redisTemplate.opsForValue().get(key);
        if (count == null) {
            redisTemplate.opsForValue().set(key, 1, seconds, TimeUnit.SECONDS);
        } else if (count < maxCount) {
            redisTemplate.opsForValue().increment(key, 1);
        } else {
            render(response, "請(qǐng)求過(guò)于頻繁,請(qǐng)稍后再試");
            return false;
        }
        return true;
    }
    private void render(HttpServletResponse response, String msg) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write(msg);
        out.flush();
        out.close();
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

5.數(shù)據(jù)加密解密攔截器

  在數(shù)據(jù)傳輸和存儲(chǔ)過(guò)程中,保護(hù)敏感數(shù)據(jù)的安全至關(guān)重要。數(shù)據(jù)加密解密攔截器可以在請(qǐng)求到達(dá)Controller之前對(duì)敏感數(shù)據(jù)進(jìn)行加密,在響應(yīng)返回給客戶(hù)端之前對(duì)加密數(shù)據(jù)進(jìn)行解密,確保數(shù)據(jù)在傳輸和處理過(guò)程中的安全性。

  比如在用戶(hù)登錄時(shí),對(duì)用戶(hù)輸入的密碼進(jìn)行加密后再傳輸?shù)椒?wù)器。在從數(shù)據(jù)庫(kù)中查詢(xún)用戶(hù)的身份證號(hào)、手機(jī)號(hào)等敏感信息時(shí),對(duì)查詢(xún)結(jié)果進(jìn)行解密后再返回給前端。

@Component
public class EncryptionInterceptor implements HandlerInterceptor {
    /**
     * 密鑰
     */
    private static final String KEY = "secret_key";
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 假設(shè)請(qǐng)求參數(shù)中有一個(gè)名為"sensitiveData"的敏感數(shù)據(jù)需要加密
        String sensitiveData = request.getParameter("sensitiveData");
        if (sensitiveData != null) {
            SecretKey secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
            byte[] encryptedData = AESUtil.encrypt(sensitiveData, secretKey);
            String encryptedDataStr = Base64.getEncoder().encodeToString(encryptedData);
            // 將加密后的數(shù)據(jù)重新放回請(qǐng)求參數(shù)中
            request.setAttribute("sensitiveData", encryptedDataStr);
        }
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 假設(shè)響應(yīng)中有一個(gè)名為"sensitiveResponseData"的敏感數(shù)據(jù)需要解密
        String sensitiveResponseData = (String) request.getAttribute("sensitiveResponseData");
        if (sensitiveResponseData != null) {
            SecretKey secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
            byte[] decodedData = Base64.getDecoder().decode(sensitiveResponseData);
            String decryptedData = AESUtil.decrypt(decodedData, secretKey);
            // 將解密后的數(shù)據(jù)重新放回請(qǐng)求屬性中,方便后續(xù)處理
            request.setAttribute("sensitiveResponseData", decryptedData);
        }
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
}

五、總結(jié)

在 Spring Boot 開(kāi)發(fā)中,攔截器就像是一把 “萬(wàn)能鑰匙”,為我們提供了豐富的功能擴(kuò)展和業(yè)務(wù)處理的可能性。

  希望大家在實(shí)際項(xiàng)目中,能夠根據(jù)業(yè)務(wù)需求,靈活地運(yùn)用這些攔截器,讓我們的 Spring Boot 應(yīng)用更加健壯、高效、安全。

  同時(shí),攔截器還有很多值得深入探討的地方,比如如何在攔截器中優(yōu)雅地處理事務(wù)、如何實(shí)現(xiàn)更加復(fù)雜的動(dòng)態(tài)攔截規(guī)則等 ,后續(xù)我們可以一起繼續(xù)探索。

  如果大家在使用攔截器的過(guò)程中有任何問(wèn)題或心得,歡迎在留言區(qū)分享交流。

到此這篇關(guān)于Spring Boot 攔截器幫助解鎖5大實(shí)用場(chǎng)景(推薦)的文章就介紹到這了,更多相關(guān)springboot攔截器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Security入門(mén)demo案例

    Spring Security入門(mén)demo案例

    Spring Security是一個(gè)高度自定義的安全框架,本文主要介紹了Spring Security入門(mén),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 如何獲取jar包resources文件路徑

    如何獲取jar包resources文件路徑

    java項(xiàng)目發(fā)布到j(luò)ar之后找不到文件路徑,遇到這樣問(wèn)題如何處理呢,下面小編給大家分享獲取jar包resources文件路徑的解決方法,感興趣的朋友一起看看吧
    2023-12-12
  • Java聊天室之實(shí)現(xiàn)獲取Socket功能

    Java聊天室之實(shí)現(xiàn)獲取Socket功能

    這篇文章主要為大家詳細(xì)介紹了Java簡(jiǎn)易聊天室之實(shí)現(xiàn)獲取遠(yuǎn)程服務(wù)器和客戶(hù)機(jī)的IP地址和端口號(hào)功能,文中的示例代碼講解詳細(xì),需要的可以了解一下
    2022-10-10
  • Component-Scan 不掃描jar里面的類(lèi)問(wèn)題

    Component-Scan 不掃描jar里面的類(lèi)問(wèn)題

    這篇文章主要介紹了Component-Scan 不掃描jar里面的類(lèi)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java中volatile關(guān)鍵字的作用與用法詳解

    Java中volatile關(guān)鍵字的作用與用法詳解

    volatile關(guān)鍵字雖然從字面上理解起來(lái)比較簡(jiǎn)單,但是要用好不是一件容易的事情。這篇文章主要介紹了Java中volatile關(guān)鍵字的作用與用法詳解的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • Java反射機(jī)制如何解決數(shù)據(jù)傳值為空的問(wèn)題

    Java反射機(jī)制如何解決數(shù)據(jù)傳值為空的問(wèn)題

    這篇文章主要介紹了Java反射機(jī)制如何解決數(shù)據(jù)傳值為空的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java 集合框架之List 的使用(附小游戲練習(xí))

    Java 集合框架之List 的使用(附小游戲練習(xí))

    這篇文章主要介紹Java 集合框架中List 的使用,下面文章將圍繞Java 集合框架中List 的使用展開(kāi)話(huà)題,并附上一些小游戲練習(xí),需要的朋友可以參考一下
    2021-10-10
  • Spring?Boot?詳細(xì)分析Conditional自動(dòng)化配置注解

    Spring?Boot?詳細(xì)分析Conditional自動(dòng)化配置注解

    首先我們先了解一下@Conditional注解,@Conditional是Spring4新提供的注解,它的作用是按照一定的條件進(jìn)行判斷,需要注入的Bean滿(mǎn)足給定條件才可以注入到Spring?IOC容器中
    2022-07-07
  • Java中Semaphore信號(hào)量的方法解析

    Java中Semaphore信號(hào)量的方法解析

    這篇文章主要介紹了Java中Semaphore信號(hào)量的方法解析,??Semaphore信號(hào)量是用來(lái)控制同?時(shí)訪(fǎng)問(wèn)?特定?資?源的?線(xiàn)?程數(shù)量,它通?過(guò)協(xié)調(diào)?各個(gè)?線(xiàn)?程,以保證合理的使用公共?資源,需要的朋友可以參考下
    2023-12-12
  • Springboot項(xiàng)目啟動(dòng)失敗提示找不到dao類(lèi)的解決

    Springboot項(xiàng)目啟動(dòng)失敗提示找不到dao類(lèi)的解決

    Spring Boot啟動(dòng)失敗,因ProductServiceImpl未正確注入ProductDao,原因:Dao未注冊(cè)為Bean,解決:在啟動(dòng)類(lèi)添加@MapperScan掃描Dao包,或單個(gè)Dao加@Mapper注解,推薦前者以批量注入
    2025-08-08

最新評(píng)論

广汉市| 商南县| 英超| 南平市| 且末县| 柳林县| 天等县| 时尚| 阿鲁科尔沁旗| 阿图什市| 灵丘县| 黑龙江省| 阜新市| 建始县| 托里县| 陵川县| 兴义市| 虎林市| 大同县| 来宾市| 来凤县| 白沙| 澎湖县| 麻江县| 乡城县| 内丘县| 历史| 亳州市| 南召县| 崇文区| 确山县| 莫力| 霸州市| 辽中县| 陆丰市| 娱乐| 龙游县| 乌海市| 永和县| 彩票| 尼玛县|