Integration case of SSMP based on SpringBoot

Integration case of SSMP based on SpringBoot

    • a brief introdction
    • module creation
    • Create entity classes
    • Import the configuration files of Mybatis-plus and druid
    • Use junit to test the query method
    • MP page query
    • query by condition
    • Business Layer Service Development
    • Rapid development of business layer Service
    • presentation layer development
    • Presentation layer implements pagination query
    • Processing of message consistency in the presentation layer
    • Query all book information
    • add book
    • delete operation
    • modify function
    • exception handling function
    • Add pagination query

A brief introduction

Module Creation

Add spring WEB and MYSQL driver dependencies

Then manually add the dependencies of Mybatis-plus and druid

Override configuration file port

Create entity class

Create a Book class under the domain package, and use lombook technology to automatically configure related get set operations

Lombok, a Java class library, provides a set of annotations to simplify the development of POJO entity classes

Add lombok dependency, no need to add coordinates, because parent already contains coordinates

 <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

Simplify development with @Data annotation

package com.ustc.domain;


import lombok.Data;

@Data
public class Book {<!-- -->

    private Integer id;
    private String type;
    private String name;
    private String description;
}


Import configuration files of Mybatis-plus and druid

server:
  port: 80
spring:
  datasource:
    druid:

      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/da?serverTimezone=UTC
      username: root
      password: 123456

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_

# configure druid

Use junit to test the query method

package com.ustc;

import com.ustc.Dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.ustc.domain.Book;
@SpringBootTest
class Sp11ApplicationTests {<!-- -->

    @Autowired
    private BookDao bookDao;

    @Test
    void contextLoads() {<!-- -->
        System.out.println(bookDao.selectById(1));
    }


// insert operation
    @Test
    void testSave(){<!-- -->
        Book book = new Book();
        book.setId(10);
        book.setType("Psychological");
        book.setName("111111111111111111");
        book.setDescription("dshf");
        bookDao.insert(book);
    }

    // update operation
    @Test
    void testSave1(){<!-- -->
        Book book = new Book();
        book.setId(10);
        book.setType("Psychological");
        book.setName("How to become a rich woman");
        book.setDescription("dshf");
        bookDao.updateById(book);
    }

    // delete operation
    @Test
    void testdelete(){<!-- -->
        bookDao.deleteById(1);
    }

    // query all operations
    @Test
    void testGetAll(){<!-- -->
        System.out.println(bookDao.selectList(null));
    }



}


MP page query

  • Create a paging object Page
  • Create a pagination blocker
// Pagination query operation needs to add interceptor in the configuration class
    @Test
    void testGetPage(){<!-- -->
        IPage page = new Page(1,2);//page is the implementation class of IPage

        // Output Data
        System.out.println(bookDao.selectPage(page,null).getRecords());
    }


package com.ustc.config;


import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MPConfig {<!-- -->

    // define interceptor
    // Inject interceptor resource
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){<!-- -->
// create mP interceptor
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());//Add pagination interceptor
        return interceptor;

    }
}


Query by condition

Use the QueryWrapper object to encapsulate the query conditions. It is recommended to use the LambdaQueryWrapper object. All query operations are encapsulated into method calls

 @Test
    void testGetBy(){<!-- -->
        QueryWrapper<Book> qw = new QueryWrapper<>();

// set query conditions
        qw.like("name","Spring");

        bookDao.selectList(qw);//Incoming query conditions
    }

    @Test
    void testGetBy1(){<!-- -->
        LambdaQueryWrapper<Book> qw = new LambdaQueryWrapper<>();

// set query conditions
        qw.like(Book::getName,"Spring");

        bookDao.selectList(qw);//Incoming query conditions
    }

Business layer Service development

The service layer interface definition is quite different from the data layer interface definition, do not mix them

  • selectByUserNameAndPassword(String username,String password) data layer

  • login(String username,String password) business layer

  • Define the service interface

package com.ustc.service;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ustc.domain.Book;
import org.springframework.stereotype.Service;

import java.util.List;


public interface BookService {<!-- -->
// The business layer first defines the interface of the business
    Boolean save(Book book);
    Boolean update(Book book);
    Boolean delete(Integer id);

    Book getById(Integer id);

    List<Book> getAll();

// pagination query interface
    IPage<Book> getPage(int currentPage, int pageSize);
}

  • Define the implementation class of the service interface
package com.ustc.service.Impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ustc.Dao.BookDao;
import com.ustc.domain.Book;
import com.ustc.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


// Define the implementation class as a bean resource of the business layer
@Service
public class BookServiceImpl implements BookService {<!-- -->
// Inject the interface of the data layer
    @Autowired
    private BookDao bookDao;


    @Override
    public Boolean save(Book book) {<!-- -->
        return bookDao.insert(book) > 0;
    }

    @Override
    public Boolean update(Book book) {<!-- -->
        return bookDao.updateById(book) > 0;
    }

    @Override
    public Boolean delete(Integer id) {<!-- -->
        return bookDao.deleteById(id) > 0;
    }

    @Override
    public Book getById(Integer id) {<!-- -->
        return bookDao. selectById(id);
    }

    @Override
    public List<Book> getAll() {<!-- -->
        return bookDao. selectList(null);
    }

    @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {<!-- -->
// First create a pagination query object
        IPage page = new Page(currentPage,pageSize);

        return bookDao.selectPage(page,null);
    }
}

  • Inject bookService interface resources for query testing
// page query
    @Test
    void testGetPage1(){<!-- -->
        IPage<Book> page = bookService. getPage(1,5);
        System.out.println(page.getRecords());

    }

// Use the business layer to query
    @Test
    void test1(){<!-- -->
        System.out.println(bookService.getById(4));
    }

Rapid development of business layer Service

  • First define an IBookService
package com.ustc.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ustc.domain.Book;

public interface IBookService extends IService<Book> {<!-- -->
}


  • Implement the IBookService interface
package com.ustc.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ustc.domain.Book;
import org.springframework.stereotype.Service;


// Remember to inject the implementation class as a bean resource

@Service
public interface IBookService extends IService<Book> {<!-- -->
}
  • Use the common interface (IService) to quickly develop Service
  • Use the general implementation class (ServiceImpl) to quickly develop ServiceImpl
  • Function overloading or function addition can be done on the basis of the general interface
  • Be careful not to overwrite the original operation when overloading, so as to avoid the loss of the functions provided by the original

Presentation layer development

package com.ustc.Controller;


import com.ustc.domain.Book;
import com.ustc.service.IBookService;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/books")
public class BookController {<!-- -->

    @Autowired
    private IBookService bookService;

// query all information

    @GetMapping("/search")
    public List<Book> getAll(){<!-- -->
        return bookService. list();
    }

// Insert data The parameters here transmit json data through the request body Add RequestBody annotation
    @PostMapping("/insert")
    public Boolean save(@RequestBody Book book){<!-- -->
        return bookService. save(book);
    }

    // change the data
    @PutMapping("/update")
    public Boolean update(@RequestBody Book book){<!-- -->
        return bookService. modify(book);
    }

//    delete data
    @DeleteMapping("/delete/{id}")
    public Boolean delete(@PathVariable Integer id){<!-- -->
        return bookService.delete(id);
    }

// Query based on id Use the pathVariable annotation to assign the url parameter to the formal parameter
    @GetMapping("{id}")
    public Book getById(@PathVariable Integer id){<!-- -->
        return bookService. getById(id);
    }

}

Use postman for testing

The presentation layer implements pagination query

  • Controller
 @GetMapping("/page/{currentPage}/{pageSize}")
    public IPage<Book> getPage(@PathVariable int currentPage,@PathVariable int pageSize){<!-- -->
        return bookService.getPage(currentPage,pageSize);

    }

  • service
 @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {<!-- -->
        IPage page = new Page(currentPage,pageSize);
        bookDao.selectPage(page,null);
        return page;
    }

Handling of presentation layer message consistency

Design the model class of the result returned by the presentation layer, which is used to unify the data format between the backend and the frontend, and also become the frontend and backend data protocol

First define an R class, where flag indicates whether the operation of the backend is successful, and data indicates the data transmitted by the backend

package com.ustc.Controller.utils;

import com.sun.org.apache.xpath.internal.operations.Bool;
import com.ustc.domain.Book;
import lombok.Data;


@Data
public class R {<!-- -->
    private Boolean flag;
    private Object data;

    public R(){<!-- -->}


    public R(Boolean flag){<!-- -->
        this.flag = flag;
    }

// Constructor overloading
    public R(Boolean flag,Object data){<!-- -->
        this.flag = flag;
        this.data = data;
    }

}


Afterwards, rewrite the interface method of Controller, insert, modify, and delete operations only need to pass in Boolean parameters, and use another construction method for interfaces that need to return data

package com.ustc.Controller;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ustc.Controller.utils.R;
import com.ustc.domain.Book;
import com.ustc.service.IBookService;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/books")
public class BookController {<!-- -->

    @Autowired
    private IBookService bookService;

// query all information

    @GetMapping("/search")
    public R getAll(){<!-- -->
        return new R(true, bookService. list());
    }

// Insert data The parameters here transmit json data through the request body Add RequestBody annotation
    @PostMapping("/insert")
    public R save(@RequestBody Book book){<!-- -->
        return new R(bookService. save(book));
    }

    // change the data
    @PutMapping("/update")
    public R update(@RequestBody Book book){<!-- -->
// return bookService. modify(book);
        return new R(bookService. modify(book));
    }

//    delete data
    @DeleteMapping("/delete/{id}")
    public R delete(@PathVariable Integer id){<!-- -->
        return new R(bookService. delete(id));
    }

// Query based on id Use the pathVariable annotation to assign the url parameter to the formal parameter
    @GetMapping("{id}")
    public R getById(@PathVariable Integer id){<!-- -->

        // The first parameter is the flag and the second parameter is the object object data
        R r = new R(true,bookService.getById(id));
        return r;
    }

    // Pagination query operation
    @GetMapping("/page/{currentPage}/{pageSize}")
    public R getPage(@PathVariable int currentPage,@PathVariable int pageSize){<!-- -->
        return new R(true,bookService.getPage(currentPage,pageSize));
    }

}

significance:

  • Design a unified return value result type to facilitate front-end development to read data
  • The result type of the return value can be set according to the requirements, and there is no fixed format
  • The return value result type is used to unify the data format between the backend and the frontend, also known as the frontend and backend data protocol

Query all book information

Send an asynchronous request, transfer the data queried by the request backend to the frontend, and the frontend data is bidirectionally bound for data display

Add book

Use axios request to send the front-end request including data to the back-end

  • The request method uses POST to call the background corresponding operation
  • Dynamically refresh the page to load data after the adding operation
  • Depending on the operation result, the corresponding prompt information will be displayed
  • Clear form data when popup adds div
 handleAdd () {<!-- -->
                // Use axios to send data to the backend post request, send the request, return res, check whether the flag operation is successful
                axios.post("/books",this.formData).then((res)=>{<!-- -->

                    // Determine whether the current operation is successful
                    if(res.data.flag){<!-- -->
                        // close popup
                        // Click OK to close the popup window after sending the data
                        this.dialogFormVisible = false;
                        this.$message.success("Added successfully");
                    }else{<!-- -->
                        this.$message.error("Failed to add");
                    }

                }).finally(()=>{<!-- -->
                    // reload data
                    this. getAll();
                });

            },

