zoukankan      html  css  js  c++  java
  • 前后端分离之解决跨域问题

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

  • 相关阅读:
    体检套餐管理系统
    Altium Designer9.4局域网内冲突的问题
    关于ARM Linux下的SD卡及U盘的挂载问题
    mkimage command not found – U-Boot images will not be built
    Xilinx------BUFG,IBUFG,BUFGP,IBUFGDS等含义以及使用
    linux文件压缩解压命令
    VIVADO 入门之仿真与逻辑分析仪使用
    Linux自动运行应用程序
    ZYNQ学习之二-EMIO
    inux grep 命令 搜索含有"zynq"字符的文件
  • 原文地址:https://www.cnblogs.com/qintang/p/13821654.html
Copyright © 2011-2022 走看看