V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
ye4tar
V2EX  ›  问与答

SpringBoot Rest 最佳实践的一些疑问

  •  
  •   ye4tar · 2021-06-28 10:17:07 +08:00 · 587 次点击
    这是一个创建于 412 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不得已要做后端开发,于是按照官方指导使用 SrpingBoot Web + JPA + Rest

    • implementation 'org.springframework.boot:spring-boot-starter-web'
    • implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    • implementation 'org.springframework.boot:spring-boot-starter-data-rest'

    写起来比较愉快,

    domain 如下:

    
    @Entity
    @Getter
    @Setter
    public class Account {
    
        @Id
        @Column(nullable = false, updatable = false)
        @SequenceGenerator(
                name = "account_sequence",
                sequenceName = "account_sequence",
                allocationSize = 1,
                initialValue = 10000
        )
        @GeneratedValue(
                strategy = GenerationType.SEQUENCE,
                generator = "account_sequence"
        )
        private Long id;
    
        @Column(nullable = false, unique = true, updatable = false)
        private String account;
    
        @Column(nullable = false)
        private String passwd;
    
        @Column
        private String salt;
    
        @Column
        private String nonce;
    
        @OneToOne
        @JoinColumn(nullable = false, updatable = false, unique = true)
        private Member member;
        
        // 偷个懒,投影直接下载这个类内部了
        @Projection(name = "accountDTO", types = Account.class)
        public interface AccountDTO {
            String getAccount();
            String getSalt();
        }
    }
    

    仓储接口

    @RepositoryRestResource(excerptProjection = Account.AccountDTO.class)
    public interface AccountRepository extends JpaRepository<Account, Long> {}
    

    此时启动工程,http://127.0.0.1/accounts接口中 account 的属性 passwd 由于投影的缘故没显示 大约是这个样子,这符合我的预期,我很欣慰!

    {
        "_embedded": {
            "accounts": [
                {
                    "account": "1008610010",
                    "salt": "xxxxx",
                    // 这里的 passwd 和 nonce 都没有了
                    "_links": {
                        "self": {
                            "href": "http://127.0.0.1/accounts/10000"
                        },
                        "account": {
                            "href": "http://127.0.0.1/accounts/10000{?projection}",
                            "templated": true
                        },
                        "member": {
                            "href": "http://127.0.0.1/accounts/10000/member"
                        }
                    }
                }
            ]
        },
        "_links": {
            "self": {
                "href": "http://127.0.0.1/accounts"
            },
            "profile": {
                "href": "http://127.0.0.1/profile/accounts"
            }
        },
        "page": {
            "size": 20,
            "totalElements": 1,
            "totalPages": 1,
            "number": 0
        }
    }
    

    此时调用http://127.0.0.1/accounts/10000,结果不该出现的 passwd 和 nonce 冒出了头。我很想跳起来对着他的狗头就是一脚。

    {
        "account": "1008610010",
        "passwd": "999999",// <===========================这里
        "salt": "salt",   
        "nonce": "nonce",// <===========================这里
        "createAt": "2021-06-22T15:01:17.50913+08:00",
        "modifyAt": "2021-06-22T15:01:24.41396+08:00",
        "_links": {
            "self": {
                "href": "http://127.0.0.1/accounts/10000"
            },
            "account": {
                "href": "http://127.0.0.1/accounts/10000{?projection}",
                "templated": true
            },
            "member": {
                "href": "http://127.0.0.1/accounts/10000/member"
            }
        }
    }
    

    在此,征求广大外出务工人员,授我渔,喂我🐟!提供一些 SrpingBoot JPA REST 一些常用的套路,值得细读和探讨的资料。

    叩首!!!

    3 条回复    2021-06-30 16:40:46 +08:00
    wccc
        1
    wccc  
       2021-06-28 10:30:29 +08:00
    dejavuwind
        2
    dejavuwind  
       2021-06-29 11:06:10 +08:00
    我选择手动 set null 或者 单独封 DTO 投影还没用过
    试了一下,可以试试 http://127.0.0.1/accounts/10000?projection=accountDTO
    ye4tar
        3
    ye4tar  
    OP
       2021-06-30 16:40:46 +08:00
    @dejavuwind 按照最佳实践的方式,不使用 spring-boot-starter-data-rest 的话,每个 DO 都会对应着一个 DTO,这样可以在 DTO 中隐藏不不必要的细节,且 DTO 做成更符合 VO 的方式,这样 DO 不用添加一些和 DB 无关的注解,类似于 JsonIgnore 、JsonFormat 等,DTO 中的可以加上 Size Pattern 等注解,这样更符合最佳实践,不过加上了 spring-boot-starter-data-rest,一切都变得不可控且不易理解
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2290 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 46ms · UTC 15:47 · PVG 23:47 · LAX 08:47 · JFK 11:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.