最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實(shí)現(xiàn)后端跨域的常見解決方案

 更新時間:2024年04月01日 10:55:16   作者:嘉禾嘉寧papa  
跨源資源共享(CORS——Cross-Origin Resource Sharing,跨源資源共享,或通俗地譯為跨域資源共享)是一種基于 HTTP 頭的機(jī)制,跨域的解決方案有很多種,前后端都有,本文給大家主要介紹Java實(shí)現(xiàn)后端跨域的常見解決方案,需要的朋友可以參考下

一、搭建服務(wù)(cross-server)

1.1、maven依賴

pom.xml

<dependencies>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>

   <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <version>1.16.14</version>
   </dependency>
</dependencies>

1.2、接口

@Slf4j
@RestController
@RequestMapping("/cross")
public class CrossController {

    @PostMapping("/request")
    public String crossRequest(HttpServletRequest request) {
        log.info("接收到跨域請求參數(shù):{}",request.getParameter("name"));
        return "Request CrossServer Success";
    }

}

1.3、配置

application.properties

server.port=8080
server.servlet.context-path=/crossServer

至此我們就提供了一個接口:http://localhost:8080/crossServer/cross/request

二、搭建服務(wù)(cross-web)

2.1、maven依賴

pom.xml

<dependencies>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>

   <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <version>1.16.14</version>
   </dependency>
</dependencies>

2.2、接口

@Controller
@RequestMapping("/test")
public class WebController {

    @RequestMapping(value = "/request")
    public String request(HttpServletRequest request) {
        return "/cross";
    }
}

2.3、頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>跨域測試頁面</title>
    <script src="js/jquery.min.js"></script>
</head>
<body>
<h1>跨域測試</h1>
<div>
    <input type="button" onclick="mySubmit()" value=" 發(fā)送跨域請求 ">
</div>
<script>
    function mySubmit() {
        // 發(fā)送跨域請求
        jQuery.ajax({
            url: "http://localhost:8086/test",
            type: "POST",
            data: {"name": "Java"},
            success: function (result) {
                alert("返回?cái)?shù)據(jù):" + result.data);
            }
        });
    }
</script>
</body>
</html>

2.4、配置

application.properties

server.port=8081
server.servlet.context-path=/crossWeb

spring.freemarker.request-context-attribute=request
spring.freemarker.charset=UTF-8
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.prefix=/views

至此我們就提供了一個接口:http://localhost:8081/crossWeb/test/request,訪問此頁面可以打開如下測試頁面:

2.5、跨域請求結(jié)果

在沒有任何跨域處理的情況下,我們點(diǎn)擊按鈕,發(fā)起請求,得到結(jié)果如下:

Access to XMLHttpRequest at 'http://localhost:8080/crossServer/cross/request' from origin 
'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' 
header is present on the requested resource.
POST http://localhost:8080/crossServer/cross/request net::ERR_FAILED 200

2.6、常見跨域情況

請求地址說明是否跨域
http://www.alian.com/a
http://www.alian.com/b
同域名
http://www.alian.com/a/b
http://www.alian.com/c/d
同域名不同文件夾
http://www.alian.com/a
https://www.alian.com/a
同域名不同協(xié)議
http://www.alian.com/a
http://www.alian.com:8080/a
同域名下不同端口
http://www.alian.com/a
http://yun.alian.com/a
同頂級域名不同二級域名
http://www.alian.com/a
http://www.yang.com/a
不同域名
http://www.alian.com/a
http://10.130.1.88:80/a
域名和對應(yīng)的ip

三、解決方案

3.1、通過 @CrossOrigin 注解

最簡單的方式是通過使用注解@CrossOrigin,但是需要注意的是這個注解版本,這個注解是從Spring Framework 4.2 GA開始有的。如果你項(xiàng)目的版本低于這個版本是用不了的。

package com.alian.crossserver.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@RestController
@RequestMapping("/cross")
public class CrossController {

    @CrossOrigin(origins = "*")
    @PostMapping("/request")
    public String crossRequest(HttpServletRequest request) {
        log.info("接收到跨域請求參數(shù):{}",request.getParameter("name"));
        return "Request CrossServer Success";
    }

}

3.2、通過配置類

為了避免方法間相互影響,我們先在我們的方法crossRequest,去除注解@CrossOrigin(origins = “*”),后面也是一樣就不一一提示了。

package com.alian.crossserver.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 所有接口
                .allowCredentials(true) // 是否發(fā)送 Cookie
                .allowedOriginPatterns("*") // 支持域
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 支持方法
                .allowedHeaders("*")
                .exposedHeaders("*");

    }
}

