中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot統一處理功能如何實現

發布時間:2023-03-20 11:11:50 來源:億速云 閱讀:134 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“SpringBoot統一處理功能如何實現”,內容詳細,步驟清晰,細節處理妥當,希望這篇“SpringBoot統一處理功能如何實現”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

在處理網絡請求時,有一部分功能是需要抽出來統一處理的,與業務隔開。

登錄校驗

可以利用spring mvc的攔截器Interceptor,實現HandlerInterceptor接口即可。實現該接口后,會在把請求發給Controller之前進行攔截處理。

攔截器的實現分為以下兩個步驟:

  • 創建?定義攔截器,實現 HandlerInterceptor 接?的 preHandle(執?具體?法之前的預處理)?法。

  • 將?定義攔截器加? WebMvcConfigurer 的 addInterceptors ?法中。

我們使用session來作為登錄校驗的例子,實現如下:

package com.demo;
import lombok.extern.slf4j.Slf4j;
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
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 為 false 則不能繼續往下執行;為 true 則可以。
     */ 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判斷session的信息是否合法
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("userinfo") != null) {
            return true;
        }
        log.error("當前用戶沒有訪問權限");
        response.setStatus(401);
        return false;
    }
}

將寫好的?定義攔截器通過WebMvcConfigurer注冊到容器中,使得攔截器生效,具體實現代碼如下:

package com.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**") // 攔截所有請求
                .excludePathPatterns("/user/login"); // 排除不攔截的 url
    }
}

如果不注入對象的話,addInterceptor() 的參數也可以直接 new 一個對象:

@Configuration // 一定不要忘記
public class MyConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**") // 攔截所有請求
                .excludePathPatterns("/user/login"); // 排除不攔截的 url
    }
}

原理

所有的 Controller 執?都會通過spring mvc的調度器 DispatcherServlet 來實現,所有?法都會執? DispatcherServlet 中的 doDispatch 調度?法,doDispatch 源碼如下:

protected void doDispatch(HttpServletRequest request, HttpServletResponse
        response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    try {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;
            try {
                // ...  忽略不重要的代碼
                // 調?預處理
                if (!mappedHandler.applyPreHandle(processedRequest, respon
                        se)) {
                    return;
                }
                // 執? Controller 中的業務
                mv = ha.handle(processedRequest, response, mappedHandler.g
                        etHandler());
               // ...  忽略不重要的代碼
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler di
                        spatch failed", var21);
            }
            this.processDispatchResult(processedRequest, response, mappedH
                    andler, mv, (Exception)dispatchException);
        } catch (Exception var22) {
            this.triggerAfterCompletion(processedRequest, response, mapped
                    Handler, var22);
        } catch (Throwable var23) {
            this.triggerAfterCompletion(processedRequest, response, mapped
                    Handler, new NestedServletException("Handler processing failed", var23));
        }
    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processe
                        dRequest, response);
            }
        } else if (multipartRequestParsed) {
            this.cleanupMultipart(processedRequest);
        }
    }
}

從上述源碼可以看出在開始執? Controller 之前,會先調? 預處理?法 applyPreHandle,? applyPreHandle ?法的實現源碼如下:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex
            = i++) {
        // 獲取項?中使?的攔截器 HandlerInterceptor
        HandlerInterceptor interceptor = (HandlerInterceptor)this.intercep
        torList.get(i);
        if (!interceptor.preHandle(request, response, this.handler)) {
            this.triggerAfterCompletion(request, response, (Exception)null
            );
            return false;
        }
    }
    return true;
}

異常處理

請求時的異常處理也是比較常見的統一處理的對象。

統?異常處理使?的是 @ControllerAdvice + @ExceptionHandler 來實現的,@ControllerAdvice 表示控制器通知類,@ExceptionHandler 是異常處理器,兩個結合表示當出現異常的時候執?某個通知,也就是執?某個?法事件,具體實現代碼如下:

package com.demo;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
/**
 * 統一處理異常
 * 一般都需要自定義一個異常對象,這里為了簡單說明只用一個map對象來說明
 */
@ControllerAdvice
public class ErrorAdive {
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public HashMap<String, Object> exceptionAdvie(Exception e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", "-1");
        result.put("msg", e.getMessage());
        return result;
    }
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public HashMap<String, Object> arithmeticAdvie(ArithmeticException e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", "-2");
        result.put("msg", e.getMessage());
        return result;
    }
}

此時若出現異常就不會報錯了,代碼會繼續執行,但是會把自定義的異常信息返回給前端!

原理

@ControllerAdvice是spring的aop對于Controller進行切面所有屬性的,包括切入點和需要織入的切面邏輯,配合@ExceptionHandler來捕獲Controller中拋出的指定類型的異常,從而達到不同類型的異常區別處理的目的。

返回數據結構

統?的返回數據結構可以使用 @ControllerAdvice + ResponseBodyAdvice接口 的方式實現,具體實現代碼如下:

package com.demo;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyA
dvice;
import java.util.HashMap;
/**
 * 統一返回數據的處理
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    /**
     * 內容是否需要重寫(通過此?法可以選擇性部分控制器和?法進?重寫)
     * 返回 true 表示重寫
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterTyp
e) {
        return true;
    }
    /**
     * ?法返回之前調?此?法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpR
                                          equest request,
                                  ServerHttpResponse response) {
        // 構造統?返回對象
        HashMap<String, Object> result = new HashMap<>();
        result.put("state", 1);
        result.put("msg", "");
        result.put("data", body);
        return result;
    }
}

讀到這里,這篇“SpringBoot統一處理功能如何實現”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

衡南县| 获嘉县| 隆尧县| 晋州市| 库伦旗| 芦山县| 四子王旗| 曲靖市| 临汾市| 淳化县| 庆安县| 清镇市| 读书| 辽中县| 泰宁县| 巴东县| 安阳县| 永福县| 台山市| 泌阳县| 松溪县| 诸暨市| 乌兰察布市| 唐海县| 工布江达县| 德令哈市| 辽阳市| 沁水县| 望谟县| 招远市| 木里| 邹城市| 南阳市| 桃园市| 富顺县| 巴里| 蓬莱市| 南投县| 鹰潭市| 美姑县| 乐都县|