【问题标题】:Angular JS and Spring MVC @RestController - POST status 0Angular JS 和 Spring MVC @RestController - POST 状态 0
【发布时间】:2015-10-20 13:38:48
【问题描述】:

我目前正在尝试在字体端使用 Angular 并在后端使用 Spring MVC (@RestController) 开发 RESTful 应用程序。我已经实现了一些 GET 和 POST 方法来获取或保存数据,但是现在我遇到了一个 POST 方法的问题:

angular.module("app").factory("BorrowerService", function($http, $log){
   var borrowBook = function(borrow){
    $log.debug("Borrowing book: " );
    $log.debug(borrow);
    $http({
        method: 'POST',
        url: 'Zadanie3/borrow',
        data: borrow
   }).then(function successCallback(response) {
        $log.debug("success");
   }, function errorCallback(response) {
          $log.error("failed to borrow the book");
          $log.error(response);
      });
   };
   return{
    borrowBook: borrowBook
   };
});

POST 结果总是 errorCallback 和输出:

failed to borrow the book
Object {data: null, status: 0, config: Object, statusText: ""}

有趣的是,在大多数浏览器(Firefox 除外)上,这本书确实是借用的。我已经搜索过 status:0 response(也在 stackoverflow 上),不幸的是没有找到解决我问题的正确方法。我将不胜感激任何帮助。这是我的 RestController 方法:

@RestController
public class BookRestPostController {

 @RequestMapping(value = "/borrow", method=RequestMethod.POST)
 public BorrowDTO borrow(@RequestBody  BorrowDTO borrow ) {
    borrowerService.borrowBook(borrow);
    return borrow;
 }
}

编辑:我忘了提到我在控制器类上使用了@RestController 注释。它自动包含@ResponseBody。

【问题讨论】:

  • 服务器应用程序和客户端应用程序是否都部署在同一个 Web 服务器中?
  • 是的,这就是问题所在。明天我会告诉你如何处理它,因为这里已经太晚了。
  • 好的,感谢您的帮助。

标签: angularjs rest spring-mvc post


【解决方案1】:

出于安全原因,某些浏览器不允许发出不在同一来源的 ajax 请求。如果您想了解更多关于CORS 的信息,我推荐this 文章。您有多种选择来解决您的问题。

第一个是如果你想保持你当前的项目结构,两个项目 存在于不同的服务器上。你应该在服务器端启用CORS(跨源资源共享)支持,我看到你使用的是更新的Spring Framework,所以你可以添加一个 将启用CORS 支持的注释。注释为@CrossOriginthis 文章。

@RestController
@CrossOrigin(maxAge = 3600)
public class BookRestPostController {

 @RequestMapping(value = "/borrow", method=RequestMethod.POST)
 public BorrowDTO borrow(@RequestBody  BorrowDTO borrow ) {
    borrowerService.borrowBook(borrow);
    return borrow;
 }
}

如果您使用的是旧版本的 Spring Framework,您可以手动操作 - 添加 Filter,这将添加所需的响应标头。见this文章

@Component
public class SimpleCORSFilter implements Filter {

    @Override
    public void init(FilterConfig arg0) throws ServletException {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        HttpServletResponse response=(HttpServletResponse) resp;

        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, resp);
    }

    @Override
    public void destroy() {}

}

这可能是实现目标的最干净的方法。 其他两种选择是创建服务器端代理或在一台服务器上部署客户端和服务器端代码,但我的建议是不要使用代理或同一台服务器!。

浏览器会预检请求,它会在每个请求之前发送一个带有特定标头(Access-Control-Request-Method and Access-Control-Request-Headers)的OPTIONS 类型的额外请求。这些请求标头将向服务器询问发出实际请求的权限。您的预检响应需要确认这些标头才能使实际请求生效。

【讨论】:

  • 我实现了过滤器解决方案,不幸的是它没有帮助。有趣的是,即使没有过滤器,我几乎所有的 GET 和 POST 请求都会成功完成。只有我描述的那个不同。
  • 当您在浏览器上打开网络选项卡时,您会看到选项请求吗?
  • 我没有检查,感谢您的提示,我发现了问题。我在表单上设置了 action 属性,该属性覆盖了我的服务中的 post 操作。谢谢!
【解决方案2】:

该死的烦人的 bugOrFeature... 添加@ResponseBody注解

public @ResponseBody BorrowDTO borrow

【讨论】:

  • 这家伙有RestController,所以会自动添加ResponseBody注解。
  • 当彼得回答时,没有任何信息。这是我的错。
猜你喜欢
  • 2015-05-19
  • 2018-02-03
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
  • 2020-12-29
  • 2015-11-06
  • 1970-01-01
相关资源
最近更新 更多