11

如何在 Spring MVC 控制器中正确使用 RESTful 删除?我有 DAO 在尝试删除某些项目时返回布尔值。

我正在尝试删除项目。如果一切正常,只需显示项目列表(已删除的项目将不再存在)。如果无法删除项目,请重定向到详细信息页面并说明无法删除的原因。

我需要一些特殊的响应状态或类似的东西吗?我的方法是 RESTful 的吗?

@RequestMapping(value = "items/{id}", method = RequestMethod.DELETE)
public String delete(@PathVariable("id") int itemId, Model model) {
    Item item = itemDao.get(id);

    // true -> can delete
    // false -> cannot delete, f.e. is FK reference somewhere
    boolean wasOk = itemDao.delete(item); 

    if (wasOk) {
        return "redirect:/items";
    }

    // will write to user which item couldn't be deleted
    model.addAttribute("item", item);
    return "items/error";
}
4

2 回答 2

19

您应该考虑使用HTTP 状态代码来指示删除操作是否成功,而不是重定向。例如HTTP 200 OK(或HTTP 204 No Content)表示操作成功,HTTP 404 Not Found如果您尝试访问的资源不存在,HTTP 405 Method Not Allowed如果不允许删除操作等。根据响应状态,客户端可以决定是否保留引用的资源(在您的情况下是由 引用的对象item/{id})。

由于您使用的是 Spring,因此您可以使用适当的@ResponseStatus注释您的控制器方法,例如 @ResponseStatus(value = HttpStatus.NO_CONTENT)

另外,Spring默认HandlerExceptionResolver已经提供了一些状态码。

于 2012-04-26T20:12:54.113 回答
12

如果您可以由用户修复删除问题,那么这似乎没问题。如果用户无能为力,那么错误代码状态可能会更正确。我可以想象的唯一删除失败是授权失败,这将是 401。这可以通过向您的方法“HttpServletResponse response”添加一个参数来设置。你的代码会变成这样:

@RequestMapping(value = "items/{id}", method = RequestMethod.DELETE)
public String delete(@PathVariable("id") int itemId, Model model, HttpServletReponse response) {
    Item item = itemDao.get(id);

    // true -> can delete
    // false -> cannot delete, f.e. is FK reference somewhere
    boolean wasOk = itemDao.delete(item); 

    if (!wasOk) {
        // will write to user which item couldn't be deleted
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        model.addAttribute("item", item);
        return "items/error";   
    }

    return "redirect:/items";
}

您可以根据需要替换其他状态代码,但这是一般的想法。

您还可以执行以下操作:

    if (!wasOk) {
        throw new DataAccessException("Unable to delete item: " + item);
    }

然后在同一个类中有一个带注释的错误处理程序

@ExceptionHandler(DataAccessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleDataAccessException(DataAccessException ex) {
    // Do some stuff
    return "errorView";
}
于 2012-04-26T20:25:11.767 回答