Java前后端分離項(xiàng)目跨域問(wèn)題解決方案
前言
本文將講解前后端項(xiàng)目中跨域問(wèn)題的常見(jiàn)解決方案,其中后端基于SpringBoot
,前端使用了jQuery
、axios
等框架用于實(shí)戰(zhàn)代碼的講解。本文將不涉及跨域
的解釋和SpringBoot
等框架,或者是Nginx
的使用,將主要講解前后端分離項(xiàng)目中跨域問(wèn)題的解決,不過(guò)如果你遇到了問(wèn)題,也歡迎一起交流學(xué)習(xí)。
跨域解決
JSONP
方式
這種方式只能用于Get
請(qǐng)求,因此如果需要以Post
請(qǐng)求方式獲取數(shù)據(jù),則可以先看后面CORS
解決方式,以下就講解兩種基于JSONP
原理的解決方案,首先先看后端的接口:
@RestController @RequestMapping("/api/customer") public class HelloController { @GetMapping("/getAllCustomerInfo") public String getAllCustomerInfo() { // 返回的數(shù)據(jù)必須包含在 getAllCustomerInfo() 字符串中 // 以便在返回到前端后,可以自動(dòng)執(zhí)行回調(diào)函數(shù),獲取數(shù)據(jù) // getAllCustomerInfo() 與前端的回調(diào)函數(shù)名對(duì)應(yīng) return "getAllCustomerInfo(" + getCustomerList() + ")"; } private String getCustomerList() { List<Customer> list = new ArrayList<>(Arrays.asList( new Customer(1, "張三", "123456"), new Customer(2, "李四", "654321"), new Customer(3, "王五", "123123") )); return new Gson().toJson(list); } }
下面就來(lái)分別講解以下兩種方式的解決方案:
js
原生解決方案
// 首先設(shè)置 src 并將結(jié)點(diǎn)添加到 <head> 中 const script = document.createElement('script') script.src = 'http://localhost:8080/api/customer/getAllCustomerInfo' document.head.appendChild(script) // 回調(diào)函數(shù)名與接口中返回的名字對(duì)應(yīng) const getAllCustomerInfo = res => { console.table(res, ['id', 'username', 'password']) }
通過(guò)以上設(shè)置就可以在Console
中看到以下結(jié)果:
jQuery
的ajax
解決方案
// 記得需要引入 jQuery <script src="https://cdn.staticfile.org/jquery/1.10.0/jquery.js"></script> $.ajax({ url: 'http://localhost:8080/api/customer/getAllCustomerInfo', type: 'get', dataType: 'jsonp', jsonpCallback: "getAllCustomerInfo" }) // 回調(diào)函數(shù)同上 const getAllCustomerInfo = res => { console.table(res, ['id', 'username', 'password']) }
CORS
解決方案
跨域資源共享(CORS) 是一種機(jī)制,它使用額外的 HTTP 頭來(lái)告訴瀏覽器 讓運(yùn)行在一個(gè) origin (domain) 上的Web應(yīng)用被準(zhǔn)許訪問(wèn)來(lái)自不同源服務(wù)器上的指定的資源。當(dāng)一個(gè)資源從與該資源本身所在的服務(wù)器不同的域、協(xié)議或端口請(qǐng)求一個(gè)資源時(shí),資源會(huì)發(fā)起一個(gè)跨域 HTTP 請(qǐng)求,詳細(xì)解釋請(qǐng)看鏈接。
后端接口中進(jìn)行設(shè)置
通過(guò)利用CORS
,我們?cè)谇岸酥恍枰谜5?code>ajax請(qǐng)求方式即可,無(wú)需再設(shè)置回調(diào)函數(shù),在這里我們使用了axios
,在展示后端代碼之前,我們先看后端代碼的改變,為了區(qū)別于JSONP
只能進(jìn)行Get
請(qǐng)求,我們這里將接口改成了Post
:
@RestController @RequestMapping("/api/customer") public class HelloController { @PostMapping("/getAllCustomerInfo") public List<Customer> getAllCustomerInfo(HttpServletResponse response) { // 設(shè)置響應(yīng)頭 response.setHeader("Access-Control-Allow-Origin", "*"); // 不再需要將結(jié)果放在回調(diào)函數(shù)中 return new ArrayList<>(Arrays.asList( new Customer(1, "張三", "123456"), new Customer(2, "李四", "654321"), new Customer(3, "王五", "123123") )); } }
然后前端代碼直接使用ajax
請(qǐng)求即可:
// 首先需要引入 axios <script src="https://cdn.staticfile.org/axios/0.1.0/axios.js"></script> axios.post('http://localhost:8080/api/customer/getAllCustomerInfo') .then(res => { console.table(res, ['id', 'username', 'password']) })
Nginx
反向代理
關(guān)于反向代理的知識(shí),這里不做詳細(xì)解析,感興趣的話,可以查看該鏈接。通過(guò)使用Nginx
的反向代理,我們?cè)诤蠖私涌谥芯涂梢匀サ繇憫?yīng)頭的代碼設(shè)置:
@RestController @RequestMapping("/api/customer") public class HelloController { @PostMapping("/getAllCustomerInfo") public List<Customer> getAllCustomerInfo() { return new ArrayList<>(Arrays.asList( new Customer(1, "張三", "123456"), new Customer(2, "李四", "654321"), new Customer(3, "王五", "123123") )); } }
然后是nginx.conf
中的修改:
server { # 監(jiān)聽(tīng)80端口, 前端不再直接訪問(wèn)8080端口, 改為訪問(wèn)80端口即可 listen 80; server_name localhost; location / { root html; # 添加頭 add_header Access-Control-Allow-Origin *; # 代理轉(zhuǎn)發(fā)到8080后端端口 proxy_pass http://localhost:8080; index index.html index.htm; } }
然后再將前端中訪問(wèn)的接口修改為80:
// 首先需要引入 axios <script src="https://cdn.staticfile.org/axios/0.1.0/axios.js"></script> // 80為 http 默認(rèn)端口,可省略 axios.post('http://localhost/api/customer/getAllCustomerInfo') .then(res => { console.table(res, ['id', 'username', 'password']) })
然后開(kāi)啟Nginx
服務(wù)器,Console
中再次出現(xiàn)了我們想看到的結(jié)果:
總結(jié)
本文并沒(méi)有包括跨域問(wèn)題的所有解決方案,不過(guò)相信對(duì)于大部分的跨域問(wèn)題,都已經(jīng)可以解決了,本文在之后也可能會(huì)繼續(xù)更新,講解更多種解決跨域問(wèn)題的方法
到此這篇關(guān)于Java前后端分離項(xiàng)目跨域問(wèn)題解決方案的文章就介紹到這了,更多相關(guān)Java前后端分離跨域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的緩存方法
本篇文章主要介紹了Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的緩存方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04java實(shí)現(xiàn)客戶端向服務(wù)器發(fā)送文件
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)客戶端向服務(wù)器發(fā)送文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Java Apollo是如何實(shí)現(xiàn)配置更新的
這篇文章主要介紹了Java Apollo是如何實(shí)現(xiàn)配置更新的,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-03-03Hibernate延遲加載原理與實(shí)現(xiàn)方法
這篇文章主要介紹了Hibernate延遲加載原理與實(shí)現(xiàn)方法,較為詳細(xì)的分析了Hibernate延遲加載的概念,原理與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-03-03