В Spring 3 возможно ли динамически установить причину @ResponseStatus? - PullRequest
23 голосов
/ 21 декабря 2011

У меня есть собственный класс исключений, аннотированный для возврата данного HttpStatus:

@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Invalid parameter")
public class BadRequestException extends RuntimeException
{
  public BadRequestException(String msg)
  {
    super(msg);
  }
}

Это работает, когда я выбрасываю BadRequestException из моего контроллера, но причина, конечно, всегда в "Неверный параметр". Есть ли способ установить возвращенную причину в этом классе? Я хотел бы передать строку для использования в качестве причины.

Спасибо!

Ответы [ 6 ]

13 голосов
/ 21 апреля 2016

Если вы опустите атрибут 'reason' в аннотации @ResponseStatus для пользовательского исключения,

@ResponseStatus(value = HttpStatus.CONFLICT)  // 409
public class ChildDataExists extends RuntimeException {
...

затем выбросить исключение

throw new ChildDataExists("Can't delete parent if child row exists.");

Сообщение об исключении поступает как «сообщение» из «данных» в выводе JSON. Кажется, «причина» в аннотации переопределяет пользовательское поведение.

12 голосов
/ 21 декабря 2011

Вы можете использовать response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid foo");

11 голосов
/ 08 апреля 2013

Правильный способ состоит в том, чтобы ввести обработчик исключений в свой контроллер, тогда вы можете установить тело ответа любого кода состояния:

@Controller
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class SomeController {
...
  @ExceptionHandler(BadRequestException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public @ResponseBody
   Map<String,Object> handleIndexNotFoundException(BadRequestException bre,
                                           HttpServletRequest request, HttpServletResponse resp) {
     HashMap<String, Object> result = new HashMap<>();
     result.put("error", true);
     result.put("error_message", bre.getMessage());
     return result;
  }
}

Перемещаясь, вы не должны загрязнять свои классы моделей / исключенийлюбые аннотации и зависимости Spring Web MVC.

Если вы хотите поделиться обработчиком со всеми контроллерами, загляните в @ControllerAdvice.

2 голосов
/ 21 декабря 2011

Аннотации должны быть статическими и не могут быть установлены динамически из вашего класса.Я предлагаю создать подкласс вашего BadRequestException для каждого типа сценария сбоя и аннотировать их по-разному.

Это не просто обходной путь - если вы скрываете детали относительно того, что пошло не так всообщение reason означает, что вы теряете гибкость, потому что любой код, который перехватывает BadRequestException, должен одинаково обрабатывать все сценарии сбоя.

1 голос
/ 27 мая 2013

Самый простой способ просто установить response.setStatus(). Легко и чисто, вы можете изменить его на любой статус, который вам нужен, вместо того, чтобы ex.getStatusCode() добавить свой код.

Тип возврата также на ваш выбор, я использую String b / c, чтобы отобразить это позже.

Кстати, sendError не очень хорошая идея, потому что, например, JBoss добавляет много HTML в ответ.

@ExceptionHandler(CommunicationException.class)
@ResponseBody()
public String handleCommunicationException(CommunicationException ex, HttpServletResponse response) throws IOException{
    response.setStatus(ex.getStatusCode());
    return ex.getStatusMessage();   
}
0 голосов
/ 21 декабря 2011

«Причина» является необязательной, поэтому вы можете опустить ее и реализовать абстрактный метод public String reason, передающий Error. Ссылка: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ResponseStatus.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...