亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot 統(tǒng)一功能處理方案

 更新時間:2025年04月23日 10:30:09   作者:Bug退退退123  
在我們進(jìn)行項(xiàng)目編寫時,有時相同的一段代碼在不同的地方使用多次,對于這種情況,spring 幫我們實(shí)現(xiàn)了統(tǒng)一功能處理,下面介紹一些常用的統(tǒng)一功能處理,感興趣的朋友一起看看吧

在我們進(jìn)行項(xiàng)目編寫時,有時相同的一段代碼在不同的地方使用多次,對于這種情況,spring 幫我們實(shí)現(xiàn)了統(tǒng)一功能處理,下面介紹一些常用的統(tǒng)一功能處理。

一、攔截器

在有些項(xiàng)目中,是需要用戶登錄才能進(jìn)行后續(xù)訪問的。但如果這時有人拿到了后端接口的 url,這時就能跳過用戶登錄進(jìn)而訪問我們的網(wǎng)站,這就有可能對網(wǎng)站造成攻擊,對于這種情況,我們可以將用戶的部分信息存到 session 中,在每次訪問接口前,都可以先獲取到 session,再將用戶信息取出,看看這個用戶是否登錄,若登錄,就允許繼續(xù)訪問,若沒有登陸,就強(qiáng)制登錄。

但是,在我們的項(xiàng)目中,接口的數(shù)目可不小,若是在每個接口中都加上這段邏輯,就會顯得我們的代碼過于冗余,于是 Spring 就為我們構(gòu)造了攔截器。

攔截器主要用來攔截用戶的請求,在指定方法前后執(zhí)行攔截器中預(yù)設(shè)的代碼,也就是說,攔截器可以在用戶的請求之前發(fā)揮作用,也可以在用戶的請求之后發(fā)揮作用。

對于上述判斷用戶登錄的業(yè)務(wù),我們就可以在攔截器中寫明判斷用戶是否登錄的代碼,這樣在用戶發(fā)送請求時,就會先執(zhí)行這段代碼,若用戶沒有登錄,就會阻止用戶進(jìn)行訪問,并跳轉(zhuǎn)到登陸頁面(這是前端干的事)。

下面介紹攔截器的具體用法。

在實(shí)現(xiàn)攔截器時,需要實(shí)現(xiàn) HandlerInterceptor 類中的 preHandle,postHandle,afterCompletion 方法,preHandle 是在目標(biāo)方法執(zhí)行前執(zhí)行的,postHandle 是在目標(biāo)方法執(zhí)行之后執(zhí)行的,afterCompletion 是在試圖渲染完成之后執(zhí)行的,但現(xiàn)在后端開發(fā)基本上都不會涉及到試圖,那么這個方法就不重點(diǎn)介紹了。

代碼如下:

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    //在目標(biāo)方法執(zhí)行前執(zhí)行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("在目標(biāo)方法執(zhí)行前執(zhí)行");
        return true;
    }
    //在目標(biāo)方法之后執(zhí)行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("在目方法執(zhí)行后執(zhí)行");
    }
    //試圖渲染完成之后執(zhí)行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("視圖渲染完成后執(zhí)行");
    }
}

preHandle 有返回值,返回 true 表示不攔截請求,返回 false 表示攔截請求。

定義好攔截器的功能后,接下來就需要注冊攔截器。注冊攔截器需要實(shí)現(xiàn) WebMvcConfigurer 中的 addInterceptors,代碼如下:

@Slf4j
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/test/**");
    }
}

使用 addInterceptor 即表示需要注冊的是哪個攔截器,使用 addPathPatterns 即表示需要攔截的路徑,即攔截器對哪些請求生效,這里的 /test/** 表示對 test 路徑下的所有方法均生效,還有其它的路徑表示,如下:

/* : 表示一級路徑,只能匹配 /test,不能匹配 /test/t1等;

/** : 表示任意級路徑,能匹配 /test,/test/t1等;

/test/* : 表示 /test 下的一級路徑,可以匹配 /test/t1,但不能匹配 /test/t1/t2等;

/test/** : 表示 /test 下的任意級路徑,可以匹配 /test/t1,/test/t1/t2,但不能匹配 /user/login 等。

當(dāng)我們配置完攔截器和注冊完攔截器后,就可以開始運(yùn)行代碼,我們使用下面的代碼來進(jìn)行測試:

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
    @RequestMapping("/t1")
    public void t1() {
        log.info("攔截器測試...");
    }
}

代碼運(yùn)行結(jié)果如下:

在這里我們可以看到,當(dāng)訪問被攔截的方法時,首先執(zhí)行的是 preHandle,由于 postHandle 返回值為 true,就不會攔截用戶請求,于是就會先執(zhí)行 t1 方法,之后會順序執(zhí)行 postHandle 和 afterCompletion。

若 preHandle 返回值為 false,代碼的運(yùn)行結(jié)果如下:

從結(jié)果中可以看出,程序只執(zhí)行了 preHandle,由于 t1 被攔截,于是 t1、postHandle、afterCompletion 就不會執(zhí)行。

在上述的攔截路徑中,我們將 /test 下的所有路徑都給攔截了,但是有的請求我們不需要攔截,那么我們就可以使用 excludPathPatterns 去去除掉不需要攔截的路徑,改動后的代碼如下:

@Slf4j
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/test/**")
                .excludePathPatterns("/test/t2");
    }
}
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
    @RequestMapping("/t1")
    public void t1() {
        log.info("t1攔截器測試...");
    }
    @RequestMapping("/t2")
    public void t2() {
        log.info("不攔截t2測試");
    }
}

TestController 中新增了 t2 方法,只攔截 t1,不攔截 t2,代碼運(yùn)行結(jié)果如下:

從圖中可以看出,t1被攔截,但 t2 沒有被攔截。

當(dāng)我們知道如何使用攔截器之后,就可以在項(xiàng)目中進(jìn)行運(yùn)用。

當(dāng)用戶在進(jìn)行訪問時,就可以對其訪問進(jìn)行攔截,在攔截器中判斷用戶是否登錄,若登錄就放行,若沒有登錄就跳轉(zhuǎn)到登錄頁面進(jìn)行登錄,代碼如下:

package com.gjm.demo.interceptor;
import com.gjm.demo.constant.Constants;
import com.gjm.demo.enums.ResultStatusEnums;
import com.gjm.demo.model.Result;
import com.gjm.demo.model.UserInfo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
 * 登錄攔截器
 */
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 目標(biāo)方法前執(zhí)行, 攔截器攔截到后,就會將response返回給前端,前端的error中就能就受到response
     * @param request
     * @param response
     * @param handler
     * @return true: 繼續(xù)執(zhí)行, false: 中斷后續(xù)操作
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("登錄之前執(zhí)行");
        //用戶未登錄的處理
        if (!checkUserInfo(request.getSession())) {
            response.setContentType("text/html;character=utf-8");
            response.setStatus(401);
            String errorMessage = "用戶未登錄";
            response.getOutputStream().write(errorMessage.getBytes("UTF-8"));
            return false;
        }
        return true;
    }
    /**
     * 對檢查用戶信息進(jìn)行封裝
     * @param session
     * @return
     */
    public boolean checkUserInfo(HttpSession session) {
        //用戶未登錄
        if (session == null || session.getAttribute(Constants.SESSION_USER_KEY) == null) {
            return false;
        }
        //獲取用戶信息
        UserInfo userInfo = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
        //用戶信息不對
        if (userInfo == null || userInfo.getId() <= 0) {
            return false;
        }
        return true;
    }
}

 其中 check 的用處是檢查用戶是否登錄。

二、統(tǒng)一數(shù)據(jù)返回格式

在進(jìn)行項(xiàng)目開發(fā)時,我需要向前端返回一個統(tǒng)一的數(shù)據(jù),這個數(shù)據(jù)是經(jīng)過封裝的,但是,在我們的接口中,有的返回的是 String,有的返回的是 boolean等,這就需要我們針對每一個接口都編寫封裝結(jié)果的代碼,這樣的代碼就有點(diǎn)冗余了。于是,Spring 就封裝了能夠統(tǒng)一返回數(shù)據(jù)格式的方法。

現(xiàn)在有一個結(jié)果類 Result,對于接口中的每一種返回值,都需要將其封裝為 Result 對象,實(shí)現(xiàn)的代碼如下:

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        //false為不處理,true為處理
        return true;
    }
    @SneakyThrows//異常處理
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof String) {
            return objectMapper.writeValueAsString(Result.success(body));//將Result類型轉(zhuǎn)化為String類型
        }
        //body已經(jīng)是result類型,就不需要封裝
        if (body instanceof Result) {
            return body;
        }
        return Result.success(body);
    }
}

該類需實(shí)現(xiàn) ResponseBodyAdvice 接口,實(shí)現(xiàn) support 和 beforeBodyWrite 方法,而且需要加上 @ControllerAdvice 注解。

support 的返回值為 boolean,返回 true 表示對各類型的返回值都進(jìn)行處理,返回 false 表示不處理。

beforeBodyWrite 即具體的實(shí)現(xiàn)類。在這里需要強(qiáng)調(diào),若接口中的返回值為 String,那么就需要對其進(jìn)行單獨(dú)處理,不然就會報錯。

對于本來就是 Result 類型的對象,就不要進(jìn)行處理,直接返回即可。

三、統(tǒng)一異常處理

在我們編寫代碼的時候,有時候可能判斷的不準(zhǔn)確,不知道哪里會出現(xiàn)異常,那么如果我們不進(jìn)行處理,就會影響程序的運(yùn)行。對于這種情況,Spring 為我們封裝了一個能統(tǒng)一處理異常的方法,代碼如下:

