如何处理REST服务中的无效参数?

时间:2015-01-21 14:39:50

标签: java spring web-services rest

我使用REST spring提供@RestController网络服务。

一般如何处理无效的参数内容?我尝试抛出一个自定义异常,但这会导致客户端出现HTTP 500错误,从而暴露堆栈跟踪。

可能这不是正确的方法。但是应该如何返回简单的错误消息? (用户不会手动访问web服务。只需连接到其他控制器的其他服务)。

4 个答案:

答案 0 :(得分:4)

我正在使用jersey,这是一个简单的例子,它将使用hibernate bean验证框架来验证你的bean。这是一项正在进行的工作,但你应该可以看到它将如何运作非常简单。

@Path("customers")
public class CustomerResource {
    @PUT
    public Response createCustomer(Customer customer) {
        BeanValidator.validate(customer);
        final String rialtoId = customerProvider.createCustomer(customer);

        return Response.ok(rialtoId).build();
    }
}

这是我创建的用于处理bean验证的泛型类。

public class BeanValidator {

    /**
     * Used to validate an order request and all the attached objects that
     * support validation.
     * 
     * @param request
     * @throws ConstraintViolationException
     */
    public static <T> void validate(T request) throws ConstraintViolationException {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();
            Set<ConstraintViolation<T>> constraintViolations = validator.validate(request);
            if (constraintViolations.size() > 0) {
                    throw new ConstraintViolationException(new HashSet<ConstraintViolation<?>>(constraintViolations));
            }
    }
}


@XmlRootElement
public class Customer {

    @NotNull(message = "spCustomerID1 is a required field")
    @Size(max = 60, message = "spCustomerID1 has a max length of 60 characters")
    private String spCustomerID1;

    @Size(max = 60, message = "spCustomerID2 has a max length of 60 characters")
    private String spCustomerID2;

    @Size(max = 60, message = "spCustomerID3 has a max length of 60 characters")
    private String spCustomerID3;

    @NotNull(message = "customerName is a required field")
    @Size(max = 60)
    private String customerName;

    @Valid
    @NotNull(message = "customerAddress is a required field")
    private PostalAddress customerAddress;

    @Valid
    @NotNull(message = "customerContact is a required field")
    private ContactInfo customerContact;

    @Valid
    @NotNull(message = "technicalContact is a required field")
    private ContactInfo technicalContact;
    ... / Getters and Setters
}

然后这是一个简单的ExceptionMapper,它将支持构造一个简单的响应以发送回客户端。请注意,它会将响应类型设置为400 BAD_REQUEST而不是500+服务器端错误。

public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

    public Response toResponse(ConstraintViolationException exception) {

        final StringBuilder strBuilder = new StringBuilder();

        for (ConstraintViolation<?> cv : exception.getConstraintViolations()) {
            strBuilder.append(cv.getPropertyPath().toString() + " " + cv.getMessage());
        }

        RestResponse responseEntity = RestResponse.responseCode(ResponseCode.CONSTRAINT_VIOLATION).setResponseMessage(strBuilder.toString()).build();

        return Response.status(Response.Status.BAD_REQUEST).entity(responseEntity).build();
    }
}

此代码尚未经过测试,但可能有助于了解如何进行验证。在我看来,这是一种非常直接的方式来进行休息服务验证,并允许您报告确切的变量路径以及每个字段的自定义错误消息。

答案 1 :(得分:1)

您应该在应用程序的最外层验证您的参数,然后才能在您的域内进行切换。此时您仍然在HTTP层中,因此可以采取适当的操作来返回400 BAD REQUEST状态。

在此范围内,您可以完全控制如何将此信息转发给您的用户(或其他服务)。如果您只是记录纯文本,或设计自己的描述错误的Json / Xml有效负载,则纯文本就可以了。

答案 2 :(得分:0)

如果我理解你,

然后,通常我认为在每个json响应中都有一个键(或者即使你的响应是XML)也是很好的,这会使进程的状态失效。这个字段可以称为状态。

所以你发回的每个回复都应该有这个status字段,它的值应该表明处理时会发生什么,以及调用者在响应中应该期待什么。

值可以是数字,也可以是文本消息,类似常量消息 您还可以添加另一个字段message,其中包含状态代码的一些text-desc。

现在您必须列出您的服务可能发回的可能的雕像。

例如:

status: 0000 
message: success

status: 0001 
message: invalid_params

status: 0002 
message: invalid_param_value

status: 0003 
message: missing_param,
:
:
etc

所以你的json响应将始终包含这些字段。在其他应该返回的数据中。

现在客户有义务处理这些回复。

JSON示例:

{
"status":"0000",
"message":"success",
"images":[ ... ]
}

{
"status":"0003",
"message":"missing_param"
}

如果您注意到非0000状态,则不会发回其他数据。 告诉客户我们有“这个问题”。

或者您可以通过向错误消息常量添加:来提供更多信息,告知有关错误的更多信息:

前,

{
"status":"0003",
"message":"missing_param:album_id"
}

告诉用户,缺少参数,并且album_id

现在您可以编写所有可能的status响应,并message 这将是您的服务文档的一部分。

答案 3 :(得分:0)

我手动验证你的参数,你可以抛出一个特定的异常。然后,您可以将异常映射到特定的HTTP状态,例如BAD REQUEST。

您可以使用Spring Controller Advice将您的异常映射到响应状态:http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc