Spring Boot

Spring Boot基础

SpringBoot简介

SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程,简单讲就是牺牲项目的自由度来减少配置的复杂度(“契约式编程”思想,SpringBoot自动配置方案的指导思想)。约定一套规则,把这些框架都自动配置集成好,从而达到“开箱即用”。同时,也支持自由配置。这就是一个非常好的方案了。

SpringBoot让创建独立的,生产环境的基于Spring的应用更加快捷简易。 大部分Spring Boot Application只要一些极简的配置,即可“一键运行”。

SpringBoot的特性如下:

  • 创建独立的Spring applications
  • 能够使用内嵌的Tomcat, Jetty or Undertow,不需要部署war
  • 提供定制化的starter poms来简化maven配置(gradle相同)
  • 追求极致的自动配置Spring
  • 提供一些生产环境的特性,比如特征指标,健康检查和外部配置。
  • 零代码生成和零XML配置

快速上手SpringBoot

SpringBoot入门程序开发

模块创建

创建新模块,选择Spring Initializr,并配置模块相关基础信息

093
094

Tips:

  • 打包方式选择jar
  • 低版本JDK的Java 版本只能选择8,高版本JDK则可选择11
  • 包名止步于com.kiang,不要有后面一串

选择当前模块需要使用的技术集

095

开发控制器类
package com.kiang.controller;

@RestController
@RequestMapping("/books")
public class BookController {
    @GetMapping
    public String getById() {
        System.out.println("springboot is running......");
        return "springboot is running......";
    }
}

牛哇,不用配那一堆乱七八糟的就能嘎嘎跑

096

Tips:

  • 还可以通过基于SpringBoot官网创建项目,或基于阿里云创建项目

  • 懒得创建可以直接复制模块:

    • 制作模板:

      • 删除与Idea相关配置文件,仅保留src目录与pom.xml文件
      • 这些东西导入模块会再自动生成,不必担心
    • 使用模板:

      • 复制一份,文件夹改成模块名

      • 修改 pom.xml 文件的

        <artifactId>springboot_xx_xx_xx</artifactId>
        <name>springboot_xx_xx_xx</name>
        

        101

        • artifactId 相当于项目标识,相同则会冲突
        • name 是在 Maven 中显示的名称,就算相同也不会冲突,甚至可以删掉,缺省会显示 artifactId。
      • 导入模块,选择外部 Maven

        102

浅谈入门程序工作原理

所以说这玩意儿跑起来全靠:

  • pom.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.6.5</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.kiang</groupId>
    	<artifactId>springboot_01_01_quickstart</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>springboot_01_01_quickstart</name>
    	<description>Demo project for Spring Boot</description>
    	<properties>
    		<java.version>11</java.version>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    				<version>2.6.5</version>
    			</plugin>
    		</plugins>
    	</build>
    </project>
    

    Tips:

    默认插件配置会爆红

    096

    得加自己框架版本号一致的版本号

    098

  • Application类

    package com.kiang;
    
    @SpringBootApplication
    public class Springboot0101QuickstartApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(Springboot0101QuickstartApplication.class, args);
    	}
    }
    
parent

从pom.xml可以看到开发SpringBoot程序要继承spring-boot-starter-parent:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.5</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

而且pom.xml里的依赖都不需要写version,这就是spring-boot-starter-parent的作用。spring-boot-starter-parent中定义了若干个依赖管理,继承parent模块可以避免多个依赖使用相同技术时出现依赖版本冲突(早期是需要手动调包解决冲突的)。

099

starter

100

开发SpringBoot程序需要导入坐标时通常导入对应的starter,每个不同的starter根据功能不同,通常包含多个依赖坐标,使用starter可以实现快速配置的效果,达到简化配置的目的。

引导类

SpringBoot工程提供引导类用来启动程序, 工程启动后创建并初始化Spring容器。

SpringBoot的引导类是Boot工程的执行入口,运行main方法就可以启动项目。SpringBoot工程运行后初始化Spring容器,扫描引导类所在包加载bean。

内嵌tomcat

内嵌Tomcat服务器是SpringBoot辅助功能之一,其工作原理是将Tomcat服务器作为对象运行,并将该对象交给Spring容器管理。变更内嵌服务器思想是去除现有服务器,添加全新的服务器。

