尋找寫程式碼感覺(十二)之 封裝分頁請求引數和返回引數

久曲健發表於2021-12-07

一、寫在前面

好在上週的加班,有了些成效,終於不用每天熬著了,可以為那段程式畫上一個暫時性的句號了,最後希望專案順利上線。

二、為什麼要進行封裝?

  • 學習的角度看,更加貼近了封裝的特性,使得程式碼整潔,複用率高,鍛鍊自己的能力。
  • 協作的角度看,利人利己。別人調你的方法或者介面,效率更高。

三、如何進行分頁請求引數和返回引數的封裝

從結果導向來看,就是將入參及返回資訊統一化,我們先對請求引數進行改造。

1、入參的改造

新建一個類,並附上頁數和每頁顯示條數兩個屬性,示例程式碼如下:

package com.rongrong.wiki.req;

import lombok.Data;

@Data
public class PageReq {
    private int page;
    private int size;
}

這並沒有完,因為還要保留原來入參,有時候也許還要用這兩個屬性,所以這裡需要繼承PageReq這個類即可,示例程式碼如下:

package com.rongrong.wiki.req;

public class EBookReq extends PageReq {
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", name=").append(name);
        sb.append("]");
        return sb.toString();
    }
}

2、返回資訊的改造

其實,這麼做的好處就是給前端同學更好的表示作用。
未封裝前返回資訊如下所示:

{
  "success": true,
  "message": "執行查詢成功!",
  "content": [
    {
      "id": 1,
      "name": " Spring Boot入門教程 ",
      "category1Id": null,
      "category2Id": null,
      "description": " 零基礎入門Java開發,企業級應用開發最佳首選框架",
      "cover": null,
      "docCount": null,
      "viewCount": null,
      "voteCount": null
    },
    {
      "id": 2,
      "name": " Vue 入門教程 ",
      "category1Id": null,
      "category2Id": null,
      "description": " 零基礎入門Vue開發,企業級應用開發最佳#電子書表",
      "cover": null,
      "docCount": null,
      "viewCount": null,
      "voteCount": null
    },
    {
      "id": 3,
      "name": " Web 自動化入門教程 ",
      "category1Id": null,
      "category2Id": null,
      "description": " Web自動化測試與Selenium 3.0從入門到實踐 #電子書表",
      "cover": null,
      "docCount": null,
      "viewCount": null,
      "voteCount": null
    }
  ]
}

Response code: 200; Time: 226ms; Content length: 585 bytes

接下來我們來進行改造,因為要封裝分頁,那麼肯定需要有共多少也這個屬性,其他返回資訊統一放到一塊去管理,由於不清楚返回型別,我們用泛型T去接收,具體示例程式碼如下:

package com.rongrong.wiki.req;
@Data
public class PageResp<T> {
    private long totalPages;
    private T content;
}

3、對service及介面進行改造

service層示例程式碼如下:

package com.rongrong.wiki.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rongrong.wiki.domain.EBook;
import com.rongrong.wiki.domain.EBookExample;
import com.rongrong.wiki.mapper.EBookMapper;
import com.rongrong.wiki.req.EBookReq;
import com.rongrong.wiki.req.PageResp;
import com.rongrong.wiki.resp.EBookResp;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;

import static com.rongrong.wiki.util.CopyUtil.copyList;

/**
 * @author rongrong
 * @version 1.0
 * @description
 * @date 2021/10/13 23:09
 */
@Service
public class EBookService {

    @Resource
    private EBookMapper eBookMapper;

    public PageResp<EBookResp> list(EBookReq eBookReq) {
        EBookExample eBookExample = new EBookExample();
        //此處程式碼的意思相當於,搞了一個Sql的where條件
        EBookExample.Criteria criteria = eBookExample.createCriteria();
        //劃波浪線為不推薦使用,這裡我們去看原始碼做個替換即可
        if (!ObjectUtils.isEmpty(eBookReq.getName())) {
            criteria.andNameLike("%" + eBookReq.getName() + "%");
        }
        //控制請求後,每頁顯顯示3條資料
        PageHelper.startPage(eBookReq.getPage(), eBookReq.getSize());
        List<EBook> eBookList = eBookMapper.selectByExample(eBookExample);
        PageInfo<EBook> pageInfo = new PageInfo(eBookList);
        System.out.println("共 " + pageInfo.getTotal() + " 條資料");
        System.out.println("共 " + pageInfo.getPages() + " 頁");
        //List<EBookResp> eBookRespList = new ArrayList<>();
        //for (EBook eBook: eBookList) {
        //    //EBookResp eBookResp = new EBookResp();
        //    ////spring boot 自帶的BeanUtils完成物件的拷貝
        //    //BeanUtils.copyProperties(eBook, eBookResp);
        //    //eBookResp.setId(12345L);
        //    //單體複製
        //    EBookResp copy = copy(eBook, EBookResp.class);
        //    eBookRespList.add(copy);
        //}
        //列表複製
        List<EBookResp> respList = copyList(eBookList, EBookResp.class);
        PageResp pageResp = new PageResp<>();
        pageResp.setTotal(pageInfo.getTotal());
        pageResp.setList(respList);
        return pageResp;
    }
}

介面改造部分示例程式碼如下:

package com.rongrong.wiki.controller;

import com.rongrong.wiki.req.EBookReq;
import com.rongrong.wiki.req.PageResp;
import com.rongrong.wiki.resp.CommonResp;
import com.rongrong.wiki.resp.EBookResp;
import com.rongrong.wiki.service.EBookService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author longrong.lang
 * @version 1.0
 * @description
 */
@RestController
@RequestMapping("/ebook")
public class EBookController {

    @Resource
    private EBookService eBookService;

    @GetMapping("/list")
    public CommonResp list(EBookReq eBookReq) {
        CommonResp<PageResp<EBookResp>> resp = new CommonResp<>();
        PageResp<EBookResp> list = eBookService.list(eBookReq);
        resp.setMessage("執行查詢成功!");
        resp.setContent(list);
        return resp;
    }
}

4、對改造程式碼進行測試

測試結果如下:

四、寫在最後

到此,請求和返回資訊的封裝介紹完,感興趣的同學請自行嘗試!

相關文章