前后端分离之解决跨域问题

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中添加额外的代码了

posted @ 2020-10-15 17:09  秦唐  阅读(2394)  评论(0编辑  收藏  举报