设计师网站模版,自己的网站怎么做app吗,备案网站注意事项,最全网站源码分享RESTful Web API设计的一个领域#xff08;经常被忽视#xff09;是如何报告与业务或应用程序有关的错误和问题。 首先要想到HTTP状态代码的正确用法#xff0c;尽管它非常方便#xff0c;但通常它的信息量还不够。 让我们以400错误请求为例。 是的#xff0c;它清楚地表明… RESTful Web API设计的一个领域经常被忽视是如何报告与业务或应用程序有关的错误和问题。 首先要想到HTTP状态代码的正确用法尽管它非常方便但通常它的信息量还不够。 让我们以400错误请求为例。 是的它清楚地表明请求是有问题的但是究竟出了什么问题呢 RESTful的体系结构风格并不决定在这种情况下应该做什么因此每个人都在发明自己的风格约定和规范。 它可能像将错误消息包含到响应中一样简单也可能像复制/粘贴长堆栈跟踪记录一样是短视的对于Java或.NET仅举几例。 并不缺乏想法但是幸运的是我们至少有一些以RFC 7807形式提供的指南HTTP API的问题详细信息 。 尽管它不是官方规范而是草案仍然但它概述了有关当前问题的良好通用原则这就是我们在本文中要讨论的内容。 简而言之 RFC 7807HTTP API的问题详细信息仅提出了错误或问题表示形式 JSON或XML格式其中可能至少包括以下详细信息 type –标识问题类型的URI参考 标题 –问题类型的简短易读摘要 status – HTTP状态代码 详细信息 –针对此问题的发生的易于理解的解释 实例 –标识问题特定发生的URI参考 更重要的是问题类型定义可以使用其他成员扩展问题详细信息对象从而为上述成员做出贡献。 如您所见从实现角度看它看起来非常简单。 更好的是感谢 Zalando 我们已经有了 RFC 7807HTTP API实现的问题详细信息 对于Java 和 特别是Spring Web 。 所以……让我们尝试一下 我们将使用最新的技术堆栈 Spring Boot和Apache CXF 流行的Web服务框架和JAX-RS 2.1实现来构建我们虚构的People Management Web API。 为了简单起见仅公开了两个端点注册和按人员标识符查找。 撇开开发现实世界服务时可能遇到的大量问题和业务约束即使使用此简单的API也可能会出错。 我们要解决的第一个问题是如果您要寻找的人尚未注册怎么办 看起来很适合404 Not Found 对吗 确实让我们从第一个问题PersonNotFoundProblem开始 public class PersonNotFoundProblem extends AbstractThrowableProblem {private static final long serialVersionUID 7662154827584418806L;private static final URI TYPE URI.create(http://localhost:21020/problems/person-not-found);public PersonNotFoundProblem(final String id, final URI instance) {super(TYPE, Person is not found, Status.NOT_FOUND, Person with identifier id is not found, instance, null, Map.of(id, id));}
} 它非常类似于典型的Java异常并且确实是一个因为AbstractThrowableProblem是RuntimeException的子类。 这样我们可以从JAX-RS API中抛出它。 Produces({ MediaType.APPLICATION_JSON, application/problemjson })
GET
Path({id})
public Person findById(PathParam(id) String id) {return service.findById(id).orElseThrow(() - new PersonNotFoundProblem(id, uriInfo.getRequestUri()));
} 如果我们运行服务器并尝试获取提供任何标识符的人员则将返回问题详细信息响应因为未预先填充数据集例如 $ curl http://localhost:21020/api/people/1 -H Accept: */* HTTP/1.1 404
Content-Type: application/problemjson{type : http://localhost:21020/problems/person-not-found,title : Person is not found,status : 404,detail : Person with identifier 1 is not found,instance : http://localhost:21020/api/people/1,id : 1
} 请注意应用程序/问题 json媒体类型的用法以及响应中包含的其他属性ID 。 尽管有许多可以改进的地方但是可以说它比仅裸露的404 或由EntityNotFoundException引起的500 要好。 另外如果需要进一步的说明可以参考此类问题背后的文档部分在我们的情况下为http// localhost21020 / problems / person-not-found 。 因此在例外之后设计问题只是一种选择。 您可能经常出于非常正当的理由会避免将业务逻辑与无关的细节耦合在一起。 在这种情况下返回问题详细信息作为JAX-RS资源的响应有效负载是完全有效的。 例如注册过程可能会引发NonUniqueEmailException因此我们的Web API层可以将其转换为适当的问题详细信息。 Consumes(MediaType.APPLICATION_JSON)
Produces({ MediaType.APPLICATION_JSON, application/problemjson })
POST
public Response register(Valid final CreatePerson payload) {try {final Person person service.register(payload.getEmail(), payload.getFirstName(), payload.getLastName());return Response.created(uriInfo.getRequestUriBuilder().path(person.getId()).build()).entity(person).build();} catch (final NonUniqueEmailException ex) {return Response.status(Response.Status.BAD_REQUEST).type(application/problemjson).entity(Problem.builder().withType(URI.create(http://localhost:21020/problems/non-unique-email)).withInstance(uriInfo.getRequestUri()).withStatus(Status.BAD_REQUEST).withTitle(The email address is not unique).withDetail(ex.getMessage()).with(email, payload.getEmail()).build()).build();}} 要触发此问题只需运行服务器实例并尝试两次注册同一个人即可就像我们在下面所做的那样。 $ curl -X POST http://localhost:21020/api/people \ -H Accept: */* -H Content-Type: application/json \-d {email:johnsmith.com, firstName:John, lastName: Smith}HTTP/1.1 400
Content-Type: application/problemjson { type : http://localhost:21020/problems/non-unique-email, title : The email address is not unique, status : 400, detail : The email johnsmith.com is not unique and is already registered, instance : http://localhost:21020/api/people, email : johnsmith.com
} 太好了因此我们的最后一个示例有些复杂但同时可能是最现实的示例。 我们的Web API在很大程度上依赖Bean验证 以确保API使用者提供的输入有效。 我们如何将验证错误表示为问题的详细信息 最直接的方法是提供专用的ExceptionMapper提供程序它是JAX-RS规范的一部分。 让我们介绍一个。 Provider
public class ValidationExceptionMapper implements ExceptionMapperValidationException {Context private UriInfo uriInfo;Overridepublic Response toResponse(final ValidationException ex) {if (ex instanceof ConstraintViolationException) {final ConstraintViolationException constraint (ConstraintViolationException) ex;final ThrowableProblem problem Problem.builder().withType(URI.create(http://localhost:21020/problems/invalid-parameters)).withTitle(One or more request parameters are not valid).withStatus(Status.BAD_REQUEST).withInstance(uriInfo.getRequestUri()).with(invalid-parameters, constraint.getConstraintViolations().stream().map(this::buildViolation).collect(Collectors.toList())).build();return Response.status(Response.Status.BAD_REQUEST).type(application/problemjson).entity(problem).build();}return Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(application/problemjson).entity(Problem.builder().withTitle(The server is not able to process the request).withType(URI.create(http://localhost:21020/problems/server-error)).withInstance(uriInfo.getRequestUri()).withStatus(Status.INTERNAL_SERVER_ERROR).withDetail(ex.getMessage()).build()).build();}protected Map?, ? buildViolation(ConstraintViolation? violation) {return Map.of(bean, violation.getRootBeanClass().getName(),property, violation.getPropertyPath().toString(),reason, violation.getMessage(),value, Objects.requireNonNullElse(violation.getInvalidValue(), null));}
} 上面的代码片段区分了两种问题 ConstraintViolationException指示无效输入并映射到400 Bad Request 而泛型ValidationException指示服务器端问题并映射到500 Internal Server Error 。 我们仅提取有关违规的基本详细信息但是即使这样做也可以大大改进错误报告功能。 $ curl -X POST http://localhost:21020/api/people \-H Accept: */* -H Content-Type: application/json \-d {email:john.smith, firstName:John} -i HTTP/1.1 400
Content-Type: application/problemjson { type : http://localhost:21020/problems/invalid-parameters, title : One or more request parameters are not valid, status : 400, instance : http://localhost:21020/api/people, invalid-parameters : [ {reason : must not be blank, value : null, bean : com.example.problem.resource.PeopleResource, property : register.payload.lastName }, { reason : must be a well-formed email address, value : john.smith, bean : com.example.problem.resource.PeopleResource, property : register.payload.email } ]
} 这次捆绑到invalid-parameters成员中的附加信息非常冗长我们分别知道类 PeopleResource 方法 register 方法的参数 有效负载 和属性 lastName和email 所有这些都从属性路径。 有意义的错误报告是现代RESTful Web API的基础之一。 通常这并不容易但绝对值得付出努力。 消费者通常只是其他开发人员应该对哪里出了问题以及如何处理有一个清晰的了解。 RFC 7807HTTP API的问题详细信息是朝正确方向迈出的一步 问题和问题弹簧网络之类的库在这里为您提供支持请充分利用它们。 完整的源代码可在Github上找到 。 翻译自: https://www.javacodegeeks.com/2019/05/http-status-code-enough-tackling-web-apis-error-reporting.html