中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

網(wǎng)站開發(fā)主管待遇優(yōu)化大師安卓版

網(wǎng)站開發(fā)主管待遇,優(yōu)化大師安卓版,三網(wǎng)合一網(wǎng)站建設合同,建設人才網(wǎng)證書查詢一、用戶登錄權限效驗 用戶登錄權限的發(fā)展從之前每個方法中自己驗證用戶登錄權限,到現(xiàn)在統(tǒng)一的用戶登錄驗證處理,它是一個逐漸完善和逐漸優(yōu)化的過程。 1.1 最初用戶登錄驗證 我們先來回顧一下最初用戶登錄驗證的實現(xiàn)方法: RestController…

一、用戶登錄權限效驗

用戶登錄權限的發(fā)展從之前每個方法中自己驗證用戶登錄權限,到現(xiàn)在統(tǒng)一的用戶登錄驗證處理,它是一個逐漸完善和逐漸優(yōu)化的過程。

1.1 最初用戶登錄驗證

我們先來回顧一下最初用戶登錄驗證的實現(xiàn)方法:
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 某方法 1
*/
@RequestMapping("/m1")
public Object method(HttpServletRequest request) {
// 有 session 就獲取,沒有不會創(chuàng)建
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("userinfo") != null) {
// 說明已經(jīng)登錄,業(yè)務處理
return true;
} else {
// 未登錄
return false;
}
}
/**
* 某方法 2
*/
@RequestMapping("/m2")
public Object method2(HttpServletRequest request) {
// 有 session 就獲取,沒有不會創(chuàng)建
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("userinfo") != null) {
// 說明已經(jīng)登錄,業(yè)務處理
return true;
} else {
// 未登錄
return false;
}
}
// 其他方法...
}
從上述代碼可以看出,每個方法中都有相同的用戶登錄驗證權限,它的缺點是:
  1. 每個方法中都要單獨寫用戶登錄驗證的方法,即使封裝成公共方法,也一樣要傳參調(diào)用和在方法中進行判斷。
  2. 添加控制器越多,調(diào)用用戶登錄驗證的方法也越多,這樣就增加了后期的修改成本和維護成本。
  3. 這些用戶登錄驗證的方法和接下來要實現(xiàn)的業(yè)務幾何沒有任何關聯(lián),但每個方法中都要寫一遍。
?所以提供一個公共的 AOP 方法來進行統(tǒng)一的用戶登錄權限驗證迫在眉睫。

1.2 Spring AOP 用戶統(tǒng)一登錄驗證的問題

說到統(tǒng)一的用戶登錄驗證,我們想到的第一個實現(xiàn)方案是 Spring AOP 前置通知或環(huán)繞通知來實現(xiàn),具 體實現(xiàn)代碼如下:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class UserAspect {
// 定義切點方法 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 方法結束執(zhí)行");
return obj;
}
}
如果要在以上 Spring AOP 的切面中實現(xiàn)用戶登錄權限效驗的功能,有以下兩個問題:
1. 沒辦法獲取到 HttpSession 對象。
2. 我們要對一部分方法進行攔截,而另一部分方法不攔截,如注冊方法和登錄方法是不攔截的,這樣的話排除方法的規(guī)則很難定義,甚至沒辦法定義。
那這樣如何解決呢?

1.3 Spring 攔截器

對于以上問題 Spring 中提供了具體的實現(xiàn)攔截器: HandlerInterceptor ,攔截器的實現(xiàn)分為以下兩個步驟:
1. 創(chuàng)建自定義攔截器,實現(xiàn) HandlerInterceptor 接口的 preHandle (執(zhí)行具體方法之前的預處理)方法。
2. 將自定義攔截器加入 WebMvcConfigurer addInterceptors 方法中。

1.3.1 自定義攔截器

接下來使用代碼來實現(xiàn)一個用戶登錄的權限效驗,自定義攔截器是一個普通類,具體實現(xiàn)代碼如下:
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 {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("userinfo") != null) {
return true;
}
response.setStatus(401);
return false;
}
}

1.3.2 將自定義攔截器加入到系統(tǒng)配置

將上一步中的自定義攔截器加入到系統(tǒng)配置信息中,具體實現(xiàn)代碼如下:
@Configuration
public class AppConfig implements WebMvcConfigurer {
// 添加攔截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 攔截所有接口
.excludePathPatterns("/art/param11"); // 排除接口
}
}
其中:
addPathPatterns 表示需要攔截的 URL “**” 表示攔截任意方法(也就是所有方法)。
excludePathPatterns 表示需要排除的 URL 。
說明:以上攔截規(guī)則可以攔截此項目中的使用 URL ,包括靜態(tài)文件(圖片文件、 JS CSS 等文件)。

排除所有的靜態(tài)資源

