Spring-MVC использует конвертер для загрузки объекта из переменной пути, но для возврата нужно 404
TL;DR - есть ли способ выдать ошибку из зарегистрированного преобразователя типов во время фазы привязки данных MVC, чтобы он возвращал ответ с определенным кодом состояния HTTP? Т.е. если мой конвертер не может найти объект из источника конверсии, могу ли я вернуть 404?
У меня есть POJO:
public class Goofball {
private String id = "new";
// others
public String getName () { ... }
public void setName (String name) { ... }
}
и я использую StringToGoofballConverter, чтобы создать пустой объект, когда "new".equals(id)
или попробуйте загрузить Goofball из базы данных, если она существует:
public Goofball convert(String idOrNew) {
Goofball result = null;
log.debug("Trying to convert " + idOrNew + " to Goofball");
if ("new".equalsIgnoreCase(idOrNew))
{
result = new Goofball ();
result.setId("new");
}
else
{
try
{
result = this.repository.findOne(idOrNew);
}
catch (Throwable ex)
{
log.error (ex);
}
if (result == null)
{
throw new GoofballNotFoundException(idOrNew);
}
}
return result;
}
Этот конвертер используется Spring, когда запрос соответствует этой конечной точке:
@RequestMapping(value = "/admin/goofballs/{goofball}", method=RequestMethod.POST)
public String createOrEditGoofball (@ModelAttribute("goofball") @Valid Goofball object, BindingResult result, Model model) {
// ... handle the post and save the goofball if there were no binding errors, then return the template string name
}
Это все работает довольно хорошо, поскольку GET запрашивает /admin/goofballs/new
а также /admin/goofballs/1234
Плавно работать в контроллере как для создания новых объектов, так и для редактирования существующих. Проблема в том, что если я выдаю запрос с поддельным идентификатором, то это не new
и также не существует в базе данных, я хочу вернуть 404. В настоящее время конвертер выдает пользовательское исключение:
@ResponseStatus(value= HttpStatus.NOT_FOUND, reason="Goofball Not Found") //404
public class GoofballNotFoundException extends RuntimeException {
private static final long serialVersionUID = 422445187706673678L;
public GoofballNotFoundException(String id){
super("GoofballNotFoundException with id=" + id);
}
}
но я начал с простого IllegalArgumentException, как рекомендовано в документации Spring. В любом случае в результате Spring возвращает ответ с HTTP-статусом 400.
Это заставляет меня думать, что я неправильно использую интерфейс Converter, но этот подход рекомендуется в документации @ModelAttribute.
Итак, еще раз вопрос: есть ли способ выдать ошибку из зарегистрированного преобразователя типов во время фазы привязки данных, чтобы он возвращал ответ с определенным кодом состояния HTTP?
1 ответ
Отвечая на мой собственный вопрос:
+ Изменить StringToGoofballConverter
просто вернуться null
для не найденного лица вместо того, чтобы бросать IllegalArgumentException
или пользовательское исключение. @Controller
Затем метод будет Goofball
объект, который имеет null
идентификатор (например, идентификатор не является "новым" или значением элемента пути). В этот момент я могу бросить GoofballNotFoundException
или любой другой @ResponseStatus
исключение оттуда, в методе контроллера, чтобы повлиять на код состояния ответа.