Ответ 1
Вы можете использовать response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid foo");
У меня есть специальный класс исключений, аннотированный для возврата заданного HttpStatus
:
@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Invalid parameter")
public class BadRequestException extends RuntimeException
{
public BadRequestException(String msg)
{
super(msg);
}
}
Это работает, когда я бросаю BadRequestException
с моего контроллера, но причина всегда является "Invalid parameter", конечно. Есть ли способ установить возвращаемую причину в этом классе? Я хотел бы передать строку, которая будет использоваться в качестве причины.
Спасибо!
Вы можете использовать response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid foo");
Правильный способ - ввести обработчик исключений в ваш контроллер, тогда вы можете установить тело ответа любого кода состояния:
@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.
Если вы опускаете атрибут "reason" в аннотации @ResponseStatus в настраиваемом исключении,
@ResponseStatus(value = HttpStatus.CONFLICT) // 409
public class ChildDataExists extends RuntimeException {
...
затем отбросить исключение
throw new ChildDataExists("Can't delete parent if child row exists.");
Сообщение об исключении приходит как "сообщение" данных в выходе JSON. Кажется, что "причина" в аннотации переопределяет пользовательское поведение.
Аннотации должны быть статичными и не могут быть динамически установлены из вашего класса. Я предлагаю создать подкласс вашего BadRequestException
для каждого типа сценария отказа и аннотировать их по-разному.
Это не просто обходное решение - если вы скрываете детали о том, что пошло не так в сообщении reason
, тогда вы теряете гибкость, потому что любой код, который ловит BadRequestException
, должен будет со всеми сценариями сбоя одинаково.
Самый простой способ просто установить 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();
}
"Причина" необязательна, поэтому вы можете опустить это и реализовать метод абстрактного метода public String, передающий Error. Ссылка: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ResponseStatus.html