Delete operation

  • The request method uses Delete to call the corresponding operation in the background
  • The delete operation needs to pass the id value corresponding to the current row data to the background
  • Dynamically refresh the page to load data after the delete operation
  • Depending on the operation result, the corresponding prompt information will be displayed
  • A prompt box pops up before the delete operation to avoid misuse
 // delete
            handleDelete(row) {<!-- -->
               // axios sends an asynchronous request using the deleteMapping parameter is the id delete operation

                this.$confirm("This operation permanently deletes the current information, do you want to continue?","Prompt",{<!-- -->type:"info"}).then(()=>{<!-- - ->
                    axios.delete("/books/" + row.id).then((res)=>{<!-- -->
                        if(res.data.flag){<!-- -->
                            this.$message.success("Deleted successfully");
                        }else{<!-- -->
                            this.$message.error("Delete failed");
                        }
                    }).finally(()=>{<!-- -->
                        // The page will be refreshed regardless of whether the deletion succeeds or fails
                        this. getAll();
                    });
                }).catch(()=>{<!-- -->
                    this.$message.info("Cancel operation");
                });

            },

Modify function

  • Load the data to be modified by passing the id value corresponding to the current row data to the background query data
  • Use front-end data two-way binding to echo the queried data
  • First click the edit button to load the backend data according to the id
  • Then edit the data and pass it to the backend
//Pop up the edit window Click the edit button to load the background data according to the id
            handleUpdate(row) {<!-- -->
                // Send an asynchronous request
                axios.get("/books/" + row.id).then((res)=>{<!-- -->

                    if(res.data.flag & amp; & amp; res.data.data != null){<!-- -->
                        // Content assignment pops up the editing window and fills in the data
                        this.dialogFormVisible4Edit = true;
                        this.formData = res.data.data;
                    }else{<!-- -->
                        this.$message.error("Data synchronization failed, auto refresh");
                    }
                }).finally(()=>{<!-- -->
                    // Reload the data, that is, refresh the page
                    this. getAll();
                });
            },

            //Edit button: The function of this button is to query the data information according to the id and then fill it into the page. The put operation will echo the data modified by the form
            handleEdit() {<!-- -->
               axios.put("/books",this.formData).then((res)=>{<!-- -->
                   // Determine whether the current operation is successful
                   if(res.data.flag){<!-- -->
                       // close the popup
                       this.dialogFormVisible4Edit = false;
                       this.$message.success("Added successfully");
                   }else{<!-- -->
                       this.$message.error("Failed to add");
                   }
               });
            },

Exception handling function

Custom exception

package com.itheima.controller.utils;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

//As an exception handler for springmvc
//@ControllerAdvice
@RestControllerAdvice
public class ProjectExceptionAdvice {<!-- -->
    //Intercept all exception information
    @ExceptionHandler(Exception. class)
    public R doException(Exception ex){<!-- -->
        // log
        //notify operation and maintenance
        // notify development
        ex. printStackTrace();
        return new R("Server failure, please try again later!");
    }
}


  • Use the annotation @RestControllerAdvice to define SpringMVC exception handlers to handle exceptions
  • The exception handler must be scanned and loaded, otherwise it will not take effect
  • Add a message attribute to the model class that returns the result from the presentation layer to pass the message to the page

Add pagination query

Initiate a request call to send the sum of the current page number and the display data volume of each page to the backend for query

 getAll() {<!-- -->
                //Send an asynchronous request
                axios.get("/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize).then((res)=>{<!-- -->
                    // console. log(res. data);

                    this.pagination.pageSize = res.data.data.size;
                    this.pagination.currentPage = res.data.data.current;
                    this.pagination.total = res.data.data.total;

                    // Pass the data sent by the request backend to the frontend Display
                    this.dataList = res.data.data.records;
                });
            },

  • Use el pagination component
  • Define the data model to which the pagination component is bound
  • Asynchronous call to get paged data
  • Paging data page echo