2015-10-20 5 views
0

В настоящее время я пытаюсь разработать приложение RESTful, используя Angular on font-end и Spring MVC на back-end (@RestController). Я уже реализовал несколько GET и POST метода для извлечения или сохранения данных, однако теперь я столкнулся с проблемой с методом один POST:Угловой JS и Spring MVC @RestController - статус POST 0

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) книга действительно заимствует. Я уже искал статус: 0 ответ (также на stackoverflow) и, к сожалению, не нашел правильного решения моей проблемы. Буду признателен за любую помощь. Вот мой метод RestController:

@RestController 
public class BookRestPostController { 

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

Edit: Я забыл упомянуть, что я использую @RestController аннотацию на моем классе контроллера. Он автоматически включает @ResponseBody.

+0

- это серверное приложение и клиентское приложение, развернутые на одном и том же веб-сервере? –

+0

На разных. – pokemzok

+0

Да, это проблема. завтра я объясню вам, как с этим бороться, потому что здесь слишком поздно. –

ответ

2

По соображениям безопасности некоторые браузеры не позволяют сделать запрос Ajax, которые не являются в то же происхождение. Если вы хотите узнать больше о CORS, я рекомендую статью this. У вас есть несколько вариантов решения вашей проблемы.

Первый, если вы хотите сохранить свою структуру текущих проектов, оба проекта существуют на разных серверах. Вы должны включить поддержку CORS (Cross-source sharing sharing) на стороне сервера, и я вижу, что вы используете новый Spring Framework, поэтому вы можете просто добавить одну аннотацию , которая позволит поддерживать поддержку CORS. Аннотация составляет @CrossOrigin см. this артикул.

@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() {} 

} 

Это, вероятно, самый чистый способ для достижения этой цели. Другими двумя альтернативами являются создание прокси-сервера на стороне сервера или развертывание как клиентского, так и серверного кода на одном сервере, но мое предложение не использует прокси-сервер или тот же сервер!

С простыми словами, браузер запросит предполетный запрос, он отправит перед каждым запросом один дополнительный запрос типа OPTIONS с конкретными заголовками (Access-Control-Request-Method and Access-Control-Request-Headers). Эти заголовки запроса будут запрашивать у сервера разрешения на выполнение фактического запроса. Ваш предполетный ответ должен подтвердить эти заголовки, чтобы фактический запрос работал.

+0

Я реализовал фильтр, и, к сожалению, это не помогло. Интересно, что даже без фильтра почти все мои запросы GET и POST завершаются успешно. Только тот, который я описал, отличается. – pokemzok

+1

Когда вы открываете вкладку сети в своем браузере, вы видите запрос параметров? –

+0

Я не проверял это, и благодаря вашему наконечнику я нашел проблему. Я установил атрибут действия в форме, которая была отменяет действие post в моей службе. Благодаря! – pokemzok

0

Черт раздражает bugOrFeature ... добавить @ResponseBody аннотацию

public @ResponseBody BorrowDTO borrow 
+0

У парня есть RestController, поэтому аннотацию ResponseBody автоматически добавляется. –

+0

Когда Петр ответил, не было никакой информации об этом. Это моя ошибка. – pokemzok

Смежные вопросы