// 攔截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 攔截所有接口
.excludePathPatterns("/**/*.js")
.excludePathPatterns("/**/*.css")
.excludePathPatterns("/**/*.jpg")
.excludePathPatterns("/login.html")
.excludePathPatterns("/**/login"); // 排除接口
}

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

正常情況下的調(diào)用順序:

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

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

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

而所有方法都會執(zhí)行 DispatcherServlet 中的 doDispatch 調(diào)度方法,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;
}
}
// 調(diào)用預處理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 執(zhí)行 Controller 中的業(yè)務
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);
}
}
}
從上述源碼可以看出在開始執(zhí)行 Controller 之前,會先調(diào)用 預處理方法 applyPreHandle ,而
applyPreHandle 方法的實現(xiàn)源碼如下:
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response)
throws Exception {
for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++)
{
// 獲取項目中使用的攔截器 HandlerInterceptor
HandlerInterceptor interceptor =
(HandlerInterceptor)this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
return true;
}
從上述源碼可以看出,在 applyPreHandle 中會獲取所有的攔截器 HandlerInterceptor 并執(zhí)行攔截器中的 preHandle 方法,這樣就會咱們前面定義的攔截器對應上了,如下圖所示:

?

此時用戶登錄權限的驗證方法就會執(zhí)行,這就是攔截器的實現(xiàn)原理。

1.4.2 攔截器小結

通過上面的源碼分析,我們可以看出, Spring 中的攔截器也是通過動態(tài)代理和環(huán)繞通知的思想實現(xiàn)的,大體的調(diào)用流程如下:

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

所有請求地址添加 api 前綴:
@Configuration
public class AppConfig implements WebMvcConfigurer {
// 所有的接口添加 api 前綴
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("api", c -> true);
}
}
其中第二個參數(shù)是一個表達式,設置為 true 表示啟動前綴。

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

統(tǒng)一異常處理使用的是 @ControllerAdvice + @ExceptionHandler 來實現(xiàn)的, @ControllerAdvice 表示控制器通知類,@ExceptionHandler 是異常處理器,兩個結合表示當出現(xiàn)異常的時候執(zhí)行某個通知,也就是執(zhí)行某個方法事件,具體實現(xiàn)代碼如下:
import java.util.HashMap;
@ControllerAdvice
public class ErrorAdive {
@ExceptionHandler(Exception.class)
@ResponseBody
public Object handler(Exception e) {
HashMap<String, Object> map = new HashMap<>();
map.put("success", 0);
map.put("status", 1);
map.put("msg", e.getMessage());
return map;
}
}
PS :方法名和返回值可以自定義,其中最重要的是 @ExceptionHandler(Exception.class) 注解。
以上方法表示,如果出現(xiàn)了異常就返回給前端一個 HashMap 的對象,其中包含的字段如代碼中定義的那樣。
我們可以針對不同的異常,返回不同的結果,比以下代碼所示:
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;
@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {
@ExceptionHandler(Exception.class)
public Object exceptionAdvice(Exception e) {
HashMap<String, Object> result = new HashMap<>();
result.put("success", -1);
result.put("message", "總的異常信息:" + e.getMessage());
result.put("data", null);
return result;
}
@ExceptionHandler(NullPointerException.class)
public Object nullPointerexceptionAdvice(NullPointerException e) {
HashMap<String, Object> result = new HashMap<>();
result.put("success", -1);
result.put("message", "空指針異常:" + e.getMessage());
result.put("data", null);
return result;
}
}
當有多個異常通知時,匹配順序為當前類及其子類向上依次匹配,案例演示。
UserController 中設置一個空指針異常,實現(xiàn)代碼如下:
@RestController
@RequestMapping("/u")
public class UserController {
@RequestMapping("/index")
public String index() {
Object obj = null;
int i = obj.hashCode();
return "Hello,User Index.";
}
}
以上程序的執(zhí)行結果如下:

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

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

統(tǒng)一數(shù)據(jù)返回格式的優(yōu)點有很多,比如以下幾個:
1. 方便前端程序員更好的接收和解析后端數(shù)據(jù)接口返回的數(shù)據(jù)。
2. 降低前端程序員和后端程序員的溝通成本,按照某個格式實現(xiàn)就行了,因為所有接口都是這樣返回的。
3. 有利于項目統(tǒng)一數(shù)據(jù)的維護和修改。
4. 有利于后端技術部門的統(tǒng)一規(guī)范的標準制定,不會出現(xiàn)稀奇古怪的返回內(nèi)容。

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

統(tǒng)一的數(shù)據(jù)返回格式可以使用 @ControllerAdvice + ResponseBodyAdvice 的方式實現(xiàn),具體實現(xiàn)代碼如下:
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;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
/**
* 內(nèi)容是否需要重寫(通過此方法可以選擇性部分控制器和方法進行重寫)
* 返回 true 表示重寫
*/
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
/**
* 方法返回之前調(diào)用此方法
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType,
Class selectedConverterType, ServerHttpRequest
request,
ServerHttpResponse response) {
// 構造統(tǒng)一返回對象
HashMap<String, Object> result = new HashMap<>();
result.put("success", 1);
result.put("message", "");
result.put("data", body);
return result;
}
}

3.3 @ControllerAdvice 源碼分析

通過對 @ControllerAdvice 源碼的分析我們可以知道上面統(tǒng)一異常和統(tǒng)一數(shù)據(jù)返回的執(zhí)行流程,我們先從 @ControllerAdvice 的源碼看起,點擊 @ControllerAdvice 實現(xiàn)源碼如下:
從上述源碼可以看出 @ControllerAdvice 派生于 @Component 組件,而所有組件初始化都會調(diào)用
InitializingBean 接口。
所以接下來我們來看 InitializingBean 有哪些實現(xiàn)類?在查詢的過程中我們發(fā)現(xiàn)了,其中 Spring MVC 中的實現(xiàn)子類是 RequestMappingHandlerAdapter ,它里面有一個方法 afterPropertiesSet() 方法,表示所有的參數(shù)設置完成之后執(zhí)行的方法,如下圖所示:

而這個方法中有一個 initControllerAdviceCache 方法,查詢此方法的源碼如下:

總結

本篇博客介紹了

  • 統(tǒng)一用戶登錄權限的效驗使用 WebMvcConfigurer+ HandlerInterceptor來實現(xiàn)
  • 統(tǒng)一異常 處理使用 @ControllerAdvice + @ExceptionHandler 來實現(xiàn)
  • 統(tǒng)一返回值處理使用 @ControllerAdvice + ResponseBodyAdvice 來處理。

http://www.risenshineclean.com/news/63905.html

相關文章:

  • 建正建設官方網(wǎng)站友情鏈接有什么用
  • 湖南做網(wǎng)站問磐石網(wǎng)絡專業(yè)鞏義網(wǎng)絡推廣外包
  • 宿州做企業(yè)網(wǎng)站學生制作個人網(wǎng)站
  • 重慶網(wǎng)絡公司網(wǎng)站建設查詢網(wǎng) 域名查詢
  • 成都建筑設計公司排名前十雞西seo
  • 做視頻網(wǎng)站的條件抖音seo推廣
  • 網(wǎng)站建設 軟件開發(fā)站長之家統(tǒng)計
  • 亞成成品網(wǎng)站源碼今天的新聞發(fā)布會
  • 劉淼 網(wǎng)站開發(fā)2022年最新最有效的營銷模式
  • 網(wǎng)站降權處理鏈接制作軟件
  • 一站式做網(wǎng)站技術鄭州網(wǎng)絡優(yōu)化實力樂云seo
  • 優(yōu)秀網(wǎng)站案例泰安百度公司代理商
  • 淘寶客做網(wǎng)站推廣賺錢嗎福州seo兼職
  • 南寧網(wǎng)站建設推廣優(yōu)化外貿(mào)營銷型網(wǎng)站設計
  • 做網(wǎng)站收費標準惠州百度關鍵詞優(yōu)化
  • 北京網(wǎng)站建設公司現(xiàn)狀網(wǎng)頁開發(fā)需要學什么
  • c 做網(wǎng)站設計關鍵詞優(yōu)化多少錢
  • 深圳網(wǎng)站建設營銷服務平臺濟南做seo排名
  • 獨立站建設哪家好沒經(jīng)驗怎么開廣告公司
  • 網(wǎng)站資源做外鏈seo教程搜索引擎優(yōu)化入門與進階
  • 破破網(wǎng)站開發(fā)廣告推廣方案
  • wordpress自動切換手機主題做網(wǎng)絡優(yōu)化的公司排名
  • 中山視角做網(wǎng)站的公司汽車網(wǎng)站建設
  • 網(wǎng)站建設背景需要寫些什么軟件如何設計網(wǎng)站
  • 違規(guī)網(wǎng)站開發(fā) 開發(fā)者如何規(guī)避風險網(wǎng)絡營銷的營銷策略
  • 對網(wǎng)站建設在電子商務中的看法如何創(chuàng)建一個屬于自己的網(wǎng)站
  • 萬江做網(wǎng)站百度搜索引擎優(yōu)化的推廣計劃
  • 網(wǎng)站建設技術經(jīng)理崗位職責別做網(wǎng)絡推廣員
  • 醫(yī)院網(wǎng)站建設ppt新手怎么引流推廣
  • 濟南網(wǎng)站制作工作室蘭州seo公司