SpringBoot實(shí)現(xiàn)統(tǒng)一功能處理的教程詳解
實(shí)現(xiàn)三個(gè)SpringBoot統(tǒng)一功能處理
1.統(tǒng)一用戶登陸權(quán)限驗(yàn)證
2.統(tǒng)一異常處理
3.統(tǒng)一數(shù)據(jù)格式返回
1.統(tǒng)一用戶登陸權(quán)限驗(yàn)證
之前的博客系統(tǒng)中,我們在每個(gè)頁面都要檢查用戶是否登錄,之后才有權(quán)限去做其他操作,之前的判斷方式就是,需要驗(yàn)權(quán)的每一處都寫了相同的驗(yàn)證方法.業(yè)務(wù)代碼中夾雜了這些非業(yè)務(wù)的代碼
現(xiàn)在我們提供一個(gè)公共的AOP方法來進(jìn)行統(tǒng)一的用戶登陸權(quán)限驗(yàn)證
在AOP的切面中實(shí)現(xiàn)用戶登陸權(quán)限的校驗(yàn)功能非常麻煩
Spring中提供了具體的實(shí)現(xiàn)攔截器:HandlerInterceptor
攔截器的實(shí)現(xiàn):
WebMvcConfigurer+HandlerInterceptor
1.1.創(chuàng)建自定義攔截器
創(chuàng)建一個(gè) Java 類,并實(shí)現(xiàn) HandlerInterceptor 接口,該接口有三個(gè)方法:preHandle、postHandle 和 afterCompletion。在 preHandle 方法中編寫前置處理邏輯,在 postHandle 方法中編寫后置處理邏輯,在 afterCompletion 方法中編寫完成后的處理邏輯
此方法返回的是布爾類型的值,返回true表示攔截器驗(yàn)證成功,繼續(xù)執(zhí)行目標(biāo)方法
返回false,則表示攔截器執(zhí)行失敗,驗(yàn)證不通過,后續(xù)目標(biāo)方法不會(huì)執(zhí)行
public class LoginInterceptor implements HandlerInterceptor { @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){ //用戶登陸成功 return true; } //response.sendRedirect("http://www.baidu.com");跳轉(zhuǎn)頁面 //response.setStatus(401);沒有權(quán)限 return false; } }
2.將自定義攔截器配置到系統(tǒng)配置項(xiàng),并設(shè)置攔截規(guī)則
代碼
@Configuration public class MyConfig implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns("/**")//攔截所有的url .excludePathPatterns("/user/login")//排除登陸功能 .excludePathPatterns("/user/reg")//排除注冊功能 .excludePathPatterns("/image/**")//排除image下所有的文件 ; } }
對如下代碼測試
這里登陸失敗后由于將狀態(tài)設(shè)置為了401,所以網(wǎng)頁無法正常運(yùn)作了
正常的應(yīng)該是,返回檢驗(yàn)登陸失敗的信息,讓用戶從前端了解情況
有了攔截器之后,會(huì)在調(diào)用Controller之前進(jìn)行攔截器的預(yù)處理操作
執(zhí)行流程:用戶->攔截器->controller->service->mapper->database
下來我們分析源碼
所有的Controller執(zhí)行都會(huì)通過一個(gè)DispatcherServlet來實(shí)現(xiàn),可以從打印臺(tái)看出
DispatcherServlet是SpringMVC框架的核心,主要負(fù)責(zé)管理請求和處理器之間的映射關(guān)系,并結(jié)合所配置的攔截器和視圖解析器來實(shí)現(xiàn)請求的分發(fā)和結(jié)果的呈現(xiàn)
例如:攔截器:DispatcherServlet支持對請求進(jìn)行攔截,并允許用戶定義自己的攔截器來進(jìn)行請求處理前和處理后的操作
大致流程如下
2.統(tǒng)一異常處理
如果不進(jìn)行統(tǒng)一異常處理,出現(xiàn)異常,會(huì)直接將異常拋到前端
統(tǒng)一的異常處理使用的是@ControllerAdvice和@ExceptionHandler來實(shí)現(xiàn)的
@ControllerAdvice表示控制器通知類,@ExceptionHandler是異常處理器,兩者結(jié)合表示出現(xiàn)異常時(shí)執(zhí)行某個(gè)通知
1.建立異常處理類
添加該注解可以集中處理所有 Controller 中拋出的異常,從而避免開發(fā)人員在每個(gè) Controller 中都編寫異常處理代碼的重復(fù)勞動(dòng)
2.創(chuàng)建異常檢測的類和業(yè)務(wù)處理方法
@ControllerAdvice 可以定義一些方法,在方法內(nèi)部使用 @ExceptionHandler 注解來處理指定類型的異常。當(dāng) Controller 中拋出該類型的異常時(shí),就會(huì)自動(dòng)調(diào)用相應(yīng)的方法來處理異常,而不是直接將異常拋到前端
此時(shí)就會(huì)返回一個(gè)json格式的異常信息到前端
上述只是處理了空指針異常,其它異常是攔截不到的.所以將監(jiān)視異常的范圍擴(kuò)大,出現(xiàn)各種異常,就會(huì)找到它們的父類--Exception
添加一個(gè)異常代碼
如果實(shí)現(xiàn)了具體的異常類,也實(shí)現(xiàn)了Exception.那么默認(rèn)是匹配具體的異常處理,匹配不到就會(huì)尋找父類的處理
3.統(tǒng)一數(shù)據(jù)格式返回
統(tǒng)一數(shù)據(jù)格式返回是指在 Spring MVC 中,定義一個(gè)通用的數(shù)據(jù)結(jié)構(gòu),來封裝所有接口的返回值,這樣可以更好地對所有返回結(jié)果進(jìn)行統(tǒng)一處理和管理,從而提高代碼的可維護(hù)性、可重用性和可擴(kuò)展性
使用注解@ControllerAdvice+ResponseBodyAdvice接口
步驟:
1.創(chuàng)建一個(gè)類,并添加 @ControllerAdvice 注解,該注解作用于類上,表示這是一個(gè)全局控制器增強(qiáng)器
2.實(shí)現(xiàn) ResponseBodyAdvice 接口,并指定泛型 T 為 Object 類型。該接口中定義了兩個(gè)方法 beforeBodyWrite() 和 supports(),分別用于處理響應(yīng)前的操作和判斷是否支持當(dāng)前返回值類型
3.在 beforeBodyWrite() 方法中,判斷響應(yīng)的對象是否為自定義的統(tǒng)一數(shù)據(jù)格式返回類型,如果不是,則將它轉(zhuǎn)換成統(tǒng)一的格式,例如封裝成一個(gè) Result 對象
4.在 supports() 方法中,判斷當(dāng)前返回值類型是否需要進(jìn)行統(tǒng)一數(shù)據(jù)格式返回的處理
使用該方法后,所有返回類型為非基本數(shù)據(jù)類型的請求,都會(huì)經(jīng)過 ResponseBodyAdvice 的處理,從而統(tǒng)一返回給前端一個(gè)自定義的結(jié)構(gòu)體數(shù)據(jù)
@ControllerAdvice public class ResponseBody implements ResponseBodyAdvice { //是否執(zhí)行beforeBodyWrite,true為執(zhí)行 @Override public boolean supports(MethodParameter returnType, Class converterType) { return true; } //返回?cái)?shù)據(jù)之前進(jìn)行數(shù)據(jù)重寫 //body:原始返回值 @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { //標(biāo)準(zhǔn)返回格式定義為:HashMap<String,Object>->code,msg,data if(body instanceof HashMap){ return body; } //重寫返回結(jié)果,返回統(tǒng)一格式 HashMap<String,Object> res = new HashMap<>(); res.put("code",200); res.put("msg",""); res.put("data",body); return res; } }
login:
reg:
按照保底的數(shù)據(jù)返回格式應(yīng)該返回data為sayhello
Resolved [java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.String]
將String格式化數(shù)據(jù)執(zhí)行流程分為三部
1.方法返回String
2.統(tǒng)一數(shù)據(jù)格式返回之前處理:String轉(zhuǎn)換為Hash Map
3.將Hash Map轉(zhuǎn)換為application/json 字符串返回給前端(接口)
不進(jìn)行異常攔截時(shí):
通過報(bào)錯(cuò)信息,可以看出是第三步出了問題,無法將HashMap 轉(zhuǎn)換為json字符串
原因:在第三步會(huì)對原body類型進(jìn)行判斷
1.String類型:使用StringHttpMessageConverter轉(zhuǎn)換器進(jìn)行轉(zhuǎn)換
2.非string類型:HttpMessageConverter轉(zhuǎn)換器進(jìn)行轉(zhuǎn)換
使用的卻是StringHttpMessageConverter轉(zhuǎn)換器對HashMap轉(zhuǎn)換成json字符串.就會(huì)拋出異常
應(yīng)當(dāng)適用HttpMessageConverter
判斷時(shí)使用原body進(jìn)行判斷,轉(zhuǎn)換時(shí)使用的是Hash Map進(jìn)行轉(zhuǎn)換的..StringHttpMessageConverter轉(zhuǎn)換不了Hash Map
解決方案:
1. 移除StringHttpMessageConverter
通過config配置文件移除
@Configuration public class MyConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.removeIf(converter -> converter instanceof StringHttpMessageConverter); } }
2.統(tǒng)一數(shù)據(jù)重寫時(shí)單獨(dú)處理String類型,單獨(dú)返回,不使用Hash Map進(jìn)行統(tǒng)一返回
方式一:
方式二:使用json工具轉(zhuǎn)換
以上就是SpringBoot實(shí)現(xiàn)統(tǒng)一功能處理的教程詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot統(tǒng)一功能處理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring需要三個(gè)級別緩存解決循環(huán)依賴原理解析
這篇文章主要為大家介紹了Spring需要三個(gè)級別緩存解決循環(huán)依賴原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02劍指Offer之Java算法習(xí)題精講數(shù)組查找與字符串交集
跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03詳解servlet的url-pattern匹配規(guī)則
本篇文章主要介紹了=servlet的url-pattern匹配規(guī)則,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12java連接hdfs ha和調(diào)用mapreduce jar示例
這篇文章主要介紹了Java API連接HDFS HA和調(diào)用MapReduce jar包,需要的朋友可以參考下2014-03-03關(guān)于SpringBoot的自動(dòng)裝配原理詳解
這篇文章主要介紹了關(guān)于SpringBoot的自動(dòng)裝配原理詳解,Spring?Boot自動(dòng)裝配原理是指Spring?Boot在啟動(dòng)時(shí)自動(dòng)掃描項(xiàng)目中的依賴關(guān)系,根據(jù)依賴關(guān)系自動(dòng)配置相應(yīng)的Bean,從而簡化了Spring應(yīng)用的配置過程,需要的朋友可以參考下2023-07-07