如何使用 Spring REST 在跨域资源共享 (CORS) 中接收 JSON 数据

Posted

技术标签:

【中文标题】如何使用 Spring REST 在跨域资源共享 (CORS) 中接收 JSON 数据【英文标题】:How To Receive JSON Data In Cross Origin Resource Sharing (CORS) with Spring REST 【发布时间】:2015-01-25 17:07:07 【问题描述】:

我正在尝试发送/接收 JSON数据从/到我的控制器类在我的项目中。

我的项目的Controller类如下:

@RequestMapping(value = "/dummy/",method = RequestMethod.POST,headers="Accept=application/json")
public Response getDummyJSON() 

    /*  Method 2: Getting the Dummy JSON Data From file and sending it as an JSON Object  */

    JSONParser parser = new JSONParser();
    JSONObject jsonObject = null;
    try 

        Object obj = parser.parse(new FileReader("d:\\JsonStruc.json"));
        jsonObject = (JSONObject) obj;

     catch (Exception e) 
        System.out.println("Error Parsing: - ");
       


        return Response.status(200).entity(jsonObject).build();             



@RequestMapping(value = "/insert/dummy/",method= RequestMethod.POST,headers="Accept=application/json")
public Response setDummyJSON(@RequestBody JSONObject inputjsonObj)

    /*Step 1: Display The JSON data sent by AngularJS */ 
    System.out.println("Data Received:"+ inputjsonObj.toString());
    JSONParser jsonparser = new JSONParser();
    ContainerFactory containerFactory = new ContainerFactory()
        public List creatArrayContainer() 
            return new LinkedList();
        

        public Map createObjectContainer() 
            return new LinkedHashMap();
        

    ;

    Map obj = (Map)inputjsonObj;
    Iterator iter = obj.entrySet().iterator();
    while(iter.hasNext())
        Map.Entry entry = (Map.Entry)iter.next();
        System.out.println(entry.getKey() + "=>" + entry.getValue());

    

    /* Step 2: send the next dummy JSON file */
    JSONParser parser = new JSONParser();
    JSONObject jsonObject1 = null;
    try 

        Object obj1 = parser.parse(new FileReader("d:\\JsonStruc1.json"));
        jsonObject1 = (JSONObject) obj1;

     catch (Exception e) 
        System.out.println("Error Parsing: - ");
       
    return Response.status(200).entity(jsonObject1).build();          
   

我的项目的CORS类如下:

public class CorsFilter extends OncePerRequestFilter

 private Properties prop = new Properties();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
            throws ServletException, IOException 


         System.out.println("Inside Cross Origin Resource Sharing Filter Class");
         System.out.println(request.getContentType());
         System.out.println(request.getContentLength());

         response.setHeader("Access-Control-Allow-Origin", "*");
         response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");
         response.setHeader("Access-Control-Max-Age", "3600");
         response.setHeader("Access-Control-Allow-Credentials", "true");
         response.setHeader("Access-Control-Allow-Headers", "x-requested-with");

         filterChain.doFilter(request, response);
    


没有问题关于通过 URL (/service/question/dummy/) 发送 Dummy JSON 数据但是 当我试图获取 JSON 数据 (/service/question/insert/dummy/) 并发送下一个 JSON 对象时 通过 setDummyJSON(....) 方法,我遇到了麻烦。 AngularJS(客户端)端显示以下异常消息

跨域请求被阻止:同源策略不允许读取 /FetchQuestions/service/question/insert/dummy/ 处的远程资源。这可以通过将资源移动到同一域或启用 CORS 来解决。

在使用 JSON 字符串作为内容正文从 localhost 调用 URL (/service/question/insert/dummy/) 时,会引发以下错误消息:

服务器拒绝了这个请求,因为请求实体的格式不受所请求方法 () 的请求资源支持。

我做错了什么?任何帮助将不胜感激。谢谢。

【问题讨论】:

我不明白为什么你需要一个拦截器,恕我直言,corsFilter 是唯一需要的东西。您能否澄清“我遇到麻烦”,例如解释/添加堆栈跟踪? @RC :我已经从项目中删除了拦截器类,还删除了 rest-servlet.xml 中的映射,无论如何调用 URL (/service/question/insert/dummy/)客户端(AngularJS)它给出了 CORS 异常。 @RC : 添加了来自客户端的异常消息。 我会尝试将Content-Type 添加到允许的标头列表(“Access-Control-Allow-Headers”)中,并确保CorsFilterweb.xml 中正确映射 @RC。 :CorsFilter 在 web.xml 中正确映射,如何将 Content-Type 添加到允许的标头列表中? 【参考方案1】:

上面的代码没有错

出于某种原因,只要使用以下命令在 AngularJS(客户端)中将 Content-Type 设置为 application/json

$httpProvider.defaults.headers.post['Content-Type'] = 'application/json';

服务器端收到 nullContent-Type。任何其他内容类型,如 application/x-www-form-urlencodedtext/plain 都可以工作,但问题仅发生在 application/json (即使 AngularJS 正在向服务器端发送 JSON 数据)。

因此,Controller 类中的一些小改动解决了问题。

@RequestMapping(value = "/insert/dummy/",method= RequestMethod.POST")
public Response setDummyJSON(@RequestBody String inputjsonObj)
/* Step1: Receive The Data in Text/Plain Format
   Step2: Conver The String To JSON Object. Do Necessary Processing.
   Step3: Return Dummy JSON Object through the Response. */
  return Response.status(200).entity(jsonObject1).build();

【讨论】:

以上是关于如何使用 Spring REST 在跨域资源共享 (CORS) 中接收 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章

在跨域请求中捕获 JSONP 错误

如何在跨域中获取 iframe contentWindow 高度

如何将焦点设置在跨域的 iframe 上

cors跨域资源共享---解决前后端跨域问题

无法在跨域上使用 JSONP 发布数据

Jquery $.ajax 在跨域调用的 IE 中失败