Подтвердить что ты не робот

В Spring 3 можно ли динамически установить причину @ResponseStatus?

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

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

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

Спасибо!

4b9b3361

Ответ 1

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

Ответ 2

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

@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.

Ответ 3

Если вы опускаете атрибут "reason" в аннотации @ResponseStatus в настраиваемом исключении,

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

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

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

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

Ответ 4

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

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

Ответ 5

Самый простой способ просто установить 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();   
}