上面是對全部方法都支持跨域,我們也可以指定某個請求支持跨域,如下:

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/cross/request") // 指定接口
                .allowCredentials(true) // 是否發(fā)送 Cookie
                .allowedOriginPatterns("*") // 支持域
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 支持方法
                .allowedHeaders("*")
                .exposedHeaders("*");

    }
}

3.3、通過 CorsFilter 對象

再沒有使用以上方式解決跨域的情況下,我們使用過濾器也可以實(shí)現(xiàn)。

package com.alian.crossserver.filter;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CustomCorsFilter {

    @Bean
    public CorsFilter corsFilter() {
        // 創(chuàng)建cors配置對象
        CorsConfiguration config = new CorsConfiguration();
        // 支持域
        config.addAllowedOriginPattern("*");
        // 是否發(fā)送 Cookie
        config.setAllowCredentials(true);
        // 支持請求方式
        config.addAllowedMethod("*");
        // 允許的原始請求頭部信息
        config.addAllowedHeader("*");
        // 暴露的頭部信息
        config.addExposedHeader("*");
        // 添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 返回 CorsFilter 對象
        return new CorsFilter(corsConfigurationSource);
    }
}

上面是對所有域名請求都支持跨域,我們也可以指定某個域名,意思就是只有指定域名可以跨域請求。比如:我們只允許http://localhost:8081的跨域請求。

@Configuration
public class CustomCorsFilter {

    @Bean
    public CorsFilter corsFilter() {
        // 創(chuàng)建cors配置對象
        CorsConfiguration config = new CorsConfiguration();
        // 支持指定域
        config.addAllowedOriginPattern("http://localhost:8081");
        // 是否發(fā)送 Cookie
        config.setAllowCredentials(true);
        // 支持請求方式
        config.addAllowedMethod("*");
        // 允許的原始請求頭部信息
        config.addAllowedHeader("*");
        // 暴露的頭部信息
        config.addExposedHeader("*");
        // 添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 返回 CorsFilter 對象
        return new CorsFilter(corsConfigurationSource);
    }
}

3.4、通過 Response 對象

在沒有使用以上方式解決跨域的情況下,我們通過Response對象也可以實(shí)現(xiàn)跨域。

@Slf4j
@RestController
@RequestMapping("/cross")
public class CrossController {

    @PostMapping("/request")
    public String crossRequest(HttpServletRequest request, HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        log.info("接收到跨域請求參數(shù):{}",request.getParameter("name"));
        return "Request CrossServer Success";
    }

}

3.5、通過實(shí)現(xiàn) ResponseBodyAdvice 對象

如果是嫌上述方法在每個方法里都要設(shè)置response.setHeader(“Access-Control-Allow-Origin”, “*”),那就可以統(tǒng)一處理返回??梢岳聾ControllerAdvice和ResponseBodyAdvice通知完成。

package com.alian.crossserver.advice;

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;

@ControllerAdvice // 織入通知
public class ResponseAdvice implements ResponseBodyAdvice {

