1. 建立前端項目
在HbuilderX里面新建一個名為front
的項目
index.html
里面的內容為:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前端頁面</title>
<script src="jquery-3.5.1.min.js"></script>
</head>
<body>
<p>使用Ajax從后端獲取到的信息為:</p>
<p id="msg" style="color: red;"></p>
<script>
$.ajax({
url: "http://localhost:8080/back/MessageServlet",
method: "GET",
success: function(data) {
$("#msg").text(data);
}
})
</script>
</body>
可以看到,前端服務器的主機名和端口號為:127.0.0.1:8848
HbuilderX的內置服務器是一個通用的Node的webserver
2. 建立后端項目
在Eclipse里面新建一個名為back
的項目
MessageServlet.java
里面的內容為:
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/MessageServlet")
public class MessageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 設置編碼
response.setCharacterEncoding("GBK");
// 返回的消息
PrintWriter out = response.getWriter();
out.print("返回的消息");
}
}
可以看到,后端Tomcat服務器的主機名和端口號為:127.0.0.1:8080
我們可以直接通過輸入相應路徑的方式來查看Servlet返回的消息
3. 在Servlet中進行配置
此時,前后端項目都已經建立完成,前端頁面通過Ajax方式向后台請求數據,但是前端頁面並沒有獲取到返回的消息,同時控制台顯示如下信息:
CORS:Cross Origin Resource Sharing,跨域資源共享。
出於安全的考慮,瀏覽器不允許Ajax訪問當前源(如果兩個頁面的協議、主機名和端口號都相同,則兩個頁面具有相同的源)之外的資源,即同源策略。
那么這時我們就需要規避同源策略來實現跨域請求。
解決跨域的方式有很多,這里使用一種在后端設置的方式,在MessageServlet中添加如下代碼:
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/MessageServlet")
public class MessageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 設置編碼
response.setCharacterEncoding("UTF-8");
// 允許跨域的主機地址
response.setHeader("Access-Control-Allow-Origin", "*");
// 允許跨域的請求頭
response.setHeader("Access-Control-Allow-Headers", "*");
// 允許跨域的請求方法
response.setHeader("Access-Control-Allow-Methods", "*");
// 是否允許攜帶cookie
response.setHeader("Access-Control-Allow-Credentials", "true");
// 重新預檢驗跨域的緩存時間
response.setHeader("Access-Control-Max-Age", "3600");
// 返回的消息
PrintWriter out = response.getWriter();
out.print("返回的消息");
}
}
刷新前端頁面,可以看到消息正常顯示:
4. 使用Filter
將Servlet中的代碼放置在Filter中
新建一個名為CORSFilter
的Filter
package servlet;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebFilter(filterName = "/CORSFilter", urlPatterns = {"/*"})
public class CORSFilter implements Filter {
public CORSFilter() {}
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "*");
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
chain.doFilter(httpServletRequest, httpServletResponse);
}
public void init(FilterConfig fConfig) throws ServletException {}
}
這樣就不需要再在每個Servlet中添加額外的代碼了