其内置了多种服务器:

  • tomcat(默认):apache出品,粉丝多,应用面广,负载了若干较重的组件
  • jetty:更轻量级,负载性能远不及tomcat
  • undertow:undertow,负载性能勉强跑赢tomcat

SpringBoot基础配置

properties文件配置

  • 修改服务器端口:

    server.port=80
    
  • 关闭运行日志图标(banner)

    spring.main.banner-mode=off
    
  • 设置日志相关

logging.level.root=debug

更多属性可在Spring Boot官网文档附录Application Properties查看

多种属性配置方式

SpringBoot提供了多种属性配置方式

  • application.properties

    server.port=80
    
  • application.yml (主流格式)

    server:
      port: 80
    
  • application.yaml

    server:
      port: 80
    
  • SpringBoot三种配置文件加载顺序:

    application.properties —> application.yml —> application.yaml

yaml

简介

YAML(YAML Ain’t Markup Language),一种数据序列化格式

  • 容易阅读
  • 容易与脚本语言交互
  • 以数据为核心,重数据轻格式
yaml语法规则
  • 大小写敏感
  • 属性层级关系使用多行描述,每行结尾使用冒号结束
  • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
  • 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
  • # 表示注释
字面值表示方式
  • boolean: TRUE #TRUE,true,True,FALSE,false,False均可
  • float: 3.14 #6.8523015e+5 #支持科学计数法
  • int: 123 #0b1010_0111_0100_1010_1110 #支持二进制、八进制、十六进制
  • null: ~ #使用~表示null
  • string: HelloWorld #字符串可以直接书写 string2: “Hello World” #可以使用双引号包裹特殊字符
  • date: 2018-02-17 #日期必须使用yyyy-MM-dd格式
  • datetime: 2018-02-17T15:02:31+08:00 #时间和日期之间使用T连接,最后使用+代表时区
数组表示方式

在属性名书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔:

users: #对象数组格式
  - name: Tom
  age: 4
  - name: Jerry
  age: 5
  users: #对象数组格式二
  -
  name: Tom
  age: 4
  -
  name: Jerry
  age: 5 
  
#对象数组缩略格式
users2: [ { name:Tom , age:4 } , { name:Jerry , age:5 } ]
yaml数据读取
lesson: SpringBoot

server:
  port: 82

enterprise:
  name: itcast
  age: 16
  tel: 4006184000
  subject:
    - Java
    - 前端
    - 大数据
  • 使用@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名……}

    @RestController
    @RequestMapping("/books")
    public class BookController {
        @Value("${lesson}")
        private String lessonName;
        @Value("${server.port}")
        private int port;
        @Value("${enterprise.subject[1]}")
        private String[] subject_01;
    }
    

    103

  • 在配置文件中可以使用属性名引用方式引用属性

    baseDir: /usr/local/fire
    
    center:
      dataDir: ${baseDir}/data
      tmpDir: ${baseDir}/tmp
      logDir: ${baseDir}/log
      msgDir: ${baseDir}/msgDir
    
  • 属性值中如果出现转义字符,需要使用双引号包裹

    lesson: "Spring\tboot\nlesson"
    
  • 可以封装全部数据到Environment对象,使用@Autowired自动装配

    @RestController
    @RequestMapping("/books")
    public class BookController {
        @Autowired
        private Environment env;
        @GetMapping("/{id}")
        public String getById(@PathVariable Integer id){
            System.out.println(env.getProperty("lesson"));
            System.out.println(env.getProperty("enterprise.name"));
            System.out.println(env.getProperty("enterprise.subject[0]"));
            return "hello , spring boot!";
        }
    }
    

    104

  • 自定义对象封装指定数据

    @Component
    @ConfigurationProperties(prefix = "enterprise")
    public class Enterprise {
        private String name;
        private Integer age;
        private String[] subject;
        // 省略get、tostring
    }
    
    @RestController
    @RequestMapping("/books")
    public class BookController {
        @Autowired
        private Enterprise enterprise;
    }
    

    105

整合第三方技术

整合JUnit

  1. 导入测试对应的starter

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
  2. 测试类使用@SpringBootTest修饰

    package com.kiang;
    
    @SpringBootTest
    class Springboot04JunitApplicationTests {
    }
    
  3. 使用自动装配的形式添加要测试的对象

    package com.kiang;
    
    @SpringBootTest
    class Springboot04JunitApplicationTests {
    	// 注入测试对象
    	@Autowired
    	private BookDao bookDao;
    	@Test
    	void contextLoads() {
    		bookDao.save();
    	}
    }
    

