【问题标题】:How can web services be independant from the DAL implementations?Web 服务如何独立于 DAL 实现?
【发布时间】:2016-01-31 18:24:16
【问题描述】:

我正在研究a project,它可以与两个数据访问层实现一起使用:

  • 图形数据库,
  • 关系数据库。

实现的选择取决于 Tomcat 启动时的 Spring 活动配置文件(spring.profiles.active=graph-database 或 spring.profiles.active=relational-database)。这很好用。

我正在服务层添加 REST 服务。目前,我只注释了retrieveAllCategories 方法,它响应“/rest/resources/categories” URL。它按预期显示 JSON,但我的问题是,当服务器使用 DAL 图数据库实现时,输出与使用关系数据库模块时不同。

不同之处在于与“ResourceCategory”类关联的对象集合。我已经必须用@JsonIgnore@JsonManagedReference@JsonBackReference (example) 之类的注释来注释我的“JPA”域bean,以避免无限递归。这是一件相当漫长而无聊的事情,我不希望在我的整个项目中都这样做。

我的问题:有没有更好的方法(比非常耐心地注释每个“关系数据库”bean)来确保我的 Web 服务将提供完全相同的数据,而与使用的 DAL 实现无关?

【问题讨论】:

    标签: java spring web-services architecture


    【解决方案1】:

    解决问题的最常见方法是使用数据传输对象 (DTO)。

    基本上,您创建一个新类,该类准确地表示您的 Web 服务的命令/响应应该如何。

    那么,只需在该类之间进行转换即可。

    例子:

    public class JpaMovie {
    
        @OneToMany
        private List<Actor> actors;
    
        // Whatever you need in JPA DAL.
    }
    
    public class GraphMovie {
        // Whatever you need in Graph DAL.
    }
    
    public class MovieDTO {
        // Structure of the web service response.
        // Always convert to this type before returning.
        // This way, no matter the DAL, your response
        // structure will always be the same.
    }
    

    以及如何在您的情况下使用它们(您正在为您的域模型使用 setter/getter 接口):

    @Controller
    public class MovieController {
    
        @Autowired
        private MovieService movieService;
    
        @RequestMapping("/movies")
        public @ResponseBody MovieDTO findById(@RequestParam String id) {
            MovieInterface movie = movieService.findById(id);
            return MovieDTO.from(movie);
        }
    
    }
    

    【讨论】:

    • 感谢您的回答,但我不确定我是否了解如何从当前的“服务”层返回 DTO 对象?使用 DTO 对象是否意味着我必须创建一个新的“网络服务”子项目?
    • @GrégoireColbert 您不需要更改“服务”层的返回类型。我在您的存储库中看到您在域模型上使用 getter/setter 接口,因此您只需要更改控制器的返回类型。请参阅我在答案末尾添加的示例。
    • 您认为创建一个包含数据传输对象和网络服务“控制器”的新 Maven 模块是否有意义?
    • @GrégoireColbert 是的,您可以将所有 DTO 放在另一个模块中,并与 API 的使用者(客户端)共享该模块。这些类是通信的model:一种contract。是的,您可以这样做,但这不是强制性的。关于 Web 服务“控制器”,我假设您使用的是 Spring MVC,因为您将问题标记为 Spring。通常我将控制器放在与应用程序相同的模块中的另一个包中,但这取决于您。
    • 谢谢。我将尝试实现一个新模块,我认为 Web 服务有点像一个新的表示层。
    猜你喜欢
    • 2010-10-20
    • 2012-09-05
    • 2015-10-08
    • 2015-10-16
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多