Bootstrap

深入JAX-RS:参数校验与异常处理实战指南

在构建RESTful API时,确保数据的正确性和完整性是至关重要的。JAX-RS(Java API for RESTful Web Services)提供了一种方便的方式来处理HTTP请求和响应,同时也支持对请求体中的Java Bean进行校验。本文将通过一个实际的示例,详细说明如何在JAX-RS资源方法中启用实体校验,并自定义异常处理程序来返回校验错误信息。

JAX-RS资源类与Java Bean

首先,我们定义一个JAX-RS资源类CustomerResource,它包含一个POST方法用于创建客户。在这个方法中,我们使用@Valid注解来启用对传入的Customer对象的校验。

@Path("/customers")
public class CustomerResource {
  @POST
  public String createCustomer(@Valid Customer customer) {
      System.out.println("-- in createCustomer() method --");
      return String.format("Customer created : %s%n", customer);
  }
}

接下来,我们定义Customer Java Bean,并使用Bean Validation注解来标记需要校验的字段。

@XmlRootElement
public class Customer {
  @NotNull
  private String name;
  @NotNull
  private String address;
  @NotNull
  @Pattern(regexp = "\\d{3}-\\d{3}-\\d{4}")
  private String phoneNumber;
  // 省略getter和setter方法...
}

自定义异常映射器

为了返回自定义的校验错误信息,我们需要编写一个异常映射器MyExceptionMapper,它实现了ExceptionMapper<ConstraintViolationException>接口。

@Provider
public class MyExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
  @Override
  public Response toResponse(final ConstraintViolationException exception) {
      return Response.status(Response.Status.BAD_REQUEST)
                     .entity(prepareMessage(exception))
                     .type("text/plain")
                     .build();
  }
  private String prepareMessage(ConstraintViolationException exception) {
      String msg = "";
      for (ConstraintViolation<?> cv : exception.getConstraintViolations()) {
          msg += cv.getPropertyPath() + " " + cv.getMessage() + "\n";
      }
      return msg;
  }
}

JAX-RS客户端与测试

为了测试我们的API,我们创建了一个JAX-RS客户端MyClient,它尝试以不合规的数据创建客户。

public class MyClient {
  public static void main(String[] args) throws Exception {
      Customer customer = new Customer();
      customer.setName(null);
      customer.setAddress(null);
      customer.setPhoneNumber("343-343-343");
      Client client = ClientBuilder.newBuilder().build();
      WebTarget target = client.target("http://localhost:8080/customers");
      Response response = target.request()
                                  .post(Entity.entity(customer, MediaType.TEXT_XML), Response.class);
      System.out.println(response.readEntity(String.class));
  }
}

输出结果

当运行上述客户端代码时,我们得到了以下输出,显示了校验失败的具体信息:

createCustomer.arg0.phoneNumber must match "\d{3}-\d{3}-\d{4}"  
createCustomer.arg0.name may not be null  
createCustomer.arg0.address may not be null  

项目依赖与技术栈

本示例项目使用了以下依赖和技术:

  • jersey-server 2.25.1:Jersey核心服务器实现。
  • jersey-container-servlet 2.25.1:Jersey核心Servlet 3.x实现。
  • jersey-bean-validation 2.25.1:提供对Bean Validation(JSR-349) API支持的Jersey扩展模块。
  • JDK 1.8
  • Maven 3.3.9

通过这个示例,我们可以看到JAX-RS如何方便地集成Java Bean校验,并自定义异常处理程序来提升API的健壮性和用户体验。

;