    /**
     * 內(nèi)容是否需要重寫(返回true表示重寫)
     *
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    /**
     * 放回結(jié)果前調(diào)用
     *
     * @param body
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        // 設(shè)置跨域
        response.getHeaders().set("Access-Control-Allow-Origin", "*");
        return body;
    }

}
  • supports:判斷是否要交給 beforeBodyWrite 方法執(zhí)行,ture:需要;false:不需要
  • beforeBodyWrite:對 response 進(jìn)行具體的處理

3.6、通過 jsonp 方式

可能還有些老系統(tǒng)spring版本是Spring Framework 4.2 GA之前的,比如3.X??赡苌厦嬗行┓绞揭灿貌涣?,比如注解。這里我們可以使用jsonp方式,這里我們先改下我們的前端和后端。

3.6.1、后端

在之前的控制層增加一個接口jsonpRequest

@Slf4j
@RestController
@RequestMapping("/cross")
public class CrossController {

    @RequestMapping("/jsonpRequest")
    public String jsonpRequest(HttpServletRequest request, HttpServletResponse response,@RequestParam("callback") String callback) {
        log.info("1接收到跨域請求參數(shù):姓名:{},年齡:{}",request.getParameter("name"),request.getParameter("age"));
        log.info("2接收到跨域請求參數(shù):{}",callback);
        String json="{\"msg\":\"Request CrossServer Success\"}";
        return callback+"("+ json +")";
    }
}

這里需要注意的兩個點(diǎn):

  • 一個是請求的方法得支持GET方法(@RequestMapping就是POST、GET都支持)
  • 返回的結(jié)果轉(zhuǎn)為json字符串,作為回調(diào)方法的參數(shù)

3.6.2、前端方法一

對應(yīng)前端第一種方法是jsonp約定俗成的默認(rèn)值為callback

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test cross</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
</head>
<body>
<h1>跨域接口測試</h1>
<div>
    <input type="button" onclick="crossRequest()" value="發(fā)送跨域請求">
    <input type="button" onclick="crossCallBack()" value="老版本發(fā)送跨域請求">
</div>
<script>
    function crossRequest() {
        // 發(fā)送跨域請求
        jQuery.ajax({
            url: "http://localhost:8080/crossServer/cross/request",
            type: "POST",
            data: {"name": "alian"},
            success: function (result) {
                alert("請求返回?cái)?shù)據(jù):" + result);
            }
        });
    }

	// 只看這個方法
    function crossCallBack() {
        // 發(fā)送跨域請求
        jQuery.ajax({
            url: "http://localhost:8080/crossServer/cross/jsonpRequest",
            type: "POST",
            data: {"name": "alian","age": "28"},
            dataType: "jsonp", //指定服務(wù)器返回的數(shù)據(jù)類型
            jsonp: "callback",
            success: function (data) {
                alert("success回調(diào):"+JSON.stringify(data));
            }
        });
    }

</script>
</body>
</html>
  • dataType:該參數(shù)必須要設(shè)置成jsonp
  • jsonp:該參數(shù)的值需要與服務(wù)器端約定(默認(rèn)值為callback
  • 成功進(jìn)入到success

所以我的后端接口就有一個參數(shù)接收

@RequestParam("callback") String callback

3.6.3、前端方法二

假設(shè)你不想用默認(rèn)的方法,比如方法名占用了,怎么辦呢?那就像下面這樣自定義方法名:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test cross</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
</head>
<body>
<h1>跨域接口測試</h1>
<div>
    <input type="button" onclick="crossRequest()" value="發(fā)送跨域請求">
    <input type="button" onclick="crossCallBack()" value="老版本發(fā)送跨域請求">
</div>
<script>
    function crossRequest() {
        // 發(fā)送跨域請求
        jQuery.ajax({
            url: "http://localhost:8080/crossServer/cross/request",
            type: "POST",
            data: {"name": "alian"},
            success: function (result) {
                alert("請求返回?cái)?shù)據(jù):" + result);
            }
        });
    }

	// 看這個方法
    function crossCallBack() {
        // 發(fā)送跨域請求
        jQuery.ajax({
            url: "http://localhost:8080/crossServer/cross/jsonpRequest?callback=jsonpCallBack",
            type: "POST",
            data: {"name": "alian","age": "28"},
            dataType: "jsonp", //指定服務(wù)器返回的數(shù)據(jù)類型
            jsonp: "jsonpCallBack",
            success: function (data) {

            }
        });
    }

	// 這個是回調(diào)方法了,不會進(jìn)入到success了
    function jsonpCallBack(data){
        var result = JSON.stringify(data); //json對象轉(zhuǎn)成字符串
        alert("Jsonp請求返回?cái)?shù)據(jù):" + result);
    }
</script>
</body>
</html>
  • 首先你得指定你的jsonp方法,比如我這里是jsonpCallBack,也就是回調(diào)方法
  • 同時我們請求里需要把回調(diào)方法名傳遞到后臺,比如我這里callback=jsonpCallBack
  • 回調(diào)就會直接進(jìn)入到我們的jsonpCallBack方法

jsonpCallBack是自定義方法名,你也可以改成其他的名字,記得請求參數(shù),請求地址,及其方法定義,三個一起改哦。

兩者的結(jié)果如下:

總結(jié)

跨域是瀏覽器的行為,跨域問題其實(shí)就是瀏覽器的同源策略所導(dǎo)致的,所以后端就沒有跨域一說了。以上幾種跨域解決方法單獨(dú)用一個就行了,盡量不要混用,以免出現(xiàn)其他重復(fù)沖突的問題。還有其他一些通過nginx或者網(wǎng)關(guān)等方法都可以解決跨域問題,就不一一介紹了。

以上就是Java實(shí)現(xiàn)后端跨域的常見解決方案的詳細(xì)內(nèi)容,更多關(guān)于Java后端跨域的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java 實(shí)戰(zhàn)圖書管理系統(tǒng)的實(shí)現(xiàn)流程

    Java 實(shí)戰(zhàn)圖書管理系統(tǒng)的實(shí)現(xiàn)流程

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+jsp+mysql+maven實(shí)現(xiàn)一個圖書管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • 使用Java Collections實(shí)現(xiàn)集合排序的全面指南

    使用Java Collections實(shí)現(xiàn)集合排序的全面指南

    在Java編程中,集合(Collection)是處理數(shù)據(jù)的重要工具之一,Java集合框架提供了豐富的接口和類來操作數(shù)據(jù)集合,而排序是其中最常見的操作之一,本文將詳細(xì)介紹如何使用Collections類對集合進(jìn)行排序,并深入探討其背后的原理和使用場景,需要的朋友可以參考下
    2025-02-02
  • Java的原子類無鎖并發(fā)利器詳解

    Java的原子類無鎖并發(fā)利器詳解

    這篇文章主要介紹了Java的原子類無鎖并發(fā)利器詳解,原子類同樣能夠解決互斥性問題、原子性問題除此之外,因?yàn)樵宇愂菬o鎖操作,沒有用互斥鎖解決帶來的加鎖解決性能消耗,這種絕佳方案是怎么做到的呢,需要的朋友可以參考下
    2023-12-12
  • Java基礎(chǔ)篇之對象數(shù)組練習(xí)

    Java基礎(chǔ)篇之對象數(shù)組練習(xí)

    對象數(shù)組就是數(shù)組里的每個元素都是類的對象,賦值時先定義對象,然后將對象直接賦給數(shù)組就行了,這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)篇之對象數(shù)組練習(xí)的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Java和Scala集合間的相互轉(zhuǎn)換方式

    Java和Scala集合間的相互轉(zhuǎn)換方式

    這篇文章主要介紹了Java和Scala集合間的相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java中如何正確重寫equals方法

    Java中如何正確重寫equals方法

    Object類中equals方法比較的是兩個對象的引用地址,只有對象的引用地址指向同一個地址時,才認(rèn)為這兩個地址是相等的,否則這兩個對象就不相等
    2021-10-10
  • Java創(chuàng)建與結(jié)束線程代碼示例

    Java創(chuàng)建與結(jié)束線程代碼示例

    這篇文章主要介紹了Java創(chuàng)建與結(jié)束線程代碼示例,小編覺得挺不錯的,這里分享給大家,供需要的朋友參考。
    2017-10-10
  • SpringBoot Redis配置多數(shù)據(jù)源的項(xiàng)目實(shí)踐

    SpringBoot Redis配置多數(shù)據(jù)源的項(xiàng)目實(shí)踐

    springboot中默認(rèn)的redis配置是只能對單個redis庫進(jìn)行操作的, 那么我們需要多個庫操作的時候這個時候就可以采用redis多數(shù)據(jù)源 ,本文就介紹了SpringBoot Redis配置多數(shù)據(jù)源,感興趣的可以了解一下
    2023-07-07
  • Java多線程案例之定時器詳解

    Java多線程案例之定時器詳解

    定時器是一種實(shí)際開發(fā)中非常常用的組件,?類似于一個?“鬧鐘”,?達(dá)到一個設(shè)定的時間之后,?就執(zhí)行某個指定好的代碼。本文主要來和大家聊聊定時器的原理與使用,需要的可以參考一下
    2023-01-01
  • 全面解析Java中常見Exception異常的錯誤排查與代碼修正

    全面解析Java中常見Exception異常的錯誤排查與代碼修正

    這篇文章主要為大家詳細(xì)介紹了Java開發(fā)中最常見的異常類型及其處理方法,包括運(yùn)行時異常(如NullPointerException,ArrayIndexOutOfBoundsException)和受檢異常,下面小編就和大家詳細(xì)介紹一下吧
    2026-03-03

最新評論

洛阳市| 武定县| 新兴县| 贵港市| 揭西县| 大连市| 台安县| 静安区| 阿图什市| 安仁县| 都昌县| 隆化县| 青神县| 福海县| 双城市| 湟源县| 玛多县| 曲阜市| 凯里市| 黎城县| 台东市| 罗城| 岐山县| 商洛市| 淮南市| 河曲县| 大田县| 江北区| 水富县| 梅州市| 高碑店市| 海兴县| 石台县| 十堰市| 邵武市| 垫江县| 通河县| 尼勒克县| 临沭县| 响水县| 娱乐|