Tips:

  • 测试类如果存在于引导类所在包或子包中无需指定引导类

  • 测试类如果不存在于引导类所在的包或子包中需要通过 classes 属性指定引导类

    @SpringBootTest(classes = 引导类类名.class)
    class Springboot04JunitApplicationTests {
    }
    

整合MyBatis

  1. 创建模块

    MyBatis需要选择的技术是 MyBatis Framework 和 MySQL Driver

    勾选MyBatis技术,即可导入MyBatis对应的starter

    106

  2. 设置数据源参数

    # 配置相关信息
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
        username: root
        password: 102576
    
    
  3. 定义数据层接口与映射配置

    数据库SQL映射需要添加@Mapper被容器识别到,@Mapper注释用来表示该接口类的实现类对象交给mybatis底层创建,然后交由Spring框架管理。

    package com.kiang.dao;
    
    @Mapper
    public interface BookDao {
        @Select("select * from tbl_book where id = #{id}")
        public Book getById(Integer id);
    }
    
  4. 测试类中注入dao接口,测试功能

    会报 “无法自动装配。未找到 ‘BookDao’ 类型的 Bean” 错误,但不影响运行。

    package com.kiang;
    
    @SpringBootTest
    class Springboot05MybatisApplicationTests {
    
    	@Autowired
    	private BookDao bookDao;
    
    	@Test
    	void contextLoads() {
    		System.out.println(bookDao.getById(1));
    		ApplicationContext ac = new ClassPathXmlApplicationContext();
    	}
    }
    

整合Druid

  1. 创建模块

    与整合MyBatis一样需要选择的技术是 MyBatis Framework 和 MySQL Driver

    对应 starter 需要手动导入

  2. 导入Druid对应的starter

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.6</version>
    </dependency>
    
  3. 指定数据源类型

    #spring:
    #  datasource:
    #    driver-class-name: com.mysql.jdbc.Driver
    #    url: jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
    #    username: root
    #    password: 102576
    #    type: com.alibaba.druid.pool.DruidDataSource
    #推荐下面这种方法:
    spring:
      datasource:
        druid:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
          username: root
          password: 102576
    
  4. 其余同整合MyBatis一样

基于SpringBoot的整合SSMP整合案例

项目创建

勾选 MySQL Driver 和 Web 技术即可,其余的需要手动导入

导入坐标

<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>

实体类开发

Lombok

一个Java类库,提供了一组注解,简化POJO实体类开发

使用需导坐标装插件:

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

lombok版本由SpringBoot提供,无需指定版本。

107

使用方式:

  • @Getter/@Setter:作用类上,生成所有成员变量的getter/setter方法;作用于成员变量上,生成该成员变量的getter/setter方法。可以设定访问权限及是否懒加载等。
  • @ToString:作用于类,覆盖默认的toString()方法,可以通过of属性限定显示某些字段,通过exclude属性排除某些字段。
  • @EqualsAndHashCode:作用于类,覆盖默认的equals和hashCode
  • @RequiredArgsConstructor:生成包含final和@NonNull注解的成员变量的构造器;
  • @Data:作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
实体类
package com.kiang.domain;

@Data
public class Book {
    private Integer id;
    private String type;
    private String name;
    private String description;

}

数据层开发

技术实现方案:MyBatisPlus + Druid

配置数据源与MyBatisPlus对应的基础配置

(id生成策略使用数据库自增策略)

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
      username: root
      password: 102576

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_
      id-type: auto
继承BaseMapper并指定泛型
package com.kiang.domain.dao;

@Mapper
public interface BookDao extends BaseMapper<Book> {

}

MP已实现基本的增删改查,故直接继承即可使用,也再添加。

可以大概测一下基本增删改查:

package com.kiang.dao;

@SpringBootTest
public class BookDaoTestCase {

    @Autowired
    private BookDao bookDao;

    @Test
    void testGetById() {
        System.out.println(bookDao.selectById(1));
    }

    @Test
    void testSave() {
        Book book = new Book();
        book.setType("test");
        book.setName("test");
        book.setDescription("test");
        bookDao.insert(book);
    }

    @Test
    void testUpdate() {
        Book book = new Book();
        book.setId(7);
        book.setType("test1");
        book.setName("test1");
        book.setDescription("test1");
        bookDao.updateById(book);
    }

