日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Spring @CrossOrigin 注解原理實現

瀏覽:106日期:2023-08-28 16:39:50

現實開發中,我們難免遇到跨域問題,以前筆者只知道jsonp這種解決方式,后面聽說spring只要加入@CrossOrigin即可解決跨域問題。本著好奇的心里,筆者看了下@CrossOrigin 作用原理,寫下這篇博客。

先說原理:其實很簡單,就是利用spring的攔截器實現往response里添加 Access-Control-Allow-Origin等響應頭信息,我們可以看下spring是怎么做的

注:這里使用的spring版本為5.0.6

我們可以先往RequestMappingHandlerMapping 的initCorsConfiguration方法打一個斷點,發現方法調用情況如下

Spring @CrossOrigin 注解原理實現

如果controller在類上標了@CrossOrigin或在方法上標了@CrossOrigin注解,則spring 在記錄mapper映射時會記錄對應跨域請求映射,代碼如下

RequestMappingHandlerMappingprotected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) { HandlerMethod handlerMethod = createHandlerMethod(handler, method); Class<?> beanType = handlerMethod.getBeanType(); //獲取handler上的CrossOrigin 注解 CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class); //獲取handler 方法上的CrossOrigin 注解 CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class); if (typeAnnotation == null && methodAnnotation == null) { //如果類上和方法都沒標CrossOrigin 注解,則返回一個null return null; } //構建一個CorsConfiguration 并返回 CorsConfiguration config = new CorsConfiguration(); updateCorsConfig(config, typeAnnotation); updateCorsConfig(config, methodAnnotation); if (CollectionUtils.isEmpty(config.getAllowedMethods())) { for (RequestMethod allowedMethod : mappingInfo.getMethodsCondition().getMethods()) { config.addAllowedMethod(allowedMethod.name()); } } return config.applyPermitDefaultValues(); }

將結果返回到了AbstractHandlerMethodMapping#register,主要代碼如下

CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) {//會保存handlerMethod處理跨域請求的配置 this.corsLookup.put(handlerMethod, corsConfig); }

當一個跨域請求過來時,spring在獲取handler時會判斷這個請求是否是一個跨域請求,如果是,則會返回一個可以處理跨域的handler

AbstractHandlerMapping#getHandler HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); //如果是一個跨域請求if (CorsUtils.isCorsRequest(request)) { //拿到跨域的全局配置 CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); //拿到hander的跨域配置 CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); //處理跨域(即往響應頭添加Access-Control-Allow-Origin信息等),并返回對應的handler對象 executionChain = getCorsHandlerExecutionChain(request, executionChain, config); }

我們可以看下如何判定一個請求是一個跨域請求,

public static boolean isCorsRequest(HttpServletRequest request) {//判定請求頭是否有Origin 屬性即可 return (request.getHeader(HttpHeaders.ORIGIN) != null); }

再看下getCorsHandlerExecutionChain 是如何獲取一個handler

protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, HandlerExecutionChain chain, @Nullable CorsConfiguration config) { if (CorsUtils.isPreFlightRequest(request)) { HandlerInterceptor[] interceptors = chain.getInterceptors(); chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors); } else { //只是給執行器鏈添加了一個攔截器 chain.addInterceptor(new CorsInterceptor(config)); } return chain; }

也就是在調用目標方法前會先調用CorsInterceptor#preHandle,我們觀察得到其也是調用了corsProcessor.processRequest方法,我們往這里打個斷點

processRequest方法的主要邏輯如下

public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request, HttpServletResponse response) throws IOException { //.... //調用了自身的handleInternal方法 return handleInternal(serverRequest, serverResponse, config, preFlightRequest); }protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response, CorsConfiguration config, boolean preFlightRequest) throws IOException { String requestOrigin = request.getHeaders().getOrigin(); String allowOrigin = checkOrigin(config, requestOrigin); HttpHeaders responseHeaders = response.getHeaders(); responseHeaders.addAll(HttpHeaders.VARY, Arrays.asList(HttpHeaders.ORIGIN, HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS)); if (allowOrigin == null) { logger.debug('Rejecting CORS request because ’' + requestOrigin + '’ origin is not allowed'); rejectRequest(response); return false; } HttpMethod requestMethod = getMethodToUse(request, preFlightRequest); List<HttpMethod> allowMethods = checkMethods(config, requestMethod); if (allowMethods == null) { logger.debug('Rejecting CORS request because ’' + requestMethod + '’ request method is not allowed'); rejectRequest(response); return false; } List<String> requestHeaders = getHeadersToUse(request, preFlightRequest); List<String> allowHeaders = checkHeaders(config, requestHeaders); if (preFlightRequest && allowHeaders == null) { logger.debug('Rejecting CORS request because ’' + requestHeaders + '’ request headers are not allowed'); rejectRequest(response); return false; } //設置響應頭 responseHeaders.setAccessControlAllowOrigin(allowOrigin); if (preFlightRequest) { responseHeaders.setAccessControlAllowMethods(allowMethods); } if (preFlightRequest && !allowHeaders.isEmpty()) { responseHeaders.setAccessControlAllowHeaders(allowHeaders); } if (!CollectionUtils.isEmpty(config.getExposedHeaders())) { responseHeaders.setAccessControlExposeHeaders(config.getExposedHeaders()); } if (Boolean.TRUE.equals(config.getAllowCredentials())) { responseHeaders.setAccessControlAllowCredentials(true); } if (preFlightRequest && config.getMaxAge() != null) { responseHeaders.setAccessControlMaxAge(config.getMaxAge()); } //刷新 response.flush(); return true; }

至此@CrossOrigin的使命就完成了,說白了就是用攔截器給response添加響應頭信息而已

到此這篇關于Spring @CrossOrigin 注解原理實現的文章就介紹到這了,更多相關Spring @CrossOrigin 注解內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲男人在线| 久久精品国产精品亚洲毛片| 欧美久久久网站| 日欧美一区二区| 免费一级片91| 日韩成人午夜精品| 国产精品多人| 国际精品欧美精品| 日韩不卡免费高清视频| 久久精品播放| av亚洲一区二区三区| 久久久夜精品| 国产精品女主播一区二区三区| 视频在线观看一区| 午夜精品影视国产一区在线麻豆| 男人的天堂亚洲一区| 色狠狠一区二区三区| 麻豆久久一区二区| 中文字幕系列一区| 日韩精品一二区| 日本91福利区| 国产 日韩 欧美一区| 男人操女人的视频在线观看欧美| 国产精品久久久免费| 久久国产亚洲精品| 蜜芽一区二区三区| 狠狠久久伊人中文字幕| 欧美日韩国产高清电影| 久久亚洲二区| 亚洲成人国产| 国产精品久久久久久久免费观看| 美女精品在线| 日韩1区2区| 日韩精品免费视频人成| 青青久久av| 欧美日韩1区| 在线精品视频一区| 91亚洲国产| 日韩激情中文字幕| 亚洲伊人影院| 欧美一级精品| 久久精品亚洲一区二区| 日韩av在线免费观看不卡| 国产精品视频一区视频二区| 免费日本视频一区| 99亚洲视频| 亚洲夜间福利| 999久久久91| 中文字幕在线高清| 蜜臀va亚洲va欧美va天堂| 色偷偷色偷偷色偷偷在线视频| 国产精品一区二区精品| 国产亚洲精品美女久久| 亚洲免费成人av在线| 好看不卡的中文字幕| 三级精品视频| 欧美日韩国产探花| 最新日韩av| 日韩电影免费在线观看| 999精品一区| 99精品综合| 欧美日韩视频免费观看| 成人羞羞视频播放网站| 亚洲一级网站| 久久九九99| 亚洲天堂黄色| 日韩精品一区第一页| 久久福利影视| 日本aⅴ免费视频一区二区三区| 亚洲精选91| 欧美精品中文| 精品国产精品久久一区免费式| 精品欧美日韩精品| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 国产精品.xx视频.xxtv| 国产日韩一区| 国产精品久久观看| 合欧美一区二区三区| 日韩精品亚洲一区二区三区免费| 美女性感视频久久| 国产精品二区不卡| 国精品一区二区三区| 国产精品99在线观看| 99久久99久久精品国产片果冰| 久久都是精品| 久久99国产精品视频| 欧美日韩一区二区综合| 天使萌一区二区三区免费观看| 国产精品调教视频| 亚洲国产不卡| 日本精品另类| 国产日韩欧美一区二区三区| 久久精品国产亚洲aⅴ | av资源亚洲| 日韩高清一区在线| 国产精品最新| 999视频精品| 另类综合日韩欧美亚洲| 欧美日韩国产在线观看网站| 日本亚洲最大的色成网站www| 精品国产91| 日韩国产在线观看| 秋霞国产精品| 成年男女免费视频网站不卡| 亚洲一区二区三区四区电影| 日韩免费视频| 国产精品丝袜在线播放| 四虎4545www国产精品| 国产精品探花在线观看| 日韩精品一区二区三区免费视频| 精品理论电影在线| 亚洲深深色噜噜狠狠爱网站| 欧美 日韩 国产精品免费观看| 久久精品人人| 国产精品主播| 国产偷自视频区视频一区二区| 麻豆精品久久| 日韩三级精品| 9色国产精品| 在线一区免费观看| 久久国产麻豆精品| 日韩av中文在线观看| 蜜桃视频一区二区三区在线观看| 999精品在线| 激情黄产视频在线免费观看| 夜夜嗨av一区二区三区网站四季av| 久久只有精品| 久久av免费看| 97精品视频在线看| www.51av欧美视频| 免费精品一区| 国产在线观看91一区二区三区| 久久香蕉网站| 91中文字幕精品永久在线| 92国产精品| 日韩一区二区三区在线免费观看| 国产一区二区三区久久| 日本久久黄色| 日韩在线免费| 麻豆成人在线| 性一交一乱一区二区洋洋av| 亚洲一区二区三区高清| 亚洲精品进入| 国产精品高清一区二区| 国产精品久久久久久久久久妞妞| 精品中文字幕一区二区三区四区| 国产aⅴ精品一区二区三区久久| 精品国产亚洲一区二区三区大结局| 91成人精品在线| 首页国产精品| 日韩视频二区| 亚洲精品女人| 国产欧美自拍| 吉吉日韩欧美| 色8久久久久| 国产欧美日韩免费观看| 久久久成人网| 久久国内精品自在自线400部| 成人国产精品久久| 六月天综合网| 国产精品激情电影| 欧美午夜精品一区二区三区电影| 日韩亚洲在线| а√天堂8资源中文在线| 久热精品在线| 国产精品一区二区精品视频观看 | 国产精品亚洲一区二区三区在线观看| 欧美日中文字幕| 亚洲精品黄色| 久久国产精品成人免费观看的软件| 国产视频一区二| 99视频一区| 日韩成人a**站| 777久久精品| 久久精品91| 日韩精品dvd| 伊人精品久久| 久久精品影视| 欧美激情麻豆| 日韩**一区毛片| 欧美精选视频一区二区| 国产欧美日韩精品一区二区免费 | 国产午夜久久| 国产日韩高清一区二区三区在线 | 国产精品videossex久久发布| 亚洲精品一区三区三区在线观看| 国产激情久久| 五月激激激综合网色播| 黄色日韩在线| 国产毛片一区| 香蕉视频成人在线观看| 国产成人精品亚洲日本在线观看| 麻豆精品视频在线| 日本三级亚洲精品| 亚洲一二三区视频| 亚洲精品乱码| 日韩中文欧美在线| 男女性色大片免费观看一区二区| 久久中文字幕av| 久久亚洲在线|