Dhe*_*rik 8 java architecture jax-rs ejb-3.0 api-versioning
我正在试图弄清楚我对API项目架构的选择.
我想使用JAX-RS 1.0版创建一个API.此API从更大,更旧,更复杂的应用程序中使用远程EJB(EJB 3.0).我正在使用Java 6.
到目前为止,我可以做到这一点并且有效.但我对解决方案不满意.看我的包裹配置.我的问题在代码后面描述:
/api/
/com.organization.api.v1.rs -> Rest Services with the JAX-RS annotations
/com.organization.api.v1.services -> Service classes used by Rest Services. Basically, they only have the logic to transform the DTOs objects from Remote EJBs in JSON. This is separated by API version, because the JSON can be different in each version.
/com.organization.api.v1.vo -> View Objects returned by the Rest Services. They will be transformed in JSON using Gson.
/com.organization.api.services -> Service classes used by versioned Services.
Here we have the lookup for Remote EJBs and some API logic, like validations. This services can be used by any versioned of each Service.
Run Code Online (Sandbox Code Playgroud)
示例com.organization.api.v1.rs.UserV1RS
:
@Path("/v1/user/")
public class UserV1RS {
@GET
public UserV1VO getUsername() {
UserV1VO userVO = ServiceLocator.get(UserV1Service.class).getUsername();
return userVO;
}
}
Run Code Online (Sandbox Code Playgroud)
示例com.organization.api.v1.services.UserV1Service
:
public class UserV1Service extends UserService {
public UserV1VO getUsername() {
UserDTO userDTO = getUserName(); // method from UserService
return new UserV1VO(userDTO.getName);
}
}
Run Code Online (Sandbox Code Playgroud)
示例com.organization.api.services.UserService
:
public class UserService {
public UserDTO getUsername() {
UserDTO userDTO = RemoteEJBLocator.lookup(UserRemote.JNDI_REMOTE_NAME).getUser();
return userDTO;
}
}
Run Code Online (Sandbox Code Playgroud)
我项目的一些要求:
UserV1Service
和UserV2Service
使用UserService
.UserV1Service
和OrderV2Service
使用AnotherService
.UserV1VO
而不是UserVO
).关于上面的代码让我烦恼的是:
ServiceLocator
堂课对我来说不是一个好方法.这个类使用旧库中的遗留代码,我对这个类的工作方式有很多疑问.使用它的方式ServiceLocator
对我来说也很奇怪,这个策略不适合模拟 单元测试的服务.我想创建一个新的ServiceLocator或使用一些依赖注入策略(或另一种更好的方法).UserService
类并不旨在由另一个"外部"服务中使用,像OrderService
.这只是为了UserVxService
.但在将来,也许OrderService
想使用一些来自UserService
...的代码ServiceLocator
我将需要lookups
在我的代码中做很多事情.创建循环依赖的机会(serviceOne查找serviceTwo,查找serviceThree,查找serviceOne)非常高.UserV1VO
可以用在我的无版本服务(com.organization.api.services
)中,但这不可能发生.一个好的架构不允许不允许的东西.我有创建一个新项目的想法,api-services
并将其放在com.organization.api.services
那里以避免这种情况.这是一个好的解决方案吗?所以......想法?
我看到的一些事情:
理想情况下应该UserService
基于接口。它们似乎有类似的契约,但唯一的区别是它们的来源(RemoteEJB、LocalServiceLocator)。这些应该是返回的 DTO
UserV1Service extends UserService
不应该使用继承,而应该倾向于组合。考虑一下您需要为同一服务的 v2 做什么。根据你的例子,你会得到UserV2Service extends UserService
. 这并不理想,特别是如果您最终在基类中使用特定于某个版本的抽象方法。然后突然间其他版本化服务需要满足这一需求。
对于服务定位器
在您的情况下,您最好使用 Spring 或 CDI 等依赖注入框架。如果您的项目是新的,这仅适用于您自己的代码。
对于那些难以进行单元测试的测试,您可以将 RemoteEJB 调用包装到它自己的接口中,这样可以更轻松地进行模拟。RemoteEJB 的测试将成为该项目的集成测试。
UserService 类不适合由其他“外部”服务(例如 OrderService)使用。它仅适用于 UserVxService。但将来,也许 OrderService 想要使用 UserService 中的一些代码
同一层上的服务之间相互通信没有任何问题。
在这种方法中,VO(如 UserV1VO)可以在我的无版本服务 (com.organization.api.services) 中使用,但这不可能发生。一个好的架构不允许出现不允许的事情。我有想法创建一个新项目,例如 api-services 并将 com.organization.api.services 放在那里以避免这种情况。这是一个好的解决方案吗?
仅仅因为您“可以”做某事并不意味着您应该做。虽然将层分离到它自己的项目中似乎是个好主意;实际上,没有什么可以阻止开发人员在该项目中重新创建相同的类,或者将 jar 包含在类路径中并使用相同的类。我并不是说拆分它是错误的,只是说它应该出于正确的原因而不是“假设情景”进行拆分。
归档时间: |
|
查看次数: |
234 次 |
最近记录: |