SpringBoot+MP+ElementUI【分頁】

燕子去了發表於2024-04-01

SpringBoot+MP+ElementUI【分頁】

其餘的增刪改操作:p45/p46/p47/p48:springboot2

依賴
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>
配置
spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      username: root
      password: 1234
mybatis-plus:
  global-config:
    db-config:
      table-prefix: tb_1
      id-type: auto #透過id自增長
  configuration:
    log-impl: org.apache.ibatis.logging,stdout.StdOutImpl  #開啟MP執行日誌
mp分頁要使用mp提供的攔截器

建立攔截器,增加分頁功能

@Configuration
public class MPConfig{
    @Bean
    public MybatisInterceptor mybatisInterceptor(){
        MybatisInterceptor mybatisInterceptor = new MybatisInterceptor();
        mybatisInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisInterceptor;
    }
}

執行分頁得到的是一個ipage物件,透過ipage物件可以得到一些資料,當前頁每頁記錄數或查詢到的資料;

@Test
void testGetPage(){
	Ipage ipage = new IPage(1,5);
	bookMapper.selectPage(ipage,null); //
}
條件查詢

普通的條件查詢

@Test
void testGetBy(){
    QueryWrapper<Book> qw = new QueryWrapper<>();
    qw.like("name","spring");
    bookMapper.selectList(qw);
}

lambda格式【推薦】

支援動態拼寫查詢條件

@Test
void testGetBy(){
    String name = "spring";
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
    lqw.like(name!=null,book::getName,name);
    bookMapper.selectList(lqw);
}
業務層Service開發

get、remove、update、save、page

使用mp提供的通用介面(IService)和業務層通用實現類(ServiceImpl<M,T>);不滿足時可以過載或追加,過載時儘量不要覆蓋原始操作

public interface IBookService extends Iservice<Book> {
    
}
@Service
public class IBookServiceImpl extends ServiceImpl<BookMapper,Book> implements IBookService {
    
}
@Test
void testGetPage(){
	Ipage<Book> ipage = new IPage<Book>(1,5);
	iBookService.page(ipage,null); //
}
表現層標準開發
@GetMapping("{currentPage}/{pageSize}")
public IPage<Book> getPage(@PathVariable int currentPage,@PathVariable int pageSize){
    return bookMapper.getPage(currentPage,pageSize);
}
public interface IBookService extends IService<Book>{
    IPage<Book> getPage(int currentPage,int pageSize);
}
@Service
public class IBookServiceImpl extends ServiceImpl<BookMapper,Book> implements IBookService{
    @Autowired
    private BookMapper bookMapper;
    @Override
    public IPage<Book> getPage(int currentPage,int pageSize){
        Page Page = new Page(currentPage,pageSize);
        bookMapper.selectPage(Page,null);
        return Page;
    }
}
統一返回格式

前後端資料協議

Result類提供不同構造方法,表現層new Result()返回出Result類

後端統一異常處理器

前端返回異常訊息處理,當後臺報錯時,可能返回的資料為,與正常狀態下後端返回的統一格式(msg、data、code)不一致

{
    "timestamp":"2021-09-15T03:27:31.038+00:00",
    "status":500,
    "error": "Internal Server Error",
    "path": "/books"
}

建立異常處理器攔截所有異常

註解可以寫不同的異常型別

國際化,後臺提供成功的和失敗的返回資料

@RestControllerAdvice
public class ProjectExceptionAdvice{
    @ExceptionHandler(Exception.class)
    public void doException(Exception e){
        //記錄日誌,通知運維開發等
        return New Result(false,null,"伺服器故障,請聯絡管理員");
    }
}
@PostMapping
public Result save(@RequestBody Book book) throws IOException{
    Boolean flag = bookService.insert(book);
    return new Result(flag,flag?"新增成功":"新增失敗");
}
//新增
handleAdd(){
    //傳送ajax請求
    axios.post("/books",this.formData).then((res)=>{
        if(res.data.flag){
            this.dialogFormVisible =false;
            this.$message.success(res.data.msg);
        }else {
            this.$message.error(res.data.msg);
        }
    }).finally(()=>{
        this.getA1ll();
    });
}
elementUI分頁元件

一般都是分頁查詢,不用列表查詢getAll()

<el-table :data="dataList">
    <el-table-column type="name" lable="圖書名稱" align="center"></el-table-column>
    <el-table-column type="type" lable="圖書類別" align="center"></el-table-column>
</el-table>


