软件开发中的决策:权衡与取舍
上QQ阅读APP看书,第一时间看更新

2.1.2 实现新的业务需求

让我们一起回顾Payment服务提供的功能。它在端点/payment上提供了一个基于HTTP的支付服务。它只提供了一个@GET资源,用于获取某个令牌的所有支付信息,如代码清单2.1所示。

代码清单2.1 /payment端点的实现

@Path("/payment")  ◁--- 暴露Payment服务的接口
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PaymentResource {
 
  private final PaymentService paymentService = new PaymentService();
  private final AuthService authService = new AuthService();  ◁--- 创建AuthService实例
 
  @GET
  @Path("/{token}")
  public Response getAllPayments(@PathParam("token") String token) {
    if (authService.isTokenValid(token)) {  ◁--- 使用AuthService验证令牌
      return Response.ok(paymentService.getAllPayments()).build();
    } else {
      return Response.status(Status.UNAUTHORIZED).build();
    }
  }
}

如你所见,在代码清单2.1中,AuthService会对令牌做验证,验证通过之后,调用方会继续访问Payment服务,返回所有的支付信息。实际项目中,AuthService的逻辑会更加复杂。我们先看看简化版AuthService的实现,如代码清单2.2所示。

代码清单2.2 创建验证服务

public class AuthService {
 
  public boolean isTokenValid(String token) {
    return token.equals("secret");
  }
}

注意 实际项目中通常不会出现两个团队使用完全一样的接口、方法名、函数签名等情况。这是之前讨论早共享代码能带来的优势之一:方法实现出现差异的概率要降低很多。

其中一个团队负责Person服务的开发,使/person端点提供HTTP服务。该服务也采用基于令牌的认证,如代码清单2.3所示。

代码清单2.3 /person端点的实现

@Path("/person")  ◁--- 暴露Person服务的HTTP接口
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PersonResource {
 
  private final PersonService personService = new PersonService();
  private final AuthService authService = new AuthService();  ◁--- 创建AuthService实例
 
  @GET
  @Path("/{token}/{id}")
  public Response getPersonById(@PathParam("token") String token, 
     @PathParam("id") String id) {
    if (authService.isTokenValid(token)) {  ◁--- 使用AuthService验证令牌
      return Response.ok(personService.getById(id)).build();
    } else {
      return Response.status(Status.UNAUTHORIZED).build();
    }
  }
}

Person服务也集成了AuthService服务。它会验证用户提供的令牌,接着使用PersonService获取Person的信息。