    @Test
    void testDelete() {
        bookDao.deleteById(7);
    }

}

为方便调试可以开启MyBatisPlus的日志:

configuration:
  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
分页功能
@Test
void testGetPage() {
    IPage page = new Page(1,5);
    IPage page1 = bookDao.selectPage(page,null);
}

IPage对象中封装了分页操作中的所有数据:数据、当前页码值 、每页数据总量、最大页码值 和数据总量。

分页操作是在MyBatisPlus的常规操作基础上增强得到,内部是动态的拼写SQL语句,因此需要增强对应的功能, 使用MyBatisPlus拦截器实现

package com.kiang.config;

@Configuration
public class MPConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

焯,千万不要把@Configuration写成@Configurable

条件查询功能

使用QueryWrapper对象封装查询条件,推荐使用LambdaQueryWrapper对象,所有查询操作封装成方法调用

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

@Test
void testGetBy2() {
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
    lqw.like(Book::getName,"c");
    bookDao.selectList(lqw);
}

业务层开发

接口定义
package com.kiang.service;

public interface BookService {
    Boolean save(Book book);
    Boolean update(Book book);
    Boolean delete(Integer id);
    Book getById(Integer id);
    List<Book> getAll();
    IPage<Book> getPage(int currentPage, int pageSize);
}
实现类定义
package com.kiang.service.impl;

@Service
public class BookServiceImpl2 implements BookService {
    @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) {
        IPage page = new Page(currentPage,pageSize);
        bookDao.selectPage(page,null);
        return page;
    }
}
测试类定义
package com.kiang.service;

@SpringBootTest
public class BookServiceTestCase {
    @Autowired
    private BookService bookService;
    @Test
    void testGetById() {
        System.out.println(bookService.getById(4));
    }
    @Test
    void testSave(){
        Book book = new Book();
        book.setType("test");
        book.setName("test");
        book.setDescription("test");
        bookService.save(book);
    }
    @Test
    void testUpdate(){
        Book book = new Book();
        book.setId(16);
        book.setType("test1");
        book.setName("test1");
        book.setDescription("test1");
        bookService.update(book);
    }
    @Test
    void testDelete(){
        bookService.delete(16);
    }
    @Test
    void testGetAll(){
        bookService.getAll();
    }
    @Test
    void testGetPage() {
        IPage<Book> page = bookService.getPage(2, 5);
        System.out.println(page.getCurrent());
        System.out.println(page.getSize());
        System.out.println(page.getTotal());
        System.out.println(page.getPages());
        System.out.println(page.getRecords());
    }
}
快速开发
接口定义
package com.kiang.service;

public interface IBookService extends IService<Book> {
    boolean saveBook(Book book);
    boolean modify(Book book);
    boolean delete(Integer id);
    IPage<Book> getPage(int currentPage, int pageSize);
    IPage<Book> getPage(int currentPage, int pageSize, Book book);
}
实现类定义
package com.kiang.service.impl;

@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
    @Autowired
    private BookDao bookDao;
    @Override
    public boolean saveBook(Book book) {
        return bookDao.insert(book) > 0;
    }
    @Override
    public boolean modify(Book book) {
        return bookDao.updateById(book) > 0;
    }
    @Override
    public boolean delete(Integer id) {
        return bookDao.deleteById(id) > 0;
    }
    @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {
        IPage page = new Page(currentPage,pageSize);
        bookDao.selectPage(page,null);
        return page;
    }
    @Override
    public IPage<Book> getPage(int currentPage, int pageSize, Book book) {
        LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
        lqw.like(Strings.isNotEmpty(book.getType()),Book::getType,book.getType());
        lqw.like(Strings.isNotEmpty(book.getName()),Book::getName,book.getName());
        lqw.like(Strings.isNotEmpty(book.getDescription()),Book::getDescription,book.getDescription());
        IPage page = new Page(currentPage,pageSize);
        bookDao.selectPage(page,lqw);
        return page;
    }
}

表现层开发

表现层接口开发
package com.kiang.Controller;

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private IBookService bookService;
    @GetMapping
    public List<Book> getAll() {
        return bookService.list();
    }
    @PostMapping
    public Boolean save(@RequestBody Book book) {
        return bookService.save(book);
    }
    @PutMapping
    public Boolean update(@RequestBody Book book) {
        return bookService.modify(book);
    }
    @DeleteMapping("{id}")
    public boolean delete(@PathVariable Integer id) {
        return bookService.delete(id);
    }
    @GetMapping("{id}")
    public Book getById(@PathVariable Integer id) {
        return bookService.getById(id);
    }
}