<div class="pagination-container">
    <el-pagination
                   class="pagination"
                   @Current-change="handleCurrentChange"
                   :current-page="pagination.currentPage"
                   :Page-size = "pagination.pageSIze"
                   :total="pagination.tatal"
                   layout="total.prev,pager,next,jumper">
    </el-pagination>
</div>
data: {
    dataList:[],
    pagination: {
        currentPage: 1,
        pageSize:10,
        total:0
    }
}

res.data.data中的第一個data是response物件中的屬性,表示伺服器返回的資料;第二個data是伺服器返回的資料中的欄位名,表示具體的資料。

getAll(){
    axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res)=>{
        this.pagination.currentPage=res.data.data.size;
        this.pagination.pageSize=res.data.data.size;
        this.pagination.total=res.data.data.total;
        this.dataList = res.data.data.records;
    })
}
handleCurrentChange(currentPage){
    this.pagination.currentPage=currentPage;
    this.getAll();
}

當把最後一頁的資料全刪了,但是不跳轉到新的最後一頁,展示一個空頁面

但是一次刪的數量大於size,可以有其他的解決方案,分析業務需求,可以跳到第一頁等

@GetMapping("{currentPage}/{pageSize}")
public Result getPage(@PathVariable int currentSize,@PathVariable int pageSize){
    IPage<Book> page = bookService.getPage(currentSize,pageSize);
    if(currentPage > page.getPages()){
        page = bookService.getPage((int)page.getPages(),pageSize);
    }
    return new Result(true,page);
}
elementUI+條件查詢

分頁+條件

<div class="filter-container">
    <el-input placeholder="圖書類別" class="filter-item" v-model="pagination.type"></el-input>
    <el-input placeholder="圖書名稱" class="filter-item" v-model="pagination.name"></el-input>
    <el-input placeholder="圖書描述" class="filter-item" v-model="pagination.desc"></el-input>
    <el-button @click="getA1l()" class="dalfBut">査詢</el-button>
    <el-button type="primary" class="butT" @click="handlecreate()">新建</e1-button>
</div>
data: {
    dataList:[],
    pagination: {
        currentPage: 1,
        pageSize:10,
        total:0,
        type:"",
        name:"",
        desc:""
    }
}

/books/1/10?type=?&name=?&desc=?

html

getAll(){
    param = "?type="+this.pagination.type;
    param += "&name="+this.pagination.name;
    param += "&desc="+this.pagination.desc;
    axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res)=>{
        this.pagination.currentPage=res.data.data.size;
        this.pagination.pageSize=res.data.data.size;
        this.pagination.total=res.data.data.total;
        this.dataList = res.data.data.records;
    })
}

controller

@GetMapping("{currentPage}/{pageSize}")
public Result getPage(@PathVariable int currentSize,@PathVariable int pageSize,Book book){
    IPage<Book> page = bookService.getPage(currentSize,pageSize,book);
    if(currentPage > page.getPages()){
        page = bookService.getPage((int)page.getPages(),pageSize,book);
    }
    return new Result(null != page,page);
}

js

@GetMapping("{currentPage}/{pageSize}")
public IPage<Book> getPage(@PathVariable int currentPage,@PathVariable int pageSize){
    return bookMapper.getPage(currentPage,pageSize);
}

Service

public interface IBookService extends IService<Book>{
    IPage<Book> getPage(int currentPage,int pageSize);
    IPage<Book> getPage(int currentPage,int pageSize,Book book);
}
@Service
public class IBookServiceImpl extends ServiceImpl<BookMapper,Book> implements IBookService{
    @Autowired
    private BookMapper bookMapper;
    
    @Override
    public IPage<Book> getPage(int currentPage,int pageSize){
        Page Page = new Page(currentPage,pageSize);
        bookMapper.selectPage(Page,null);
        return Page;
    }
    
    @Override
    public IPage<Book> getPage(int currentPage,int pageSize,Book book){
        Page Page = new Page(currentPage,pageSize);
        LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
        lwq.like(String.isNotEmpty(book.getName()),Book::getName,book.getName());
        lwq.like(String.isNotEmpty(book.getType()),Book::getType,book.getType());
        lwq.like(String.isNotEmpty(book.getDesc()),Book::getDesc,book.getDesc());
        return bookMapper.selectPage(Page,lwq);
    }
}

判斷拼接,具體看業務情況

param = "?query";
param = "&type="+this.pagination.type;
param += "&name="+this.pagination.name;
param += "&desc="+this.pagination.desc;
console.log(param);