@JsonView的使用

前言

在從學習轉換到實際生產項目中,學到了教程中沒有的知識,實際生產項目更加貼近於實際,用到了更多的方法。就好比Java的一個註解@JsonView。json

應用場景

在實際生產項目中,咱們在後臺返回實體對象轉化的json對象時,不但願後臺返回實體的一些數據給前臺,好比說咱們不但願每次返回用戶時不想把用戶的密碼返回到前臺。這時候咱們就能夠用到@JsonView字段。這個註解的做用就是控制輸入輸出後的json。segmentfault

定義實體類

在網上看了不少例子,大多數都是拿密碼舉例,獲取用戶列表時不須要密碼,獲取具體某個用戶時獲取密碼,可是我感受例子不切合實際,理論上咱們任什麼時候候都不該該返回密碼給前臺(有點較真了,人家只是舉例而已)。因此咱們在此換一個例子。就拿咱們如今寫的系統來講吧:
1.教師端獲取學生做業列表時,獲取做業基本信息便可,
2.獲取具體某個做業時,獲取做業內容。
定義一個做業類app

@Entity
public class Work extends AbstractEntity { 

    private Integer score = 0;
    
    @ManyToMany
    @JsonView(AttachmentsJsonView.class)
    private List<Attachment> attachments = new ArrayList<>();

    @ManyToOne
    @JsonView(ItemJsonView.class)
    @JoinColumn(nullable = false)
    private Item item;

    @ManyToOne
    @JsonView(StudentJsonView.class)
    @JoinColumn(nullable = false)
    private Student student;
    
    public interface AttachmentsJsonView {}
    public interface ItemJsonView {}
    public interface StudentJsonView {}
    
    ...
}

咱們在此截取
四個字段,成績,做業內容,做業所在實驗,做業所關聯學生。咱們但願在在獲取做業列表時獲取做業所在實驗信息和做業所關聯學生信息從而獲取做業基本信息,在查看某一個做業時獲取具體做業內容,而咱們的做業成績是咱們兩個方法都但願返回的。
在做業內容,做業所在實驗,做業所關聯學生分別加上@JsonView,分別定義接口。 而咱們的成績不須要定義,就會默認全部方法都返回。學習

定義方法

如今咱們來到c層,定義方法咱們先來定義接口繼承咱們在實體類規定的接口,想獲取哪些字段就繼承對應接口this

private interface getAllJsonView extends Work.StudentJsonView, Work.ItemJsonView  {

}

private interface getByIdJsonView extends Work.AttachmentsJsonView {

}

而後方法定義code

/**
     * 獲取全部做業
     * @param pageable 分頁信息
     * @return 全部做業
     */
    @GetMapping("getAll")
    @JsonView(getAllJsonView.class)
    public Page<Work> getAll(Pageable pageable) {
        return workService.getAll(pageable);
    }
    
    /**
     * 根據id獲取做業
     * @param id 做業id
     * @return 做業
     */
    @GetMapping("{id}")
    @JsonView(getByIdJsonView.class)
    public Work getById(@PathVariable Long id) {
        return this.workService.findById(id);
    }

不一樣方法分別用JsonView不一樣接口註解,這樣就能返回咱們想要的啦。對象

補充

不一樣方法對應不一樣接口

此時對於獲取具體某個做業再寫一個方法繼承

...
    
    /**
     * 根據id獲取做業
     * @param id 做業id
     * @return 做業
     */
    @GetMapping("{id}")
    @JsonView(getByIdJsonView.class)
    public Work getById(@PathVariable Long id) {
        return this.workService.findById(id);
    }
    
    /**
     * 查看某一學生某一實驗做業
     * @param itemId 實驗id
     * @param studentId 學生id
     * @return 做業
     */
    @GetMapping("getByItemIdAndStudentId")
    @JsonView(getByItemIdAndStudentIdJsonView.class)
    public Work getByItemIdAndStudentId(@RequestParam Long itemId, @RequestParam Long studentId) {
        Optional<Work> workOptional = workService.getByItemIdAndStudentId(itemId, studentId);
        if (workOptional.isPresent()) {
            throw new ObjectNotFoundException("未找到相關做業");
        }
        return workOptional.get();
    }

咱們應該用不一樣接口去定義,即便咱們想要獲取的內容是同樣的教程

private interface getByIdJsonView extends Work.AttachmentsJsonView {
    }

private interface getByItemIdAndStudentIdJsonView extends getByIdJsonView {
    }

可是咱們能夠繼承原來的接口,兩個內容是同樣的。這樣寫的好處是當咱們改變咱們的接口時易於維護,假設不少方法都用一個JsonView,當JsonView改變時不少方法都變了,難以維護。接口

解決棧溢出問題

@JsonView註解還能夠解決死循環致使的棧溢出問題,筆者還沒遇到過,在此就不細述了。
具體看如下博客

@jsonView過濾屬性

總結

在實際生產項目中咱們應該考慮更多,也須要用到更多知識。
在此感謝解決我疑惑的學長和老師。
參考博客
@JsonView的使用

相關文章
相關標籤/搜索