国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

商貿(mào)網(wǎng)站管理培訓(xùn)機(jī)構(gòu)

商貿(mào)網(wǎng)站,管理培訓(xùn)機(jī)構(gòu),西寧網(wǎng)站建設(shè)服務(wù)公司,裝飾設(shè)計(jì)乙級資質(zhì)目錄 一、用戶登錄權(quán)限驗(yàn)證 1.1 SpringAOP可以進(jìn)行處理嗎? 1.2 創(chuàng)建自定義攔截器 1.3 將自定義攔截器配置到系統(tǒng)配置項(xiàng)中 1.4 攔截器的實(shí)現(xiàn)原理 1.4.1 實(shí)現(xiàn)原理源碼分析 1.5 統(tǒng)一訪問前綴添加 二、統(tǒng)一異常處理 2.1 為什么需要使用統(tǒng)一異常處理?…

目錄

一、用戶登錄權(quán)限驗(yàn)證

1.1 SpringAOP可以進(jìn)行處理嗎?

1.2?創(chuàng)建自定義攔截器

?1.3?將自定義攔截器配置到系統(tǒng)配置項(xiàng)中

1.4 攔截器的實(shí)現(xiàn)原理

1.4.1 實(shí)現(xiàn)原理源碼分析

1.5 統(tǒng)一訪問前綴添加

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

2.1 為什么需要使用統(tǒng)一異常處理?

2.2 統(tǒng)一異常處理的實(shí)現(xiàn)

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

3.1 為什么需要統(tǒng)一數(shù)據(jù)返回格式?

3.2 統(tǒng)一數(shù)據(jù)返回格式的實(shí)現(xiàn)

?3.3 返回值為String類型時(shí),應(yīng)該如何處理?

3.3.1 將 StringHttpMessageConverter 去掉。

3.3.2 在統(tǒng)一數(shù)據(jù)返回的時(shí)候,單獨(dú)處理String類型,讓其返回一個(gè)String字符串,而非 HashMap

?總結(jié):


前言:

一般Spring Boot統(tǒng)一功能處理模塊,也是AOP的實(shí)戰(zhàn)環(huán)節(jié),要實(shí)現(xiàn)課程目標(biāo)有以下3個(gè):

  • 統(tǒng)一用戶登錄權(quán)限驗(yàn)證
  • 統(tǒng)一數(shù)據(jù)格式
  • 統(tǒng)一異常處理

一、用戶登錄權(quán)限驗(yàn)證

1.1 SpringAOP可以進(jìn)行處理嗎?

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class UserAspect {// 定義切點(diǎn)?法 controller 包下、?孫包下所有類的所有?法@Pointcut("execution(* com.example.demo.controller..*.*(..))")public void pointcut(){ }// 前置?法@Before("pointcut()")public void doBefore(){}// 環(huán)繞?法@Around("pointcut()")public Object doAround(ProceedingJoinPoint joinPoint){Object obj = null;System.out.println("Around ?法開始執(zhí)?");try {// 執(zhí)?攔截?法obj = joinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}System.out.println("Around ?法結(jié)束執(zhí)?");return obj;}
}

我們知道SpringAOP雖然就提供了對用戶登錄的處理邏輯,但是存在一些問題:

  • 沒有辦法獲取HttpSession對象
  • 如果要對一部分方法攔截,一部分方法不攔截,這種情況很難處理。(比如注冊和登錄方法在用戶登錄權(quán)限驗(yàn)證中是不能進(jìn)行攔截的)

攔截器和SpringAOP雖然都是AOP的實(shí)現(xiàn)方式,但是這兩個(gè)其實(shí)是完全不同的技術(shù)體系。

Spring提供了具體的實(shí)現(xiàn)攔截器:HandlerInterceptor,該SpringBoot 攔截器實(shí)現(xiàn)分為以下兩個(gè)步驟:

  1. 自定義攔截器
  2. 將自定義攔截器配置到系統(tǒng)配置項(xiàng),并且設(shè)置合理的攔截規(guī)則