@Slf4j
@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {
    @ExceptionHandler
    public Result handler(Exception e) {
        log.error("發(fā)生異常, e: ", e);
        return Result.fail(ResultStatusEnums.ERROR, "內(nèi)部錯誤,請聯(lián)系管理員");
    }
    @ExceptionHandler
    public Result handler(NullPointerException e) {
        log.error("發(fā)生異常, e: ", e);
        return Result.fail(ResultStatusEnums.ERROR, "空指針異常,請聯(lián)系管理員");
    }
    @ExceptionHandler
    public Result handler(IndexOutOfBoundsException e) {
        log.error("發(fā)生異常, e: ", e);
        return Result.fail(ResultStatusEnums.ERROR, "數(shù)組越界異常,請聯(lián)系管理員");
    }
}

ExceptionAdvice 需要使用 @ControllerAdvice 和 @ResponseBody 注解。

在各個方法上需要使用 @ExceptionHandler 注解。

在這個類中,一共處理了三個異常,也可以繼續(xù)增加異常的種類。若代碼中拋出了異常并且沒有手動捕獲,就會拋給 ExceptionAdvice 類,在這個類中尋找與之距離最近的異常,若沒有,就會直接使用 Exception 代替。

上述的代碼還有另一種寫法,代碼如下:

@Slf4j
@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {
    @ExceptionHandler(Exception.class)
    public Result handler1(Exception e) {
        log.error("發(fā)生異常, e: ", e);
        return Result.fail(ResultStatusEnums.ERROR, "內(nèi)部錯誤,請聯(lián)系管理員");
    }
    @ExceptionHandler(NullPointerException.class)
    public Result handler2(Exception e) {
        log.error("發(fā)生異常, e: ", e);
        return Result.fail(ResultStatusEnums.ERROR, "空指針異常,請聯(lián)系管理員");
    }
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public Result handler3(Exception e) {
        log.error("發(fā)生異常, e: ", e);
        return Result.fail(ResultStatusEnums.ERROR, "數(shù)組越界異常,請聯(lián)系管理員");
    }
}

在每個 @ExceptionHandler 注解中標(biāo)明捕獲的是什么類型的異常,這樣在每個方法的參數(shù)中就能直接使用 Exception 代替。

到此這篇關(guān)于SpringBoot 統(tǒng)一功能處理方案的文章就介紹到這了,更多相關(guān)SpringBoot 統(tǒng)一功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?zxing實(shí)現(xiàn)生成并解析二維碼與條形碼

    Java?zxing實(shí)現(xiàn)生成并解析二維碼與條形碼

    這篇文章主要為大家詳細(xì)介紹了Java如何通過zxing實(shí)現(xiàn)生成并解析二維碼與條形碼,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2024-11-11
  • 配置tjxCold(idea效率插件)的模版教程詳解

    配置tjxCold(idea效率插件)的模版教程詳解

    這篇文章主要介紹了配置tjxCold(idea效率插件)的模版教程詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • java基于Apache FTP實(shí)現(xiàn)文件上傳、下載、修改文件名、刪除

    java基于Apache FTP實(shí)現(xiàn)文件上傳、下載、修改文件名、刪除

    本篇文章主要介紹了Apache FTP實(shí)現(xiàn)文件上傳、下載、修改文件名、刪除,實(shí)現(xiàn)了FTP文件上傳(斷點(diǎn)續(xù)傳)、FTP文件下載、FTP文件重命名、FTP文件刪除等功能,有需要的可以了解一下。
    2016-11-11
  • SpringBoot注解@EnableScheduling定時任務(wù)詳細(xì)解析

    SpringBoot注解@EnableScheduling定時任務(wù)詳細(xì)解析

    這篇文章主要介紹了SpringBoot注解@EnableScheduling定時任務(wù)詳細(xì)解析,@EnableScheduling 開啟對定時任務(wù)的支持,啟動類里面使用@EnableScheduling 注解開啟功能,自動掃描,需要的朋友可以參考下
    2024-01-01
  • Springboot @RequestBody注解踩坑記錄

    Springboot @RequestBody注解踩坑記錄

    這篇文章主要介紹了Springboot @RequestBody注解踩坑記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot如何通過yml方式整合Mybatis

    SpringBoot如何通過yml方式整合Mybatis

    這篇文章主要介紹了SpringBoot如何通過yml方式整合Mybatis,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Spring事務(wù)框架之TransactionStatus源碼解析

    Spring事務(wù)框架之TransactionStatus源碼解析

    這篇文章主要為大家介紹了Spring事務(wù)框架之TransactionStatus源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • springcloud檢索中間件?ElasticSearch?分布式場景的使用

    springcloud檢索中間件?ElasticSearch?分布式場景的使用

    單機(jī)的elasticsearch做數(shù)據(jù)存儲,必然面臨兩個問題:海量數(shù)據(jù)存儲問題、單點(diǎn)故障問題,本文重點(diǎn)給大家介紹springcloud檢索中間件?ElasticSearch?分布式場景的運(yùn)用,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • Spring boot 數(shù)據(jù)源未配置異常的解決

    Spring boot 數(shù)據(jù)源未配置異常的解決

    這篇文章主要介紹了Spring boot 數(shù)據(jù)源未配置異常的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 簡單了解Java垃圾回收器的種類

    簡單了解Java垃圾回收器的種類

    這篇文章主要介紹了簡單了解Java垃圾回收器的種類,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12

最新評論