目錄
前言
1.?Spring AOP 用戶統(tǒng)?登錄驗(yàn)證的問題
1.1 自定義攔截器
1.2 配置攔截器并配置攔截的規(guī)則
1.3 攔截器的原理源碼分析
2. 統(tǒng)一異常處理
2.1 實(shí)現(xiàn)統(tǒng)一異常處理
2.2 測(cè)試統(tǒng)一異常處理
3. 統(tǒng)一的數(shù)據(jù)格式返回
3.1?統(tǒng)?數(shù)據(jù)返回格式的實(shí)現(xiàn)
3.2 測(cè)試統(tǒng)一的數(shù)據(jù)返回
前言
? ? ? ? Spring AOP是一個(gè)面向切面編程的框架,可以同設(shè)置要做處理的類為切面,設(shè)置切點(diǎn)進(jìn)行設(shè)置攔截規(guī)則,然后定義通知,實(shí)現(xiàn)一定的攔截規(guī)則.但是我們?cè)腟pring AOP的框架使用起來比較繁瑣.為了解決如此之類的Spring AOP的問題.對(duì)于Spring AOP的實(shí)戰(zhàn),本文將介紹三種功能.
1. 統(tǒng)一用戶登錄權(quán)限驗(yàn)證
2. 統(tǒng)一數(shù)據(jù)返回格式
3. 統(tǒng)一異常處理
1.?Spring AOP 用戶統(tǒng)?登錄驗(yàn)證的問題
假設(shè)我們要實(shí)現(xiàn)這樣一個(gè)功能,在多個(gè)頁面進(jìn)行判斷用戶的登錄狀態(tài),然后發(fā)現(xiàn)當(dāng)前用戶的登錄狀態(tài)為空的時(shí)候進(jìn)行跳轉(zhuǎn)到登錄頁.
????????我們之前的做法是,在每個(gè)頁面的路由中進(jìn)行判斷用戶的登錄狀態(tài),顯然這些操作是重復(fù)的,后來我們又學(xué)習(xí)了Spring AOP,我們?cè)囅肟梢詫⑿枰M(jìn)行驗(yàn)證的類進(jìn)行設(shè)置為切面,在需要地方進(jìn)行配置攔截的規(guī)則,然后進(jìn)行設(shè)置前置通知.這個(gè)思想是可以的,但是我們實(shí)現(xiàn)起來會(huì)遇到兩個(gè)問題.
1.??沒辦法獲取到 HttpSession 對(duì)象(我們需要對(duì)Session進(jìn)行判斷當(dāng)前的用戶登錄狀態(tài))
2.??我們要對(duì)?部分方法進(jìn)行攔截,而另?部分方法不攔截,如注冊(cè)?法和登錄方法是不攔截的,這樣的話排除?法的規(guī)則很難定義,甚至沒辦法定義。
針對(duì)一以上的問題,Spring 框架為我們提供了一個(gè)具體實(shí)現(xiàn)的攔截器:HandlerInterceptor
而我們要使用這個(gè)攔截器實(shí)現(xiàn)自己的功能,可以具體分為兩步:
?下面我們使用代碼進(jìn)行實(shí)現(xiàn)上述的功能:
1.1 自定義攔截器
具體代碼:
public class LoginInterceptor implements HandlerInterceptor {
/**
* 此方法返回一個(gè)boolean類型的值,返回true表示驗(yàn)證成功,繼續(xù)執(zhí)行后續(xù)流程
*/
// 重寫preHandle方法實(shí)現(xiàn)自己的業(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("userinfo") != null){
// 用戶已經(jīng)登錄
return true;
}
// 沒有登錄,可以進(jìn)行跳轉(zhuǎn)到登錄頁面,或者返回一個(gè)401 或者403 沒有權(quán)限碼
response.sendRedirect("/login1.html");
// response.setStatus(403);
// 上面兩者取一個(gè)即可
return false;
}
}
1.2 配置攔截器并配置攔截的規(guī)則
紅色部分就是將自定義的攔截器添加到項(xiàng)目中,然后綠色是一個(gè)擴(kuò)展,就是在路由前面加前綴.
?具體代碼:
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created with IntelliJ IDEA.
* Description:將自定義攔截器加入到WebMvcConfigurer中,重寫addInterceptors方法進(jìn)行設(shè)置攔截規(guī)則
* User: YAO
* Date: 2023-07-14
* Time: 15:04
*/
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 攔截規(guī)則設(shè)置,此處進(jìn)行攔截所有請(qǐng)求
.excludePathPatterns("/user/login")
.excludePathPatterns("/user/reg")
.excludePathPatterns("/user/get-num")
.excludePathPatterns("/user/get-string")
.excludePathPatterns("/img/**")
.excludePathPatterns("/**/*.html");
}
// 所有的接?添加 api 前綴
// 給路由進(jìn)行添加前綴 ,設(shè)置為 true 表示啟動(dòng)前綴
// @Override
// public void configurePathMatch(PathMatchConfigurer configurer) {
// configurer.addPathPrefix("api", c -> true);
// }
}
我們對(duì)上述實(shí)現(xiàn)的攔截器進(jìn)行驗(yàn)證
?當(dāng)進(jìn)行點(diǎn)擊的時(shí)候,因?yàn)闆]有Session所以直接跳轉(zhuǎn)到我們?cè)O(shè)置的登錄頁面了.
可以看出沒有進(jìn)行設(shè)置過Cookie的,就是沒有Session連接.?
1.3 攔截器的原理源碼分析
所有的方法都會(huì)執(zhí)行 DispatcherServlet 中的 doDispatch 調(diào)度方法,觀察源碼發(fā)現(xiàn):
??點(diǎn)擊這個(gè)applyPreHandle,applyPreHandle 中會(huì)獲取所有攔截器 HandlerInterceptor 并執(zhí)行攔截器中的 preHandle 方法,這與之前我們實(shí)現(xiàn)攔截器的步驟對(duì)應(yīng).
2. 統(tǒng)一異常處理
????????統(tǒng)一異常處理是指?在應(yīng)用程序中定義一個(gè)公共的異常處理機(jī)制,用來處理所有的異常情況。?這樣可以避免在應(yīng)用程序中分散地處理異常,降低代碼的復(fù)雜度和重復(fù)度,提高代碼的可維護(hù)性和可擴(kuò)展性.\
????????統(tǒng)?異常處理使?的是 @ControllerAdvice + @ExceptionHandler 來實(shí)現(xiàn)的,@ControllerAdvice 表示控制器通知類,@ExceptionHandler 是異常處理器,兩個(gè)結(jié)合表示當(dāng)出現(xiàn)異常的時(shí)候執(zhí)行某個(gè)通知,也就是執(zhí)行某個(gè)方法事件.
2.1 實(shí)現(xiàn)統(tǒng)一異常處理
2.2 測(cè)試統(tǒng)一異常處理
我們自己創(chuàng)建一個(gè)路由,其中內(nèi)容出現(xiàn)一個(gè)空指針異常,我們查看是否能進(jìn)行返回給前端處理.?
我們?cè)O(shè)置的異常處理起到作用了.那么如果不設(shè)置,異常的處理,會(huì)出現(xiàn)什么樣的現(xiàn)象?
就會(huì)直接將控制臺(tái)打印的異常返回給前端,前端拿到數(shù)據(jù)就很懵.所以統(tǒng)一的異常處理還是很有必要的.
3. 統(tǒng)一的數(shù)據(jù)格式返回
3.1?統(tǒng)?數(shù)據(jù)返回格式的實(shí)現(xiàn)
下述是我們一般的統(tǒng)一返回的數(shù)據(jù)的格式
實(shí)現(xiàn)統(tǒng)一的數(shù)據(jù)返回格式可以使用 @ControllerAdvice + ResponseBodyAdvice 的方式實(shí)現(xiàn),具體步驟如下:
- 創(chuàng)建一個(gè)類,并添加 @ControllerAdvice 注解;
- 實(shí)現(xiàn) ResponseBodyAdvice 接口,并重寫 supports 和 beforeBodyWrite 方法.
?上述部分就是記性統(tǒng)一的數(shù)據(jù)格式返回.
其中需要注意的是,當(dāng)返回的類型為String類型的時(shí)候,我們需要使用Jackson將String轉(zhuǎn)換成json再進(jìn)行返回.也就是綠色的部分.
package com.example.demo.config;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
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.ResponseBodyAdvice;
import java.util.HashMap;
/**
* Created with IntelliJ IDEA.
* Description:
* User: YAO
* Date: 2023-07-14
* Time: 17:25
*/
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
HashMap<String, Object> result = new HashMap<>();
result.put("state",1);
result.put("msg", "");
result.put("data", body);
if (body instanceof String){
// 需要特殊進(jìn)行處理,因?yàn)镾tring比較特殊,既不是基礎(chǔ)類型也不是對(duì)象,進(jìn)行重寫的時(shí)候String用的格式化工具是自己獨(dú)有的
// 在body返回之前沒有加載好.需要將String進(jìn)行單獨(dú)進(jìn)行處理.使用Jackson將String轉(zhuǎn)換成json再進(jìn)行返回.
try {
return objectMapper.writeValueAsString(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return result;
}
}
3.2 測(cè)試統(tǒng)一的數(shù)據(jù)返回
可以看出返回的格式是我們規(guī)定好的格式.這就變得更加統(tǒng)一.
?好啦本文就總結(jié)到這了,點(diǎn)個(gè)贊吧,謝謝!!!文章來源:http://www.zghlxwxcb.cn/news/detail-625619.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-625619.html
到了這里,關(guān)于Spring Boot 系列4 -- 統(tǒng)一功能處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!