1.2?創(chuàng)建自定義攔截器

自定義攔截器繼承HandlerInterceptor后,需要重寫相對應(yīng)的方法,這里我們重寫 preHandle方法:

?代碼如下:

package com.example.demo.common;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/*** 自定義攔截器*/
public class LoginInterceptor implements HandlerInterceptor {/*** 以下方法是調(diào)用目標(biāo)方法之前執(zhí)行的方法。此方法返回boolean類型的值* 返回true標(biāo)識驗(yàn)證成功,程序會繼續(xù)執(zhí)行后續(xù)流程* 返回false, 表示攔截器攔截失敗, 驗(yàn)證未通過, 后續(xù)的流程和目標(biāo)方法不再執(zhí)行。* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic 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) {// 用戶已經(jīng)登錄return true;}return false;}
}

?1.3?將自定義攔截器配置到系統(tǒng)配置項(xiàng)中

?重寫addInterceptors方法:

?設(shè)置攔截規(guī)則,代碼如下

package com.example.demo.config;import com.example.demo.common.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;public class MyConfig implements WebMvcConfigurer {@AutowiredLoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**") //攔截所有的url.excludePathPatterns("user/login") // url為:user/login 不進(jìn)行攔截 以下同理.excludePathPatterns("user/reg").excludePathPatterns("image/**"); // image夾目錄下的所有url都不進(jìn)行攔截}
}

或者使用Spring方法,通過DI注入的方式,這樣可以實(shí)現(xiàn)不用new一個(gè)實(shí)例:

首先需要將攔截器添加到spring中,也就是給其添加一個(gè)五大類注解,這里我們就使用@Component。接著就可以使用@Autowired來得到實(shí)例。

?其中:

  • addPathPatterns: 表示需要攔截的URL,“**”表示攔截任意方法(也就是所有方法)。
  • excludePathPatterns: 表示需要排除的URL。

?說明:以上攔截規(guī)則可以攔截此項(xiàng)目中的URL,包括靜態(tài)文件(圖片文件,JS和CSS等文件)。

1.4 攔截器的實(shí)現(xiàn)原理

下面我們先來看一組正常情況下的調(diào)用順序:

然而有了攔截器之后,會在調(diào)用Controller之前進(jìn)行相應(yīng)的業(yè)務(wù)處理,執(zhí)行的流程如下圖所示:

1.4.1 實(shí)現(xiàn)原理源碼分析

所有的Controller執(zhí)行都會通過一個(gè)調(diào)度器DispatcherServlet來實(shí)現(xiàn),這一點(diǎn)可以從Spring Boot控制臺的打印信息看出,如下圖所示:

在IDEA中,通過全局搜索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 {processedRequest = this.checkMultipart(request);multipartRequestParsed = processedRequest != request;mappedHandler = this.getHandler(processedRequest);if (mappedHandler == null) {this.noHandlerFound(processedRequest, response);return;}HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());String method = request.getMethod();boolean isGet = HttpMethod.GET.matches(method);if (isGet || HttpMethod.HEAD.matches(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {return;}}if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 實(shí)現(xiàn)Controller的業(yè)務(wù)邏輯mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}this.applyDefaultViewName(processedRequest, mv);mappedHandler.applyPostHandle(processedRequest, response, mv);} catch (Exception var20) {dispatchException = var20;} catch (Throwable var21) {dispatchException = new NestedServletException("Handler dispatch failed", var21);}this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);} catch (Exception var22) {this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);} catch (Throwable var23) {this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));}} finally {if (asyncManager.isConcurrentHandlingStarted()) {if (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}} else if (multipartRequestParsed) {this.cleanupMultipart(processedRequest);}}}

觀察DispatcherServlet中的某段代碼:

我們發(fā)現(xiàn),在執(zhí)行后續(xù)的Controller代碼之前,都會先執(zhí)行這個(gè)applyPreHandle方法,于是鼠標(biāo)雙擊 applyPreHandle,得到代碼如下:

從上述源碼可以看出,在applyPreHandle中會獲取所有的攔截器HandlerInterceptor并執(zhí)行攔截器中的preHandle方法,這樣就和之前定義的攔截器對應(yīng)上了,如下圖所示:

package com.example.demo.common;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
public class LoginInterceptor implements HandlerInterceptor {/*** 以下方法是調(diào)用目標(biāo)方法之前執(zhí)行的方法。此方法返回boolean類型的值* 返回true標(biāo)識驗(yàn)證成功,程序會繼續(xù)執(zhí)行后續(xù)流程* 返回false, 表示攔截器攔截失敗, 驗(yàn)證未通過, 后續(xù)的流程和目標(biāo)方法不再執(zhí)行。* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic 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) {// 用戶已經(jīng)登錄return true;}response.setContentType("application/json");response.setCharacterEncoding("utf8");response.getWriter().println("asdasd");return false;}
}

1.5 統(tǒng)一訪問前綴添加

所有請求地址添加api前綴:

代碼如下:

package com.example.demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class AppConfig implements WebMvcConfigurer {@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {configurer.addPathPrefix("fox", c -> true);}
}

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

2.1 為什么需要使用統(tǒng)一異常處理?

通俗來講,統(tǒng)一異常處理的主要目的是為了方便前端,讓其更好的處理后端的信息,盡量將邏輯處理這塊放置于后端,前端的目的其實(shí)主要是為用戶服務(wù)。

比如:可以跟前端約定出現(xiàn)異常報(bào)錯(cuò)時(shí)候的狀態(tài)碼是多少,這樣方便前端的處理,也方便后續(xù)后端在日志文件中將其找到,并修改異常。

2.2 統(tǒng)一異常處理的實(shí)現(xiàn)

統(tǒng)一異常處理使用的是@ControllerAdvice + @ExceptionHandler 來實(shí)現(xiàn)的,@ControllerAdvice表示控制器通知類, @ExceptionHandler是異常處理器,兩個(gè)結(jié)合表示當(dāng)出現(xiàn)異常的時(shí)候執(zhí)行某個(gè)通知,也就是執(zhí)行某個(gè)方法事件,具體實(shí)現(xiàn)代碼如下:

以上方法表示,如果出現(xiàn)了異常就返回給前端一個(gè)HashMap對象, 其中包含的字段如代碼定義那樣。

?注意:

方法名和返回值都是可以自定義的,另外 @ExceptionHandler()中的參數(shù)是可以選擇的,這里是Exception.class:表示的是可以在程序拋出異常的時(shí)候執(zhí)行這里的代碼,讓其返回?cái)?shù)據(jù)給前端,如果填入的參數(shù)是NullPointerException:那么表示的是當(dāng)程序出現(xiàn)空指針異常的時(shí)候,會執(zhí)行這里的代碼。

這里的實(shí)現(xiàn)邏輯和Java中的異常處理是相似的,如果開發(fā)者有對Exception和NullPointerException分別進(jìn)行了處理,那么當(dāng)程序出現(xiàn)NullPointerException異常的時(shí)候,還是會根據(jù)我們寫的NullPointerException執(zhí)行邏輯進(jìn)行處理,并不會直接走Exception的邏輯。

示例如下:

訪問頁面后效果如下:

總結(jié):當(dāng)有多個(gè)異常通知時(shí),匹配順序?yàn)楫?dāng)前類及其子類向上依次匹配。

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

3.1 為什么需要統(tǒng)一數(shù)據(jù)返回格式?

統(tǒng)一數(shù)據(jù)返回格式的優(yōu)點(diǎn)如下,比如以下幾個(gè):

  • 方便前端程序員更好的接受和解析后端數(shù)據(jù)接口的數(shù)據(jù)
  • 降低前端程序員和后端程序員的溝通成本
  • 有利于項(xiàng)目統(tǒng)一數(shù)據(jù)的維護(hù)和修改
  • 有利于后端技術(shù)部門的統(tǒng)一規(guī)范的標(biāo)準(zhǔn)制定,不會出現(xiàn)稀奇古怪的返回內(nèi)容

3.2 統(tǒng)一數(shù)據(jù)返回格式的實(shí)現(xiàn)

統(tǒng)一的數(shù)據(jù)返回格式可以使用@ControllerAdvice + ResponseBodyAdvice 的方式實(shí)現(xiàn),具體實(shí)現(xiàn)代碼如下:

package com.example.demo.common;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;/*** 統(tǒng)一數(shù)據(jù)格式處理*/
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {/*** 是否執(zhí)行 beforeBodyWrite 方法, 返回 true 就執(zhí)行, 返回 false 就不執(zhí)行* @param returnType* @param converterType* @return*/@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}/*** 返回?cái)?shù)據(jù)之前進(jìn)行數(shù)據(jù)重寫* @param body 原始返回值* @param returnType* @param selectedContentType* @param selectedConverterType* @param request* @param response* @return*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {// 這里我們規(guī)定統(tǒng)一的數(shù)據(jù)返回為HashMapif (body instanceof HashMap) {return body;}// 重寫返回結(jié)果,讓其返回一個(gè)統(tǒng)一的數(shù)據(jù)格式HashMap<String, Object> result = new HashMap<>();result.put("code",200);result.put("data",body);result.put("msg","");return result;}
}

?訪問user/login1:

經(jīng)過統(tǒng)一功能處理后代碼展現(xiàn)如下:

?3.3 返回值為String類型時(shí),應(yīng)該如何處理?

?但是如果將返回值改為String類型,按照以上的執(zhí)行邏輯,那么就無法走上述的正常數(shù)據(jù)統(tǒng)一處理:

我們發(fā)現(xiàn),當(dāng)返回類型為String的時(shí)候,程序會拋出異常,從而被我們的 統(tǒng)一異常處理模塊攔截。

觀察異常信息,發(fā)現(xiàn) 拋出異常:java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.String

可能會感到奇怪,為什么會拋出這個(gè)異常呢?

下面我們來看看后端返回前端時(shí)候的執(zhí)行流程:

1.? 一開始,前端訪問該網(wǎng)址時(shí),方法返回的是 String:

2. 統(tǒng)一數(shù)據(jù)返回之前會進(jìn)行處理,將 String 轉(zhuǎn)換為 HashMap:

3. 將HaspMap轉(zhuǎn)換成 application/json 字符串給前端(接口)

這個(gè)步驟有兩種情況,先判斷原Body的類型:

  • 是 String 類型,那么就會使用 StringHttpMessageConverter 進(jìn)行類型轉(zhuǎn)換
  • 如果不是 String 類型,那么使用 HttpMessageConverter 進(jìn)行類型轉(zhuǎn)換

以上報(bào)錯(cuò)就是因?yàn)樵糂ody是String類型,所以在類型轉(zhuǎn)換時(shí)候報(bào)錯(cuò)了

解決方案有如下兩種:

  • 將 StringHttpMessageConverter 去掉。
  • 在統(tǒng)一數(shù)據(jù)返回的時(shí)候,單獨(dú)處理String類型,讓其返回一個(gè)String字符串,而非HashMap

3.3.1 將 StringHttpMessageConverter 去掉。

在配置文件中使用以下代碼即可;

package com.example.demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;@Configuration
public class MyConfig implements WebMvcConfigurer {/*** 移除 StringHttpMessageConverter* @param converters*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.removeIf(converter -> converter instanceof StringHttpMessageConverter);}
}

?訪問地址后顯示如下:

3.3.2 在統(tǒng)一數(shù)據(jù)返回的時(shí)候,單獨(dú)處理String類型,讓其返回一個(gè)String字符串,而非 HashMap

引入ObjectMapper(ObjectMapper?是Jackson庫中的一個(gè)類,用于在Java對象(POJO,Plain Old Java Objects)和JSON數(shù)據(jù)之間進(jìn)行相互轉(zhuǎn)換):

對Body為String進(jìn)行單獨(dú)處理:?

訪問頁面如下所示:

?總結(jié):

本文主要介紹了統(tǒng)一用戶登錄權(quán)限的效驗(yàn),使用WebMvcConfigurer + HandlerInterceptor 來實(shí)現(xiàn)。統(tǒng)一異常處理使用 @ControllerAdvice + @ExceptionHandler 來實(shí)現(xiàn),統(tǒng)一返回值處理使用@ControllerAdvice + ResponseBodyAdvice來處理。

http://m.aloenet.com.cn/news/29869.html

相關(guān)文章:

  • ftp是專門提供文件傳輸?shù)木W(wǎng)站百度注冊新賬號
  • 品牌seo公司焦作關(guān)鍵詞優(yōu)化排名
  • 建網(wǎng)站的服務(wù)器學(xué)電商出來一般干什么工作
  • 創(chuàng)意個(gè)人網(wǎng)站設(shè)計(jì)大冶seo網(wǎng)站優(yōu)化排名推薦
  • 律師網(wǎng)站深圳網(wǎng)站設(shè)計(jì)百度app在哪里找
  • 黔東南網(wǎng)頁設(shè)計(jì)seo搜索引擎優(yōu)化人員
  • wordpress掃碼收款seo網(wǎng)絡(luò)營銷課程
  • 公司做的網(wǎng)站賬務(wù)處理淘寶關(guān)鍵詞搜索量查詢
  • 開發(fā)公司人效比seo排名培訓(xùn)學(xué)校
  • 做網(wǎng)站彩票代理犯法嗎我是站長網(wǎng)
  • php做網(wǎng)站網(wǎng)絡(luò)營銷有什么崗位
  • 國內(nèi)可以做的國外兼職網(wǎng)站海外營銷方案
  • 專門做微信推送的網(wǎng)站搜索引擎優(yōu)化要考慮哪些方面?
  • 海北高端網(wǎng)站建設(shè)哪家好網(wǎng)站推廣途徑和推廣要點(diǎn)
  • 網(wǎng)站建設(shè)方案書深圳關(guān)鍵詞推廣優(yōu)化
  • 東營本地網(wǎng)站制作公司可以入侵的網(wǎng)站
  • 公司網(wǎng)站維護(hù)該誰來做全網(wǎng)營銷外包
  • java可以做微信網(wǎng)站么站長統(tǒng)計(jì)工具
  • 做域名后就得做網(wǎng)站嗎河北高端網(wǎng)站建設(shè)
  • 網(wǎng)站title是什么培訓(xùn)機(jī)構(gòu)加盟店排行榜
  • 網(wǎng)站備案 取名資訊通不過外貿(mào)網(wǎng)站推廣費(fèi)用
  • 去除wordpress相冊系統(tǒng)優(yōu)化工具
  • 做網(wǎng)站的回扣什么是seo?
  • 蘇州做門戶網(wǎng)站的公司公司網(wǎng)站怎么優(yōu)化
  • 中國建設(shè)銀行移動門戶網(wǎng)站百度推廣客戶端app
  • 阿里巴巴網(wǎng)站做推廣效果怎么樣如何制作一個(gè)網(wǎng)址
  • 重慶福彩建站2022新聞熱點(diǎn)10條
  • 怎么把網(wǎng)站做火seo入門培訓(xùn)課程
  • 泰國做彩票網(wǎng)站企業(yè)網(wǎng)站營銷的實(shí)現(xiàn)方式
  • 大數(shù)據(jù)技術(shù)建設(shè)網(wǎng)站百度地圖人工電話