无法在 Google 应用引擎中处理跨域 json 请求并在 json 中获得响应

Posted

技术标签:

【中文标题】无法在 Google 应用引擎中处理跨域 json 请求并在 json 中获得响应【英文标题】:Not able to process cross domain json request in Google app engine and get response in json 【发布时间】:2014-12-08 21:49:47 【问题描述】:

XMLHttpRequest 无法加载 http://XXXXXXXX.com/getProduct.html。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://example.com' 不允许访问。

我的客户端jsp代码:

<script type="text/javascript" src="Jquery.js"></script>

<script>
function submitLogin() 
        var obj = 
                "productMasterId" : "1"
        ;

        $.ajax( 
            url: "http://XXXXXXXX.com/getProduct.html", 
            type: 'POST',
            contentType: 'text/javascript; charset=utf-8',
            crossDomain : true,
            mimeType: 'text/javascript',
            success : function(response) 
                alert("done");
                alert(response);
            
            ,
            error : function(response) 

            
        ); 

    
</script>
<a href="javascript:submitLogin()">click </a>

我的服务器端代码:

@RequestMapping("/getProductDetailsForReview.html")
    public @ResponseBody PaymentForm getProductDetailsForReview(@RequestBody PaymentForm paymentForm, HttpServletResponse response) 
        log.debug("Start of method getProductDetailsForReview");
        PaymentForm form = userPaymentService.getProductForReview(paymentForm);
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        log.debug("End of method getProductDetailsForReview");
        return form;
    

CORS 过滤器:

package com.bullbeardevice.filter;

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.http.HttpServletResponse;

import org.springframework.stereotype.Component;

/**
 * Servlet Filter implementation class SimpleCORSFilter
 */
@Component
public class SimpleCORSFilter implements Filter 

    /**
     * Default constructor. 
     */
    public SimpleCORSFilter() 
        // TODO Auto-generated constructor stub
    

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
        System.out.println("In CORS Filter");
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(req, res);
    

    public void init(FilterConfig filterConfig) 

    public void destroy() 


回复:

Remote Address:127.0.0.1:8888
Request URL:http://localhost:8888/getProductDetailsForReview.html
Request Method:POST
Status Code:415 Unsupported Media Type
Request Headersview source
Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip,deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:23
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Host:localhost:8888
Origin:http://localhost:8080
Referer:http://localhost:8080/samplekit/jsp/index.jsp
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
Form Dataview sourceview URL encoded
"productMasterId":"1":
Response Headersview source
Access-Control-Allow-Headers:application/javascript
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:*
Access-Control-Max-Age:3600
Cache-Control:no-cache
Cache-Control:no-store
Content-Length:83
Content-Type:text/html; charset=iso-8859-1
Date:Wed, 15 Oct 2014 07:09:48 GMT
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Pragma:no-cache
Server:Development/1.0

Spring xml 配置:

    <context:component-scan base-package="com.bull.*" />
    <context:annotation-config />
    <bean id="multipartResolver" class="org.gmr.web.multipart.GMultipartResolver">
        <property name="maxUploadSize" value="1048576" />
    </bean>
    <bean id="viewResolver2"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass">
            <value>
                org.springframework.web.servlet.view.tiles2.TilesView
            </value>
        </property>
    </bean>
    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
        <property name="basename" value="ApplicationResources" />
    </bean>
    <mvc:annotation-driven
        content-negotiation-manager="contentNegotiationManager" />
    <!-- Configure bean to convert JSON to POJO and vice versa -->
    <bean id="jsonMessageConverter"
        class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </bean>
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonMessageConverter" />
            </list>
        </property>
    </bean>
    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="ApplicationResources" />
    </bean>
    <bean id="contentNegotiationManager"
        class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="defaultContentType" value="application/json" />
        <property name="favorPathExtension" value="false" />
    </bean>

</beans>

【问题讨论】:

