Smartgwt RestDataSource与SpringMVC和跨客户端 [英] Smartgwt RestDataSource with SpringMVC and cross-client

查看:270
本文介绍了Smartgwt RestDataSource与SpringMVC和跨客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过大量工作后,我有一个现有的后端Web服务应用程序,由Spring-RS,Spring MVC,Spring控制器提供支持,这些控制器在Spring框架内使用Jackson来将响应转换为JSON。



以下是WEB-INF / myproject-servlet.xml的一部分

 < mvc:annotation-driven> 
< mvc:message-converters register-defaults =true>
< bean class =org.springframework.http.converter.json.MappingJackson2HttpMessageConverter>
< property name =objectMapper>
< bean class =com.fasterxml.jackson.databind.ObjectMapper>

< property name =dateFormat>
< bean class =java.text.SimpleDateFormat>
< constructor-arg type =java.lang.Stringvalue =yyyy-MM-dd>< / constructor-arg>
< / bean>
< / property>
< / bean>
< / property>
< / bean>
< / mvc:message-converters>
< / mvc:annotation-driven>

< bean id =jsonHttpMessageConverterclass =org.springframework.http.converter.json.MappingJackson2HttpMessageConverter>
< property name =supportedMediaTypesvalue =application / json/>
< / bean>

< bean class =org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter>
< property name =messageConverters>
< list>
< ref bean =jsonHttpMessageConverter/>
< / list>
< / property>
< / bean>

这个网络服务应用程序非常好!我可以部署WAR到我的本地tomcat,它部署好。我可以单元测试他控制器,以确保URL是正确的,并且Web应用程序在Spring中正确配置。我可以点击URL,并获得JSON数据完全按照我的预期。网址是:

  http:// mylocalhost / myproject / invoices / invoiceId / 1 



返回1张发票。



现在,我运行的是SmartGWT网络应用程序,免费版本,我有一个RestDataScource控制器。我之前编写过许多SmartGWT web应用程序,这些应用程序都包含:实体,dao,服务层,控制器和数据源。有了这一点,根本没有交叉客户端问题,控制器和数据源在同一个应用程序。我不反对这样做,但我想尝试将它们分开。



我最近看到这不工作!我的SmartGWT web应用程序本地运行在Jetty开发模式下。起始网址为:

  http:// mylocalhost:8888 / myapp 

当尝试在

上调用后端时

  http:// mylocalhost:8080 / my-ws,然后我的listgrid给我一个警告消息。 

如果我只能添加一行:RPCManager.setAllowCrossDomainCalls(true);
我在RESTDataSource中添加它吗?我在哪里添加这个?它真的只是使一切工作吗?还有其他我需要添加吗?



所以,我看着XJSONDataSource,我看到我需要对我的RestDataSource进行一些更改,将其转换为XJsonDataSource。这里有一些伟大的信息与另一个发布,他们建议添加:

  //我在哪里放这行?控制器或数据源
String callbackString = request.getParameter(callback);

//我在哪里放这个代码?控制器或数据源
response.setContentType(text / X-JSON);
response.getWriter()。write(callbackString +(+ JSONstring +));
response.setStatus(HttpServletResponse.SC_OK);

我不知道这个代码在哪里,所以我需要一些额外的帮助。就控制器而言,这里是它的一部分:

  @RequestMapping(value =/ invoiceId方法= RequestMethod.GET,headers =Accept = application / json)
public @ResponseBody
InvoiceDetailDTO getContactTypeByUserId(@RequestBody String invoiceNumber)
{
InvoiceDetailDTO invoiceDetailDto = invoiceService.getInvoiceDetail (发票号码);

// invoiceDetailDto由Spring自动转换为JSON
return invoiceDetailDto;
}

在上面的代码中有request和response控制器,我该怎么走?



最后,我想只使用我的RestDataSource并调整它的工作方式,我想要的,忽略任何这些跨站点问题。如果我需要使用XJSONDataSource,我只需要一些真正好的例子,以及如何根据需要调整控制器的例子。



谢谢!

解决方案

RPCManager.setAllowCrossDomainCalls(true); 应在初始化的早期阶段 - onModuleLoad())。



getContactTypeByUserId 添加 Access-Control-Allow-Origin 作为具有正确值的响应标头。

检查 http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

基于 http://forums.smartclient.com/showthread.php?t=15487 ,SmartGWT应处理跨域



在最糟糕的情况下,您可能必须发送JSONP样式响应以及所需的标头才能使其正常工作。
$ b $在这种情况下,它可能最好有一个单独的方法,类似于以下,以服务SmartGWT请求。

我没有使用XJSONDataSource,以下是只是一个指南。

  //使用稍微不同的URI来区别于其他控制器方法
@RequestMapping(value =/ invoiceId / sgwt,method = RequestMethod.GET,headers =Accept = application / json)
public @ResponseBody String getContactTypeByUserIdForSgwt(@RequestBody String invoiceNumber,
HttpServletRequest请求,HttpServletResponse响应){

可以重用正常的控制器方法
InvoiceDetailDTO invoiceDetailDto = getContactTypeByUserId(invoiceNumber);

//使用jackson或其他工具将invoiceDetailDto转换为JSON字符串
String JSONstring = convertToJson(invoiceDetailDto);

//必须检查SmartGWT请求以确保发送回调名称的实际参数名称
String callbackString = request.getParameter(callback);

response.setContentType(text / X-JSON);

return callbackString +(+ JSONstring +);
}






更新



可能是一个好主意,清除代码(或从头开始/最小)由于以前的努力遗留下来。



在解决这个问题有三个阶段:

1.使SmartGWT正常工作,而不使用服务

2.使服务正常工作CORS请求

3.切换SmartGWT以使用服务



阶段1应用于消除任何客户端问题。

如果客户端在部署在同一主机/域中时使用服务,则跳到第2阶段。



阶段1

为此,可以使用提供静态响应的数据网址,如 RestDataSource JSON响应

将示例响应放在类似于 test.json 并使其可从客户端Web应用程序访问。

将DataSource代码保持最小并使用 setDataURL(); 测试.json 位置。



test.json - 更改字段名称和值

  {
response:{
status:0,
startRow: 0,
endRow:3,
totalRows:3,
data:[
{field1:value,field2:value},
{field1: value,field2:value},
{field1:value,field2:value},
]
}
} code>

DataSource

  TestDS扩展RestDataSource {

private static TestDS instance = new TestDS();

public static TestDS getInstance(){
return instance;
}

private TestDS(){
setDataURL(data / test.json); // => http://< client-app-host:port> /< context> /data/test.json
setDataFormat(DSDataFormat.JSON);
// setClientOnly(true);

DataSourceTextField field1 = new DataSourceTextField(field1,Field1);
DataSourceTextField field2 = new DataSourceTextField(field2,Field 2);

setFields(field1,field2);
}
}

阶段2 >
检查引用的其他详细信息。



失败的预览CORS请求的标头位于 localhost:8118托管的网页,以及托管在 localhost:7117 中的服务。

由于端口不同而失败。在不同的方案(https / ftp /文件/ etc。)或不同的主机/域也会失败。

 主机:localhost :7117 
User-Agent:Mozilla / 5.0(X11; Ubuntu; Linux x86_64; rv:22.0)Gecko / 20100101 Firefox / 22.0
Accept:text / html,application / xhtml + xml,application / xml ; q = 0.9,* / *; q = 0.8
Accept-Language:en-US,en; q = 0.5
Accept-Encoding:gzip,deflate
原产地:http:// local_host:8118< =表示应该授予访问的起点
访问控制请求方法:GET <=指示将在实际请求中使用的方法
访问控制请求 - 标题:content-type< =表示将在实际请求中使用的标题

服务器:Apache-Coyote / 1.1
允许:GET,HEAD,POST,PUT,DELETE,TRACE ,OPTIONS
Content-Length:0

成功请求的请求/响应头对。

  Host:localhost:7117 
User-Agent:Mozilla / 5.0(X11; Ubuntu; Linux x86_64; rv:22.0)Gecko / 20100101 Firefox / 22.0
Accept:text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8
Accept-Language:en -US,en; q = 0.5
Accept-Encoding:gzip,deflate
原产地:http:// localhost:8118
访问控制请求方法:GET
访问-Control-Request-Headers:content-type

服务器:Apache-Coyote / 1.1
访问控制允许原产地:http:// localhost:8118
访问 - 控制允许方法:GET
访问控制允许标题:内容类型
允许:GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS
Content-Length:0

Host:localhost:7117
User-Agent:Mozilla / 5.0(X11; Ubuntu; Linux x86_64; rv:22.0)Gecko / 20100101 Firefox / 22.0
Accept:application / json,text / javascript,* / *; q = 0.01
Accept-Language:en-US,en; q = 0.5
Accept-Encoding:gzip,deflate
Content-Type:application / json
Referer:http: //localhost:8118/cors-test.html
原产地:http:// localhost:8118

服务器:Apache-Coyote / 1.1
访问控制:*
Content-Type:application / json
Transfer-Encoding:chunked

为了支持CORS请求,服务后端必须正确响应预检OPTIONS请求,而不仅仅是服务调用。

这可以使用ServletFilter完成。

 < filter> 
< filter-name> corsfilter< / filter-name>
< filter-class> test.CorsFilter< / filter-class>
< / filter>

< filter-mapping>
< filter-name> corsfilter< / filter-name>
< url-pattern> / *< / url-pattern>
< / filter-mapping>

public class CorsFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain)
throws ServletException,IOException {
if(request.getHeader(Access-Control-Request-Method)!= null&OPTIONS.equals(request.getMethod())){
response.addHeader(Access- Allow-Origin,http:// localhost:8118);

//允许的方法列表,Access-Control-Request-Method必须是此
response.addHeader(Access-Control-Allow-Methods,GET)的子集;
//允许的头部列表,Access-Control-Request-Headers必须是这个
的一个子集response.addHeader(Access-Control-Allow-Headers,Content-Type,If-Modified -以来);

//预飞行请求缓存超时
// response.addHeader(Access-Control-Max-Age,60);
}
filterChain.doFilter(request,response);
}
}

@RequestMapping(method = RequestMethod.GET,value =/ values,produce = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity< Map> getValues(){
List< Map< String,Object>> values = getValues(); //处理实际的数据处理并返回一个适合响应的列表

SgwtResponse sgwtResponse = new SgwtResponse(); //具有基本(公共)属性的POJO
sgwtResponse.status = 0L;
sgwtResponse.startRow = 0L;
sgwtResponse.endRow = Long.valueOf(values.size());
sgwtResponse.totalRows = sgwtResponse.startRow + sgwtResponse.endRow;
sgwtResponse.data = values; // java.util.List

Map< String,SgwtResponse> jsonData = new HashMap< String,SgwtResponse>();
jsonData.put(response,sgwtResponse);

HttpHeaders headers = new HttpHeaders();
headers.add(Access-Control-Allow-Origin,*); // required

return new ResponseEntity< Map>(jsonData,headers,HttpStatus.OK);
}

使用jQuery使用XHR检索JSON响应的简单测试页。 br>
更改URL并在客户端Web应用程序中部署以直接测试服务,而不使用SmartGWT。

 < DOCTYPE html> 
< html>
< head>
< script src =http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js>< / script>
< script>
$(document).ready(function(){
$(#retrieve)。click(function(){
$ .ajax({
type:GET ,
contentType:application / json,
url:< URL-of-service>,
dataType:json,
success:function ,status,xhr){
$(#content).text(JSON.stringify(data,null,2));
},
error:function(xhr,status,错误){
$(#content)。text(Unable to retrieve data);
}
});
});
} ;
< / script>
< / head>
< body>
< input type =buttonid =retrievevalue =Retrieve/>
< div id =content/>
< / body>
< / html>

If-Modified-Since Access-Control-Allow-Headers 中为SmartGWT。

使用 RPCManager.setAllowCrossDomainCalls(true);

大多数现代浏览器(浏览器兼容性 1 )和SmartGWT RestDataSource 支持CORS请求。

仅当您必须依赖JSONP时才使用XJSONDataSource,因为浏览器与CORS请求不兼容。



发送 Access-Control-Allow-Origin:* 对于飞行前请求,将允许任何网站对服务进行跨域调用,这可能会引起安全问题,加上 * 不能用于某些CORS请求。

更好的方法是指定允许跨域请求的确切站点 - Access-Control- Allow-Origin:http://www.foo.com

在这种情况下可能不需要,但请检查访问控制允许原点多原域?,如果需要,找到允许多个站点发出CORS请求的方法。 / p>

参考文献:

[1] https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS

[2] http://java-success.blogspot.com/2012/11/cors-and-jquery -with-spring-mvc-restful.html


After a lot of work, I have an existing back-end web services application that is powered by Spring-RS, Spring MVC, Spring controllers, and these controllers user Jackson within the Spring framework to convert responses to JSON.

Here is part of the WEB-INF/myproject-servlet.xml

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
          <property name="objectMapper">
             <bean class="com.fasterxml.jackson.databind.ObjectMapper">

                     <property name="dateFormat">
                        <bean class="java.text.SimpleDateFormat">
                            <constructor-arg type="java.lang.String" value="yyyy-MM-dd"></constructor-arg>
                        </bean>
                     </property>
             </bean>
          </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

<bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="supportedMediaTypes" value="application/json"/>
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  <property name="messageConverters">
      <list>
        <ref bean="jsonHttpMessageConverter" />
      </list>
  </property>
</bean>

This web-services app works great! I can deploy the WAR to my local tomcat, and it deploys fine. I can unit test he controller to make sure the URL is correct and the web-app is correct configured within Spring. I can hit the URL and get JSON data back exactly as I expected it to. The url is:

http://mylocalhost/myproject/invoices/invoiceId/1

returns 1 invoice.

Now, I am running a SmartGWT web-app, the free version, and I have a RestDataScource controller. I have written many SmartGWT web-apps before, and these apps were all inclusive: entities, dao's, service layer, controllers, and datasources. With this, there was no cross-client issues at all provided the controllers and the datasources were within the same app. And I am not against doing that again, but I want to try to separate them apart.

I just recently saw that this does not work!!! With my SmartGWT web-app running locally within Jetty for development mode. The starting URL is:

     http://mylocalhost:8888/myapp

And when this tries to call the back-end on

    http://mylocalhost:8080/my-ws, then my listgrid gives me a warning message.

If I can just add the one line: RPCManager.setAllowCrossDomainCalls(true); Do I add this within my RESTDataSource? Where do I add this to? And will it really just make everything work? Is there anything else I need to add?

So, I was looking at XJSONDataSource and I saw that I needed to make a few changes to my RestDataSource to convert it to a XJsonDataSource. There is some great information here with another posting and they suggested adding:

   // Where do I put this line?   the controller or the datasource
   String callbackString = request.getParameter("callback");

   // Where do I put this code?  the controller or the datasource
   response.setContentType("text/X-JSON");
   response.getWriter().write( callbackString + " ( " + JSONstring + " ) " );
   response.setStatus(HttpServletResponse.SC_OK);  

I am not sure where this code goes, so I need some extra help there. As far as the controller goes, here is part of what it looks like:

    @RequestMapping(value = "/invoiceId", method = RequestMethod.GET, headers = "Accept=application/json")
    public @ResponseBody
        InvoiceDetailDTO getContactTypeByUserId(@RequestBody String invoiceNumber)
     {
         InvoiceDetailDTO invoiceDetailDto = invoiceService.getInvoiceDetail(invoiceNumber);

        // invoiceDetailDto is automatically converted to JSON by Spring
        return invoiceDetailDto;
     }

In the code above with "request" and "response" have to go into the controller, how do I go about that?

Ultimately, I'd love to just use my RestDataSource and tweak it to work the way I want it to, and ignore any of these cross-site issues. If I do need to use XJSONDataSource, I just need some real good examples, and an example on how to tweak my controllers if needed.

Thanks!

解决方案

RPCManager.setAllowCrossDomainCalls(true); should be called during early stages of initialization (e.g.- onModuleLoad()).

getContactTypeByUserId might have to add Access-Control-Allow-Origin as a response header with proper value.
Check http://en.wikipedia.org/wiki/Cross-origin_resource_sharing.
Based on http://forums.smartclient.com/showthread.php?t=15487, SmartGWT should handle cross domain requests on its own.

As a worst case scenario, you might have to send a JSONP style response along with required headers to get this working.
In that case, its probably best to have a separate method, similar to following, to serve SmartGWT requests.
I haven't worked with XJSONDataSource, so following is only a guideline.

// use a slightly different URI to distinguish from other controller method
@RequestMapping(value = "/invoiceId/sgwt", method = RequestMethod.GET, headers = "Accept=application/json")
public @ResponseBody String getContactTypeByUserIdForSgwt(@RequestBody String invoiceNumber,
        HttpServletRequest request, HttpServletResponse response) {

     // can reuse normal controller method
     InvoiceDetailDTO invoiceDetailDto = getContactTypeByUserId(invoiceNumber);

     // use jackson or other tool to convert invoiceDetailDto to a JSON string
     String JSONstring = convertToJson(invoiceDetailDto);

    // will have to check SmartGWT request to make sure actual parameter name that send the callback name
    String callbackString = request.getParameter("callback"); 

    response.setContentType("text/X-JSON");

    return  callbackString + " ( " + JSONstring + " ) " ;
 }


Update

Probably a good idea to clean up code (or start from scratch/minimum) due to left overs from previous efforts.

There are three phases in solving this:
1. Get SmartGWT to work correctly, without using the service
2. Get the service to work correctly with CORS requests
3. Switch SmartGWT to use the service

Phase 1 should be used to iron out any client side issues.
Skip to phase 2, if client is working with the service when deployed in the same host/domain.

Phase 1
For this, its possible to use a data URL that provide a static response, as explained in RestDataSource JSON responses.
Place the sample response in a file similar to test.json and make it accessible from client web application.
Keep the DataSource code to a minimum and use setDataURL(); with test.json location.

test.json - change (and add if needed) field names and values

{    
 response:{
    status:0,
    startRow:0,
    endRow:3,
    totalRows:3,
    data:[
        {field1:"value", field2:"value"},
        {field1:"value", field2:"value"},
        {field1:"value", field2:"value"},
    ]
 }
}

DataSource

public class TestDS extends RestDataSource {

    private static TestDS instance = new TestDS();

    public static TestDS getInstance() {
        return instance;
    }

    private TestDS() {
        setDataURL("data/test.json");       // => http://<client-app-host:port>/<context>/data/test.json
        setDataFormat(DSDataFormat.JSON);
        // setClientOnly(true);

        DataSourceTextField field1 = new DataSourceTextField("field1", "Field 1");
        DataSourceTextField field2 = new DataSourceTextField("field2", "Field 2");

        setFields(field1, field2);
    }
}

Phase 2
Check references for additional details.

Headers of a failed preflight CORS request made from a page hosted in localhost:8118, and service hosted in localhost:7117.
Failed due to different port. Will fail on different scheme (https/ftp/file/etc.) or different host/domain as well.

Host: localhost:7117
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost:8118                   <= indicates origin to which access should be granted
Access-Control-Request-Method: GET              <= indicates the method that will be used in actual request
Access-Control-Request-Headers: content-type    <= indicates the headers that will be used in actual request

Server: Apache-Coyote/1.1
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS
Content-Length: 0

Request/response header pairs of a successful request.

Host: localhost:7117
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost:8118
Access-Control-Request-Method: GET
Access-Control-Request-Headers: content-type

Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: http://localhost:8118
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Content-Type
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS
Content-Length: 0

Host: localhost:7117
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Referer: http://localhost:8118/cors-test.html
Origin: http://localhost:8118

Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: *
Content-Type: application/json
Transfer-Encoding: chunked

In order to support CORS requests, service backend must respond correctly to the preflight OPTIONS request, not just the service call.
This can be done using a ServletFilter.

<filter>
    <filter-name>corsfilter</filter-name>
    <filter-class>test.CorsFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>corsfilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

public class CorsFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
            response.addHeader("Access-Control-Allow-Origin", "http://localhost:8118");

            // list of allowed methods, Access-Control-Request-Method must be a subset of this
            response.addHeader("Access-Control-Allow-Methods", "GET");
            // list of allowed headers, Access-Control-Request-Headers must be a subset of this
            response.addHeader("Access-Control-Allow-Headers", "Content-Type, If-Modified-Since");

            // pre-flight request cache timeout
            // response.addHeader("Access-Control-Max-Age", "60");
        }
        filterChain.doFilter(request, response);
    }
}

