前后端分離之解決跨域問題


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中添加額外的代碼了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM