【问题标题】:RESTful web services using jQuery ajax使用 jQuery ajax 的 RESTful Web 服务
【发布时间】:2015-06-19 15:36:38
【问题描述】:

我正在使用 java 的 restful web 服务

@Path("/data")
public class StudentDataService {

    StudentInfo st=new StudentInfo();

    @GET
    @Path("/mydata")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public List<Student> findAll() {
        System.out.println("data returned to the web service");
        return st.populateData();
    }
}

我正在返回一个包含学生姓名、ID、分数等的数据列表。

尝试使用 jQuery ajax 调用此方法如下:

function findAll() {
console.log('findAll');
 $.ajax({  
       type: "GET",  
       url: "http://localhost:9297/StudentData/rest/data/mydata",  
       dataType: "json",  
       crossDomain: true,
       success: function(resp){  
         // we have the response  
         alert("Data\n '" + resp + "'");  
       },  
       error: function(e){  
         alert('Error: ' + e);  
       }  
     });
}

我遇到错误

它还在控制台上给出错误,例如“未找到元素”

【问题讨论】:

  • 对 ajax 使用相对 url。
  • 只是猜测:改为 dataType: "json" 尝试 dataType: "application/json"。如果这不起作用,请告诉我们错误消息是什么...
  • 您对error 函数参数的假设不正确。它实际上是 xhr 对象。更改功能如下function(jqxhr, status, errorMsg),并提示状态和错误信息,然后反馈给我们。我最初的猜测是你有一个跨域问题
  • 将 dataType 更改为 application/json,并将其更改为 function(jqxhr, status, errorMsg) 给出 'Error:parseerror'
  • 附带说明:您的代码不是线程安全的。

标签: java jquery ajax rest jax-rs


【解决方案1】:

您可能会遇到 问题。由于您试图从服务器获取类型 application/json 并且您的请求是跨域的。如果您使用建议的 @user1129947 之类的 Response 对象包装您的 jax-rs 方法,您可以修改响应的标头以允许跨域请求,如下所示:

import javax.ws.rs.core.Response;

@Path("/data")
public class StudentDataService {

    StudentInfo st=new StudentInfo();

    @GET
    @Path("/mydata")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Response findAll() {
        return Response.ok(st.populateData())
            .header("Access-Control-Allow-Origin", "*")
            .build();
    }
}

标题Access-Control-Allow-Origin: * 现在将出现在响应中,这将告诉浏览器允许接收应用程序/json 数据。

请注意,标头中的 * 参数允许任何域访问此资源

如果您想确保只有您的域可以访问此资源,那么您必须将标头的值设置为特定域。

如果您使用自定义标头或最终想要将 cookie 发送到服务器,那么您将不得不处理超出此答案范围的预检请求。

See Mozilla's documentation on CORS for more information

奖金编辑:

对于将 CDI 与 JAX-RS 一起使用的任何人,您可以查看 this filter-interceptor combo 以处理 CORS

【讨论】:

  • 如果它 一个 CORS 问题(我认为不是,基于上面 cmets 中提出的异常),您的解决方案将不起作用,因为preflight 是一个 OPTIONS 请求。对于 CORS 支持,最好的办法是在响应过滤器中实现标头。
  • @peeskillet 在这种情况下,除非他发送自定义请求标头,否则不会发生 OPTIONS 预检。由于它是 GET 请求,因此也没有请求正文,因此由于请求正文内容类型而发生预检的情况不适用。尽管他的消息正文作者的其他问题仍然适用。
  • 我忘了这是一个 GET 请求 :-)
  • 要扩展@Peskillet 的评论,最好在ContainerResponseFilter 中实现这些标头。对于那些使用cdi 的人,可以编写一个CrossDomain 拦截器来修改响应对象并添加必要的标头。在我自己的设置中,我使用了组合,其中 OPTIONS 预检由过滤器处理,实际响应的标头由拦截器处理,因此我可以选择允许跨域的 jax-rs 方法。跨度>
【解决方案2】:

"得到异常:javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class java.util.ArrayList, and Java type java.util.List&lt;dao.Student&gt;, and MIME media type application/json was not found""

您似乎缺少 JSON 提供程序。如果你使用的是 Maven,你可以添加这个依赖

<dependency>
  <groupId>com.fasterxml.jackson.jaxrs</groupId>
  <artifactId>jackson-jaxrs-json-provider</artifactId>
  <version>2.4.0</version>
</dependency>

如果你没有使用 Maven,去寻找这些 jars

您可以搜索并下载所有jar here

然后您可以注册提供程序,方法是将 Jackson 包添加到要扫描的包中(在您的 web.xml 配置中)

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>
            your.packages.to.scan,
            com.fasterxml.jackson.jaxrs.json
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

【讨论】:

    【解决方案3】:

    我建议您使用 gson 在服务器端处理 json,因为它非常易于使用。例如:

    List<Student> items = new ArrayList<>();
    while (...) {
      items.add(new Student(...));
    }
    Gson gson = new Gson();
    return gson.toJson(items);
    

    这只是一个示例,请根据您的要求采用。

    【讨论】:

    • 函数的返回类型应该是什么?
    • 我觉得可以是String + @Produces("application/json")。
    • 如果我返回 String 而不是使用 json 那么在 ajax 调用中应该使用什么数据类型?
    • 你返回 JSON - @Produces("application/json")。所以 dataType 仍然是“application/json”。您还可以使用 @Produces("text/plain") 和 dataType "text/plain" 然后解析返回数据,如 JSON.parse(resp) 成功...
    【解决方案4】:

    使用 javax.ws.rs.core.Response 对象并构建输出。否则有你自己的包装类并包装你的输出并将包装类返回给响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 2011-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-10
      相关资源
      最近更新 更多