如何处理 REST 服务中的无效参数?
How to handle invalid parameters in REST service?
我使用 spring
@RestController
.
提供 REST
网络服务
一般无效的参数内容应该如何处理?我尝试抛出一个自定义异常,但这会导致客户端出现 HTTP 500
错误并由此暴露堆栈跟踪。
这可能不是正确的方法。但是应该如何返回简单的错误消息呢? (网络服务不会被用户手动访问。只是通过连接到其余控制器的其他服务)。
如果我理解你的话,
然后,通常我认为在每个 json 响应(或者即使您的响应是 XML)中都有一个键是很好的,它指示进程的状态。该字段可以称为状态。
所以你发回的每一个响应都应该有这个 status
字段,它的值应该表明处理过程中发生了什么,以及调用者应该在响应中期望什么。
这个值可以是一个数字,或者一条短信,一些类似常量的信息
您还可以添加另一个字段,message
,其中包含状态代码的一些文本描述。
现在您必须列出您的服务可能发回的可能雕像。
例如:
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
状态下,不会发回其他数据。
只是告诉客户我们有 "this issue".
或者您可以通过将 :
添加到错误消息常量来提供更多信息,告知有关错误的更多信息:
例如,
{
"status":"0003",
"message":"missing_param:album_id"
}
告诉用户,缺少一个参数,它是 album_id
现在您可以写下所有可能的 status
回复,然后 message
这将成为您的服务文档的一部分。
如果你手动验证你的参数,你可能会抛出一个特定的异常。然后您可以将异常映射到特定的 HTTP 状态,例如 BAD REQUEST。
您可以使用 Spring 控制器建议将异常映射到响应状态:http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc。
您应该在应用程序的最外层验证您的参数,然后再将其移交给您的域。此时您仍处于 HTTP 层,因此可以采取适当的操作,即 return 400 BAD REQUEST 状态。
在此范围内,您可以完全控制如何将此信息传递给您的用户(或其他服务)。如果您只是记录纯文本,或者设计您自己的 Json/Xml 描述错误的负载,纯文本就可以了。
我正在使用 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 验证的通用 class。
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();
}
}
此代码尚未经过测试,但它可能有助于了解如何进行验证。在我看来,这是进行休息服务验证的一种非常直接的方法,它允许您报告确切的变量路径以及每个字段的自定义错误消息。
我使用 spring
@RestController
.
REST
网络服务
一般无效的参数内容应该如何处理?我尝试抛出一个自定义异常,但这会导致客户端出现 HTTP 500
错误并由此暴露堆栈跟踪。
这可能不是正确的方法。但是应该如何返回简单的错误消息呢? (网络服务不会被用户手动访问。只是通过连接到其余控制器的其他服务)。
如果我理解你的话,
然后,通常我认为在每个 json 响应(或者即使您的响应是 XML)中都有一个键是很好的,它指示进程的状态。该字段可以称为状态。
所以你发回的每一个响应都应该有这个 status
字段,它的值应该表明处理过程中发生了什么,以及调用者应该在响应中期望什么。
这个值可以是一个数字,或者一条短信,一些类似常量的信息
您还可以添加另一个字段,message
,其中包含状态代码的一些文本描述。
现在您必须列出您的服务可能发回的可能雕像。
例如:
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
状态下,不会发回其他数据。
只是告诉客户我们有 "this issue".
或者您可以通过将 :
添加到错误消息常量来提供更多信息,告知有关错误的更多信息:
例如,
{
"status":"0003",
"message":"missing_param:album_id"
}
告诉用户,缺少一个参数,它是 album_id
现在您可以写下所有可能的 status
回复,然后 message
这将成为您的服务文档的一部分。
如果你手动验证你的参数,你可能会抛出一个特定的异常。然后您可以将异常映射到特定的 HTTP 状态,例如 BAD REQUEST。
您可以使用 Spring 控制器建议将异常映射到响应状态:http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc。
您应该在应用程序的最外层验证您的参数,然后再将其移交给您的域。此时您仍处于 HTTP 层,因此可以采取适当的操作,即 return 400 BAD REQUEST 状态。
在此范围内,您可以完全控制如何将此信息传递给您的用户(或其他服务)。如果您只是记录纯文本,或者设计您自己的 Json/Xml 描述错误的负载,纯文本就可以了。
我正在使用 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 验证的通用 class。
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();
}
}
此代码尚未经过测试,但它可能有助于了解如何进行验证。在我看来,这是进行休息服务验证的一种非常直接的方法,它允许您报告确切的变量路径以及每个字段的自定义错误消息。