ajax跨域问题以及解决方案_js跨域请求的三种方法
出于瀏覽器的同源策略限制。同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會(huì)受到影響??梢哉fWeb是構(gòu)建在同源策略基礎(chǔ)之上的,瀏覽器只是針對(duì)同源策略的一種實(shí)現(xiàn)。同源策略會(huì)阻止一個(gè)域的javascript腳本和另外一個(gè)域的內(nèi)容進(jìn)行交互。所謂同源(即指在同一個(gè)域)就是兩個(gè)頁(yè)面具有相同的協(xié)議(protocol),主機(jī)(host)和端口號(hào)(port)
AJAX跨域請(qǐng)求
下面簡(jiǎn)單模擬一個(gè)場(chǎng)景—–>>
前端有一個(gè)頁(yè)面
鼠標(biāo)離開用戶名輸入框時(shí),檢查是否符合要求,如果為空,則給提示,如果不為空,則異步查詢數(shù)據(jù)庫(kù),后返回結(jié)果;
本次請(qǐng)求的頁(yè)面是8082端口的,而響應(yīng)的ajax路徑卻是8080端口的
前端代碼—>
<!DOCTYPE html>
<html>
<head>
<title>$Title%sSourceCod</title>
<meta charset="UTF-8"/>
<script src="js/jquery-3.5.1.min.js"></script>
<script> function checkUname(){
// 獲取輸入框中的內(nèi)容 if(null == $("#unameI").val() || '' == $("#unameI").val()){
$("#unameInfo").text("用戶名不能為空"); return; } $("#unameInfo").text(""); // 通過jQuery.ajax() 發(fā)送異步請(qǐng)求 $.ajax( {
type:"GET",// 請(qǐng)求的方式 GET POST url:"http://localhost:8080/loadPicture_war_exploded/checkName.do?", // 請(qǐng)求的后臺(tái)服務(wù)的路徑 data:"uname="+$("#unameI").val(),// 提交的參數(shù) success:function(info){
// 響應(yīng)成功執(zhí)行的函數(shù) $("#unameInfo").text(info) } } ) } </script>
</head>
<body>
<form action="myServlet1.do" >
用戶名:<input id="unameI" type="text" name="uname" onblur="checkUname()">
<span id="unameInfo"></span><br/>
密碼:<input type="password" name="pwd"><br/>
<input type="submit" value="提交按鈕">
</form>
</body>
</html>
后端代碼—>
package com.gavin.controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/checkName.do")
public class testAjax extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uname = req.getParameter("uname");
String callBack = req.getParameter("aaa");
System.out.println(uname);
String info = "";
if ("gavin".equals(uname)) {
info = "用戶名已經(jīng)占用";
} else {
info = "用戶名可用";
}
// 向?yàn)g覽器響應(yīng)數(shù)據(jù)
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/javaScript;charset=UTF-8");
resp.getWriter().print(callBack + "('" + info + "')");
}
}
訪問的時(shí)候?yàn)g覽器提示—>
原因—>
對(duì) CORS 請(qǐng)求的響應(yīng)缺少必需的Access-Control-Allow-Origin頭,其用于確定在當(dāng)前源內(nèi)操作的資源是否可以訪問。
如果服務(wù)器在您的控制之下,請(qǐng)將請(qǐng)求站點(diǎn)的源添加到允許訪問的域集,方法是將其添加到Access-Control-Allow-Origin頭的值。
為什么會(huì)有跨域呢?
因?yàn)閷?shí)際應(yīng)用中分布式與集群會(huì)涉及到跨域,前端服務(wù)器與后端服務(wù)器分離,前端服務(wù)異步請(qǐng)求后端服務(wù)器就涉及到了跨域;
由于瀏覽器的同源策略,所以跨服務(wù)器訪問會(huì)有一些小麻煩,先一步一步探索去解決;
這個(gè)時(shí)候js文件能不能加載生效呢? 答案是生效了;
Web頁(yè)面上調(diào)用js文件時(shí)可以跨域,也就是后擁有”src”這個(gè)屬性的標(biāo)簽都卻擁有跨域的能力
那么我們轉(zhuǎn)變思路,如果將異步請(qǐng)求轉(zhuǎn)到j(luò)s文件身上
比如我們可以這么做
后端可以接收到前端數(shù)據(jù);
但是這樣寫看起來怪怪的,而且實(shí)際上這樣異步請(qǐng)求中的url依然會(huì)被瀏覽器攔截
如果去掉這個(gè)url,會(huì)發(fā)生不可描述的事情,像這樣—-整個(gè)span被頁(yè)面代碼填滿,
那怎么處理呢?
此時(shí)異步請(qǐng)求添加一個(gè)屬性—dataType:“jsonp”
這樣就可以正常一點(diǎn)實(shí)現(xiàn)跨域的異步請(qǐng)求了—>
function checkUname(){
// 獲取輸入框中的內(nèi)容
if(null == $("#unameI").val() || '' == $("#unameI").val()){
$("#unameInfo").text("用戶名不能為空");
return;
}
$("#unameInfo").text("");
// 通過jQuery.ajax() 發(fā)送異步請(qǐng)求
$.ajax(
{
type:"GET",// 請(qǐng)求的方式 GET POST
url:"http://localhost:8080/loadPicture_war_exploded/checkName.do?", // 請(qǐng)求的后臺(tái)服務(wù)的路徑
data:"uname="+$("#unameI").val(),// 提交的參數(shù)
dataType:"jsonp",
success:function(info){ // 響應(yīng)成功執(zhí)行的函數(shù)
$("#unameInfo").text(info)
}
}
)
}
原因—->>
雖然跨域請(qǐng)求實(shí)現(xiàn)了,但是前端接收不到后端返回的數(shù)據(jù),即異步 請(qǐng)求中的success方法失效了,
為什么失效?因?yàn)槿绻峭ㄟ^script來完成異步請(qǐng)求,那么返回的內(nèi)容應(yīng)該是一個(gè)js代碼,
既然是這樣,我們要想在span中添加返回類的信息,那么我們不妨在前端寫一個(gè)方法,用于專門像span中添加信息—然后后端返回的信息來直接調(diào)這個(gè)方法就好了;
function showInfo(info){
$("#unameInfo").val(info);
}
后端返回的數(shù)據(jù)
運(yùn)行原理——>>>>
解決一個(gè)小痛點(diǎn),前端方法名隨時(shí)可能變化,為了降低耦合度,一般會(huì)這么做,前端發(fā)送的數(shù)據(jù)中攜帶該方法名;
前面不是說success廢了嗎?我就想用這個(gè)方法,不想在額外定義一個(gè)別的showInfo方法,那么這個(gè)該怎么做呢?
在異步請(qǐng)求上添加一個(gè)參數(shù):
jsonp:“任意的名稱A”
GetJson實(shí)現(xiàn)跨域請(qǐng)求
function checkUname(){
// 獲取輸入框中的內(nèi)容
if(null == $("#unameI").val() || '' == $("#unameI").val()){
$("#unameInfo").text("用戶名不能為空");
return;
}
$("#unameInfo").text("");
$.getJSON(
"http://localhost:8080/loadPicture_war_exploded/checkName.do?jsoncallback=?",
{uname:$("#unameI").val()},
function(info){
$("#unameInfo").text(info)
}
)
}
通過后臺(tái)代碼也可以實(shí)現(xiàn)跨域,一般在過濾器中添加如下代碼,那么前端在請(qǐng)求時(shí)就不用考慮跨域問題了
/*請(qǐng)求地址白名單 *代表所有 /
resp.setHeader(“Access-Control-Allow-Origin”, ““);
/*請(qǐng)求方式白名單 */
resp.setHeader(“Access-Control-Allow-Methods”, “POST, GET, OPTIONS, DELETE”);
resp.setHeader(“Access-Control-Max-Age”, “3600”);
resp.setHeader(“Access-Control-Allow-Headers”, “x-requested-with”);
在結(jié)合springmvc之后,可以通過一個(gè)注解來完成跨域
CrossOrigin注解實(shí)現(xiàn)跨域
package com.gavin.controller;
import com.gavin.pojo.AlertMsg;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class AjaxTEST {
@CrossOrigin(value ="http://127.0.0.1:8020" )
@RequestMapping("/checkName3.do")
@ResponseBody
public AlertMsg checkUserName(@RequestBody AlertMsg alertMsg) {
System.out.println(alertMsg);
if ("gavin".equals(alertMsg.getUname())) {
alertMsg.setMsg("用戶名已經(jīng)占用");
} else {
alertMsg.setMsg( "用戶名可用");
}
// 向?yàn)g覽器響應(yīng)數(shù)據(jù)----返回一個(gè)json格式的數(shù)據(jù)
System.out.println(alertMsg);
return alertMsg;
}
}
function checkUname3() {
// 獲取輸入框中的內(nèi)容
if(null == $("#unameI3").val() || '' == $("#unameI3").val()) {
$("#unameInfo3").text("用戶名不能為空");
return;
}
$("#unameInfo3").text("");
var str = $("#unameI3").val();
$.ajax({
type: "post",
url: "http://localhost:8080/loadPicture_war_exploded/checkName3.do?",
// data:{uname:$("#unameI3").val(),msg:""},
//data:{"uname":$("#unameI3").val(),"msg":""},
data: JSON.stringify({
uname: $("#unameI3").val()
}),
dataType: "json",
contentType: "application/json;charset=UTF-8",
success: function(data) {
$("#unameInfo3").text(data.msg);
}
});
}
關(guān)于json對(duì)象的一些感悟與理解;
前端傳過來的數(shù)據(jù)—-可能是字符串,也可能是json對(duì)象,但是在處理的時(shí)候還是以字符串進(jìn)行處理的,
JSON.stringify()方法是將一個(gè)JavaScript對(duì)象轉(zhuǎn)換成符合JSON格式的字符串,然后后端通過解析字符串在轉(zhuǎn)化為一個(gè)json對(duì)象;
所以
ajax跨域的解決方案有種了,
第一種是 jsonp的形式,
另一種是getjson()
最后一種是注解CrossOrigin
總結(jié)
以上是生活随笔為你收集整理的ajax跨域问题以及解决方案_js跨域请求的三种方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文献记录(part74)--Subspa
- 下一篇: MultipeerConnectivit