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
}
只要对/admin/goofballs/new
和/admin/goofballs/1234
的GET请求在控制器中顺利工作以创建新对象和编辑现有对象,这一切都能很好地工作。问题是如果我发出一个伪造的id请求,一个不是new
并且数据库中也不存在的请求我想返回404.目前转换器抛出一个自定义异常:< / p>
@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开始为recommended in the Spring docs。在任何一种情况下,结果都是Spring返回HTTP状态为400的响应。
这让我觉得我误用了Converter接口但是那个方法appears to be recommended by the @ModelAttribute docs。
所以,问题是:有没有办法在数据绑定阶段从注册类型转换器中抛出错误,以便它返回具有特定HTTP状态代码的响应?
答案 0 :(得分:1)
回答我自己的问题:
将StringToGoofballConverter
更改为仅针对未发现的实体返回null
,而不是抛出IllegalArgumentException
或自定义异常。然后,@Controller
方法将被赋予Goofball
对象,该对象具有null
id(例如,id不是“new”,也不是path元素值)。此时,我可以在控制器方法中抛出GoofballNotFoundException
或任何其他@ResponseStatus
异常,以影响响应状态代码。