如果我使用 CORS 并定义过滤器并将响应头设置为 response.setHeader("Access-Control-Allow-Origin", "*") 那么我得到 GET localhost:8888/getProductDetailsForReview.html 415 (不支持的媒体类型) 我的请求到达过滤器 【参考方案1】:

问题只是我在控制器的方法的参数中使用了@RequestBody。现在我已经用@requestparam 替换了它,它工作正常。

【讨论】:

【参考方案2】:

好吧,我想说的是缺少一些信息,但请尝试提供帮助。很少有事情是错误的。从最明显的开始

您的请求针对“http://XXXXXXXX.com/getProduct.html”,但您的映射是“/getProductDetailsForReview.html”,但我认为这是一个错字。您在评论中提到的问题很可能是由于响应中的错误 contentTypes。

假设您使用 CORS 过滤器,例如在接受的答案CORS Filter not working as intended 中建议。以下将起作用

<script>
    function submitLogin() 
        var obj = 
            "productMasterId": "1"
        ;

        $.ajax(
            url: "http://XXXXXXXX.com/getProductDetailsForReview",
            type: 'POST',
            crossDomain: true,
            success: function (response) 
                alert("done");
                alert(response);
            ,
            error: function (response) 
                alert(response);
            
        );

    
</script>
<a href="javascript:submitLogin()">click </a>

请注意,我已删除 contentType 并且已从请求中删除了 html。原因是如果 html 存在,则响应的 contentType 将设置为 text/html,与您在请求中设置的不同

@RequestMapping("/getProductDetailsForReview")
    public @ResponseBody PaymentForm getProductDetailsForReview(@RequestBody PaymentForm paymentForm, HttpServletResponse response) 
        log.debug("Start of method getProductDetailsForReview");
        PaymentForm form = userPaymentService.getProductForReview(paymentForm);
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        log.debug("End of method getProductDetailsForReview");
        return form;
    

结合这三者,适当的 CORS 过滤器,稍微修改的 Ajax 调用,以及修改后的服务器映射,您就会让它正常工作, 最好的


在更新中反映您的评论。 Spring MVC 使用内容协商来推断应该是什么响应内容类型,并且后缀优先于其他选项。我认为这是你的问题,看看

http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

话虽如此,请尝试将 favorPathExtension = "false" 属性添加到您的 Spring MVC 配置中,

 <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
...
        <property name="favorPathExtension" value="false" />
...
</bean>

让我知道它是如何锻炼的

【讨论】:

我无法从我的操作 /getProductDetailsForReview 中删除 html,因为我在 web.xml 中的调度程序 servlet url-pattern 中提供了 *.html。我还使用 CORS 过滤器更新了我的问题。 我已经用我可以在浏览器中看到的请求和响应标头更新了我的问题。请检查。我可以弄清楚在响应标头中我将内容类型设置为 text/html 并且我期待 json。可能就是这个问题。请建议 这正是问题所在,很可能是由于上述原因,您能否粘贴您的 spring mvc 配置的 XML 我遇到了一个链接,即spring.io/guides/gs/rest-service-cors 它也适用于 GAE。我已经编辑了我的问题。 根据您所写的一切,CORS 已经在为您工作。检查您发布的标头,请求接受 application/json,但响应给出的是 text/html,这就是您获得 415 Unsupported Media Type 的原因。你在响应中得到这个 contentType 的原因是因为你的请求有 .html 作为后缀,所以 Spring MVC 推断响应类型应该是 text/html。在你的 contentNegotionManager bean 中设置 ,我敢打赌一切都会开始工作:)

以上是关于无法在 Google 应用引擎中处理跨域 json 请求并在 json 中获得响应的主要内容,如果未能解决你的问题,请参考以下文章

在 Google 应用引擎 Python 中提供静态 html

无法从应用引擎访问 Google 云功能(带有入口控制)

google浏览器无法本地测试ajax

谷歌电子表格和谷歌应用引擎如何实现交互

Ajax 跨域和同源策略的解释和使用,使用jQuery跨域,模板引擎artTemplate的使用详细解释+案例

如何在 Google App Engine 中解析 JSON?