@RequestMapping(method = RequestMethod.GET, value = "/values", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map> getValues() {
    List<Map<String, Object>> values = getValues(); // handle actual data processing and return a list suitable for response

    SgwtResponse sgwtResponse = new SgwtResponse(); // A POJO with basic (public) attributes
    sgwtResponse.status = 0L;
    sgwtResponse.startRow = 0L;
    sgwtResponse.endRow = Long.valueOf(values.size());
    sgwtResponse.totalRows = sgwtResponse.startRow + sgwtResponse.endRow;
    sgwtResponse.data = values; // java.util.List

    Map<String, SgwtResponse> jsonData = new HashMap<String, SgwtResponse>();
    jsonData.put("response", sgwtResponse);

    HttpHeaders headers = new HttpHeaders();
    headers.add("Access-Control-Allow-Origin", "*"); // required

    return new ResponseEntity<Map>(jsonData, headers, HttpStatus.OK);
}

A simple test page that use jQuery to retrieve a JSON response using XHR.
Change URL and deploy in client web application to directly test service, without using SmartGWT.

<!DOCTYPE html>
<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script>
            $(document).ready(function () {
                $("#retrieve").click(function () {
                    $.ajax({
                        type: "GET",
                        contentType: "application/json",
                        url: "<URL-of-service>",
                        dataType: "json",
                        success: function (data, status, xhr) {
                            $("#content").text(JSON.stringify(data, null, 2));
                        },
                        error: function (xhr, status, error) {
                            $("#content").text("Unable to retrieve data");
                        }
                    });
                });
            });
        </script>
    </head>
    <body>
        <input type="button" id="retrieve" value="Retrieve"/>
        <div id="content"/>
    </body>
</html>

If-Modified-Since header was required in Access-Control-Allow-Headers for SmartGWT.
Use RPCManager.setAllowCrossDomainCalls(true); during SmartGWT initialization to avoid the warning.

Most modern browsers (Browser compatibility1) and SmartGWT RestDataSource support CORS requests.
Use XJSONDataSource only when you have to rely on JSONP, due to browser incompatibility with CORS requests.

Sending Access-Control-Allow-Origin: * for pre-flight request will allow any site to make cross domain calls to the service, which could pose a security issue, plus * can not be used in certain CORS requests.
Better approach is to specify the exact site to which cross domain requests are allowed - Access-Control-Allow-Origin: http://www.foo.com.
Probably not required in this case, but check Access-Control-Allow-Origin Multiple Origin Domains? if needed, to find ways to allow multiple sites to make CORS requests.

References:
[1] https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS
[2] http://java-success.blogspot.com/2012/11/cors-and-jquery-with-spring-mvc-restful.html

这篇关于Smartgwt RestDataSource与SpringMVC和跨客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