使用Postman逐一测试

表现层消息一致性处理
package com.kiang.Controller.utils;

@Data
public class R {
    private Boolean flag;
    private Object data;

    public R() {
    }

    public R(Boolean flag) {
        this.flag = flag;
    }

    public R(Boolean flag, Object data) {
        this.flag = flag;
        this.data = data;
    }
}

返回数据改成类似这种:

@GetMapping
public R getAll() {
    // return bookService.list();
    return new R(true, bookService.list());
}
前后端协议联调
  • 单体项目中页面放置在 resources/static 目录下
  • created 钩子函数用于初始化页面时发起调用
  • 页面使用axios发送异步请求获取数据后确认前后端是否联通
前端发送异步请求,调用后端接口
getAll() {
    axios.get("/books").then((res)=>{
        console.log(res);
    })
}
列表页

将查询数据返回到页面,利用前端数据双向绑定进行数据展示

getAll() {
    axios.get("/books").then((res)=>{
        // console.log(res);
        this.dataList = res.data.data;
    })
}
弹出添加窗口
//弹出添加窗口
handleCreate() {
    this.dialogFormVisible = true;
}
清除表单数据
//弹出添加窗口
handleCreate() {
    this.dialogFormVisible = true;
    this.resetForm();
},
//重置表单
resetForm() {
    this.formData = {};
}
添加
handleAdd () {
    axios.post("/books", this.formData).then((res)=>{
        if(res.data.flag){
            this.dialogFormVisible = false;
            this.$message.success("添加成功");
        }else{
            this.$message.success("添加失败");
        }
    }).finally(()=>{
        this.getAll();
    })
}
取消添加
cancel(){
    this.dialogFormVisible = false;
    this.$message.info("当前操作取消");
}
删除
  • 请求方式使用Delete调用后台对应操作
  • 删除操作需要传递当前行数据对应的id值到后台
  • 删除操作结束后动态刷新页面加载数据
  • 根据操作结果不同,显示对应的提示信息
  • 删除操作前弹出提示框避免误操作
handleDelete(row) {
    this.$confirm("此操作为永久删除,是否继续?","提示",{type: "info"}).then(()=>{
        axios.delete("/books/" + row.id).then((res)=>{
            if(res.data.flag){
                this.$message.success("删除成功");
            }else{
                this.$message.error("删除失败");
            }
        }).finally(()=>{
            this.getAll();
        })
    }).catch(()=>{
        this.$message.info("当前操作取消");
    })
}
弹出修改窗口
handleUpdate(row) {
    axios.get("/books/" + row.id).then((res)=>{
        if(res.data.flag && res.data.data != null){
            this.dialogFormVisible4Edit = true;
            this.formData = res.data.data;
        }else {
            this.$message.error("数据同步失败");
        }
    }).finally(()=>{
        this.getAll();
    })
}
修改

和添加逻辑相同只是请求方式不同

handleEdit() {
    axios.put("/books", this.formData).then((res)=>{
        if(res.data.flag){
            this.dialogFormVisible4Edit = false;
            this.$message.success("修改成功");
        }else{
            this.$message.success("修改失败");
        }
    }).finally(()=>{
        this.getAll();
    })
}
业务消息一致性处理

修改表现层返回结果的模型类,封装出现异常后对应的信息

package com.kiang.Controller.utils;

@Data
public class R {
    private Boolean flag;
    private Object data;
    private String msg;
}

写个异常处理,否则出异常会返回:

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

写个异常处理模块

package com.kiang.Controller.utils;

@RestControllerAdvice
public class ProjectExceptionAdvice {

    @ExceptionHandler
    public R doException(Exception ex) {
        ex.printStackTrace();
        return new R("服务器故障");
    }
}
分页功能
getAll() {
    axios.get("/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize).then((res)=>{
        this.pagination.pageSize = res.data.data.size;
        this.pagination.currentPage = res.data.data.current;
        this.pagination.total = res.data.data.total;

        this.dataList = res.data.data.records;
    });
}
handleCurrentChange(currentPage) {
    this.pagination.currentPage = currentPage;
    this.getAll();
}

原文地址:http://www.cnblogs.com/AncilunKiang/p/16837678.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性