V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
RedrumSherlock
V2EX  ›  Java

Spring 相关,有没有什么好的解决方案

  •  
  •   RedrumSherlock · 2020-11-29 02:08:32 +08:00 · 3395 次点击
    这是一个创建于 1455 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如现在有一个简单的 Employee 的 POJO 类,因为要数据库操作所以要用 Spring 的 JPA 就得在类里加上 Entity 的注释,但是这样就有 Spring 的 context 了。

    现在因为很多其他的微服务都需要这个类,想把这个类拿到不带 Spring 的共用的 package 下面就做不到,不得不维护两个类,一个是带 Spring 的一个是不带给其他微服务用比如 unwrap json 之类的,有没有什么比较好的办法只用维护一个?

    22 条回复    2020-12-01 17:05:17 +08:00
    kingfalse
        1
    kingfalse  
       2020-11-29 02:10:05 +08:00 via Android
    运行时动态字节码复制一个?这个倒是也好做
    pelloz
        2
    pelloz  
       2020-11-29 02:24:49 +08:00
    你这个类是单独一个共享依赖吧,你在 pom 里面将 JPA 相关依赖设置为 <scope>provided</scope> 就好了。
    不过我觉得你的意思估计是写了一个类,然后到处复制粘贴....那就没有好办法了
    nvkou
        3
    nvkou  
       2020-11-29 02:32:54 +08:00 via Android
    微服务不是业务独立吗?其他程序至少用不到这个类。
    跨系统间传输可以再转一个通用 pure pojo 然后分包做依赖
    cheng6563
        4
    cheng6563  
       2020-11-29 03:04:57 +08:00 via Android
    写个父类或接口打上 @Entity 注解,其他项目也自己写一个不带注解的父类或接口,要处理好项目依赖问题
    RedrumSherlock
        5
    RedrumSherlock  
    OP
       2020-11-29 05:05:18 +08:00
    @nvkou 是业务独立,但是某些微服务之间还是有一些共用的 model,我们这些一般都丢一个类似 lib 或者 util 的包里,然后每个微服务 import 进来减少冗余。

    分包做依赖具体是怎么操作?就还是一个 pojo 用来跨系统,然后分包再建一个带注解的做 JPA 操作?
    340244120w
        6
    340244120w  
       2020-11-29 06:10:38 +08:00 via iPhone
    最原始的 Xml 就是做这个的呀
    RedrumSherlock
        7
    RedrumSherlock  
    OP
       2020-11-29 06:19:50 +08:00
    @340244120w 是啊,现在一个想法就是不用注解回归 xml,但是 Spring boot 好像 2.0 以后要回 xml 不太方便,不再去自动找默认的那些 xml 文件了,得自己写几个 configuration
    zhazi
        8
    zhazi  
       2020-11-29 06:38:31 +08:00 via Android
    使用 @entity 跟 spring 的 context 一点关系都没有。
    mind3x
        9
    mind3x  
       2020-11-29 06:47:43 +08:00   ❤️ 4
    你这需要共用的不是 model,而是 DTO 。Entity 和 DTO 之间分层并且互相转换是常见的基本操作。
    tension2012
        10
    tension2012  
       2020-11-29 07:14:10 +08:00
    如果一个普通的 POJO 类,要做 O-R Mapping 的话, 无论是 annotation 还是 xml 方式,你至少要告诉程序, 你是怎么个映射规律, 比如你的 table name 是什么, 你的 column name 是什么, 你的 primary key 等等?

    不过,如果什么都不做的话, 那就只能程序到 mysql 的那些系统字典表里去查对应的表名,列名和类型, 然后自己去组装一个类, 但是这样对命名规范很严格, 很容易出现映射错误的问题
    VeryZero
        11
    VeryZero  
       2020-11-29 10:35:55 +08:00
    @mind3x 同意,如果多个微服务需要依赖同一个 model,说明服务拆分有问题。。

    不过我们公司也是这么干的😄 区别就是我们用的 MyBatis,所以貌似没这问题
    Braisdom
        12
    Braisdom  
       2020-11-29 10:40:49 +08:00
    我一直都不明白,为什么会存在 POJO,VO,DTO, Entity 这些概念,纯属过于理论化的抽象,脱离实践太远,完全没有考虑开发过程中的理解的复杂度。
    hantsy
        13
    hantsy  
       2020-11-29 11:00:13 +08:00
    微服务一个最基本的原则,每个服务要实现自治(开发,测试,发部周期不影响其它的服务),服务之间使用轻量协议交互(比如, HTTP,Message Broker 等)。

    对于你的情况,说白了你的程序根本就不是微服务架构,微服务压根就不会用到数据库相关代码共享。如果要共享,也只有协议数据格式( Http 的内容数据格式,Message Payload 规格)可以共享。

    没有准备好 MS,就不要强行往上面靠,微服务架构跟你的所有的框架没太多关系,你的程序并不是用了 Spring Cloud 或者其它什么微服务框架就是微服务架构,很多人只是使用某种框架“碰瓷”微服务而已。
    mejee
        14
    mejee  
       2020-11-29 11:03:33 +08:00 via iPhone
    9 楼正解
    xuanbg
        15
    xuanbg  
       2020-11-29 11:29:30 +08:00
    别的服务用到就要自己搞个 DTO 用于反序列化。要么你把这个 DTO 放到一个公共的包里面,别的服务引用这个包。但维护更新包版本又是一个麻烦事,所以这种方法不建议。还有个办法是别的服务直接用 Object 类型,如果只是甩给前端看看没有业务逻辑相关的话。
    perfee
        16
    perfee  
       2020-11-29 17:35:33 +08:00
    系统 A,系统 B 。
    系统 B 要依赖系统 A,那么 A 就要有一个干净的对外的接口。否则 A 和 B 就太耦合了。
    如果 A 和 B 都不想给对方开接口,那好了,搞一个中立的 C,C 来担任这个角色,发布干净的 API 或者 SPI,A B 共用。

    所以,如果 POJO 类是共用的,它就不应该被 A 视作私有的,既然不是私有的,就不能夹杂私货。
    如果 A 觉得维持这个干净的 api 太累了,应该搞一个独立的 C 来维护。

    整体的意思还是要回到经常谈论的点上:内聚和耦合,你怎么处理这个关系。
    Braisdom
        17
    Braisdom  
       2020-11-29 20:24:13 +08:00   ❤️ 1
    刚刚仔细看了楼主的贴子,像这类问题也比较容易解决:动态代理
    不同微服务中使用同一个领域模型是正常的,但不同微服务中根据自身的技术特性,对模型也会有不同的技术型定义,这是很正常的需求。

    解决方法:在能用的 JAR 中通过 Java Interface 定义领域模型,JPA 中只是实现这个 Interface,其它的微服务只看到 Java Interface,在不同微服务之间进行模型传递时,通过一个动态代理的对象工厂创建这个接口的实例。

    这样就可以不需要在所有的微服务中看到 JPA 的 Entity 了,它们看到的只有领域模型的 Interface,只不过需要定义好对象传输的协议,和反序列化的逻辑。
    chenshun00
        18
    chenshun00  
       2020-11-30 09:44:46 +08:00
    BeanUtils.Copy(source,target)
    Aresxue
        19
    Aresxue  
       2020-11-30 15:40:08 +08:00
    问题的原因就是你把 DO 和 DTO 变成一个了,这种做法本身是有点问题,但非要这么做也没事,client 包依赖 JPA 然后 JPA 的依赖变成 provided,实际 run 的应用中也有要 JPA 的依赖,两个依赖版本要尽量保持一致
    Joker123456789
        20
    Joker123456789  
       2020-11-30 16:11:37 +08:00
    正确的做法就是维护两个类,所以不用改。
    Jrue0011
        21
    Jrue0011  
       2020-12-01 17:02:34 +08:00
    或许可以寻找一个具有代码生成功能(注解处理器)的 mapper 框架,维护一个类,另一个提供给其他服务使用的类自动生成代码?
    Jrue0011
        22
    Jrue0011  
       2020-12-01 17:05:17 +08:00
    @Jrue0011 MapStruct 好像有这个能力,不过没用过不太清楚
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1116 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:38 · PVG 07:38 · LAX 15:38 · JFK 18:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.