SpringBoot——1、基础篇

1、快速上手SpringBoot

1.1、parent

  • 开发SpringBoot程序要继承spring-boot-starter-parent,所有SpringBoot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少依赖冲突的目的;
  • spring-boot-starter-parent中定义了若干依赖管理,各版本间存在着诸多坐标版本不同;
  • 继承parent模块可以避免多个依赖使用相同技术时出现依赖版本冲突;
  • 继承parent的形式也可以采用引入依赖的形式实现效果。

1.2、starter

SpringBoot中常见项目名称,定义了当前项目使用的所有坐标依赖,以达到减少依赖配置的目的。

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

实际开发:

  • 使用任意坐标时,仅书写GAV中的G和A,V由SpringBoot提供,除非SpringBoot未提供对应版本的V;
  • 如发生坐标错误,再指定Version(要小心版本冲突)。

1.3、引导类

package com.clp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Springboot0101QuickstartApplication {

    public static void main(String[] args) {
        //生成可配置的容器对象
        ConfigurableApplicationContext ctx = SpringApplication.run(Springboot0101QuickstartApplication.class, args);
    }
}

SpringBoot的引导类是Boot工程的执行入口,运行main()方法就可以启动项目;

SpringBoot工程运行后初始化Spring容器,扫描引导类所在包加载bean。

1.4、内嵌tomcat

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

SpringBoot内嵌有三款服务器:

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

2、基础配置

2.1、属性配置

2.1.1、修改配置

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

  • application.properties;
    在./resource/application.properties中:
    用(什么技术就开什么配置)
    
    # 服务器的端口配置
    server.port=80
    
    # 修改banner(运行日志图标)
    #spring.main.banner-mode=off # 关闭运行日志图标
    #spring.banner.image.location=logo.png
    
    # 设置日志相关(设置启动日志)
    logging.level.root=debug
    logging.level.com.clp=warn
  • application.yml(常用);
    application.yml:
    
    server:
      port: 80
  • application.yaml;
    application.yaml:
    
    server:
      port:80

不同配置文件中相同配置按照加载优先级相互覆盖,不同配置文件中不同配置全部保留。加载优先级:application.properties -> application.yml -> application.yaml

2.2、YMAL

yaml:YAML(YAML,Ain't Markup Language):一种数据序列化格式。优点:① 容易阅读;② 容易与脚本语言交互;③ 以数据为核心,重数据轻格式。

2.2.1、yaml语法规则

(核心规则:数据前面要加空格与冒号隔开):

  • 大小写敏感;
  • 属性层级关系使用多行描述,每行结尾使用冒号结束;
  • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用tab键);
  • 属性值前面添加空格(属性名与属性值之间用冒号+空格作为分隔);
  • # 表示注释。
    # 设置端口
    server:
      port: 80
    
    user:
      name: zhangsan
      age: 18
      
    users1:
      - name: zhangsan
        age: 18
      - name: lisi
        age: 17
      -
        name: wangwu
        age: 20
    
    users2: [{name: zhangsan, age: 17}, {name: lisi, age: 18}]
    
    a:
      d:
        name: zhangsan
        hobbies:
          - game
          - music
          - sleep 
        hobbies2: [game, music, sleep]

2.2.2、数据读取

使用@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名...}

package com.clp.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/books")
public class BookController {
    /**
     * country: beijing
     */
    //读取yml数据中的单一数据
    @Value("${country}")
    private String country;

    /**
     * user0:
     *   name: zhangsan
     *   age: 18
     */
    @Value("${user0.name}")
    private String name;

    /**
     * users:
     *   - name: zhangsan
     *     age: 18
     *   - name: lisi
     *     age: 20
     * @return
     */
    @Value("${users[0].age}")
    private int age;

    @GetMapping
    public String getById() {
        System.out.println("springboot is running..");
        System.out.println("country: " + country);
        System.out.println("user.name: " + name);
        System.out.println("users[0].age: " + age);
        return "springboot is running...";
    }

}

封装全部数据到Environment对象:

package com.clp.controller;

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired //使用自动装配将application.yml中所有的数据封装到一个对象Environment中
    private Environment env;

    @GetMapping
    public String getById() {
        System.out.println("springboot is running..");
        System.out.println(env.getProperty("server.port"));
        return "springboot is running...";
    }
}

封装部分数据:(注意:封装类需要定义为Spring管理的bean,否则无法进行属性注入)

package com.clp;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * application.yml:
 * # 创建类,用于封装下面的数据
 * # 由spring帮我们去加载数据到对象中,一定要告诉spring加载这些信息
 * # 使用的时候从spring中直接获取信息使用
 * datasource:
 *   driver: com.mysql.jdbc.Driver
 *   url: jdbc:mysql://localhost/springboot_db
 *   username: root
 *   pasword: 123456
 *
 * 步骤:
 * 1、定义数据模型封装yaml文件中对应的数据(变量名要和键的名称一致)
 * 2、定义为spring管控的bean(使用@Component)
 * 3、指定加载的数据(使用@ConfigurationProperties)
 */
@Component
@ConfigurationProperties(prefix = "datasource") //指定加载的数据
public class MyDataSource {
    private String driver;
    private String url;
    private String username;
    private String password;

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}


package com.clp.controller;

import com.clp.MyDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private MyDataSource myDataSource;

    @GetMapping
    public String getById() {
        System.out.println("springboot is running..");
        System.out.println("myDataSource: " +myDataSource);
        return "springboot is running...";
    }
}

2.2.3、yml文件中的变量引用

application.yml:

baseDir: C:\windows
# 使用${属性名}的方式引用数据
tempDir1: ${baseDir}\temp # \t不解析为制表符
# 使用双引号包裹的字符串,其中的转义字符可以生效
tempDir2: "${baseDir}\temp" # \t解析为制表符

3、整合第三方技术

3.1、整合JUnit

步骤:

  1. 导入对应的starter(创建工程时会自动导入);
            <!--默认导入测试相关模块-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            </dependencies>
  2. 测试类使用@SpringBootTest修饰;
  3. 使用自动装配的形式添加要测试的对象。

名称:@SpringBootTest

类型:测试类注解

位置:测试类定义上方

作用:设置JUnit加载的SpringBoot启动类

相关属性:classes:设置SpringBoot启动类。注意:如果测试类在SpringBoot启动类或子包中,可以省略启动类的设置,也就是省略classes的设定;测试类如果不存在于引导类所在的包或子包中需要通过classes属性指定引导类。

范例:

package com.clp;

import com.clp.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(classes = Springboot03JunitApplication.class) //显式地写上引导类
class Springboot03JunitApplicationTests {
    /**
     * 测试步骤:
     * 1、注入你要测试的对象;
     * 2、执行要测试的对象对应的方法
     */
    @Autowired
    private BookDao bookDao;

    @Test
    void contextLoads() {
        bookDao.save();
    }
}

3.2、整合MyBatis

核心配置:数据库连接相关信息(连什么?连谁?什么权限?)

映射配置:SQL映射(XML/注解)

步骤:

  1. 创建新模块,选择Spring初始化,并配置模块相关基础信息;选择当前模块需要使用的技术集Dependencies(MyBatis Framework、MySQL Driver);
  2. 数据库连接相关信息转换成配置。设置数据源参数(在application.yml中):
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/mydb
        username: root
        password: 123456
  3. 数据库SQL映射需要添加@Mapper被容器识别到。定义数据层接口与映射配置:
    package com.clp.dao;
    
    import com.clp.domain.Book;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    
    @Mapper
    public interface BookDao {
        @Select("select * from tbl_book where id = #{id}")
        public Book getById(Integer id);
    }

3.3、整合MyBatis-Plus

3.4、整合Druid

步骤:

  1. 导入Druid对应的starter;
            <!--导入druid相关依赖-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.2.6</version>
            </dependency>
  2. 配置对应的设置或采用默认配置。变更Druid的配置方式如下:
    # 方式1(推荐)
    spring:
      datasource:
        druid:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc.mysql://localhost:3306/mydb?serverTimezone=UTC
          username: root
          password: 123456
    
    # 方式2
    #spring:
    #  datasource:
    #    driver-class-name: com.mysql.jdbc.Driver
    #    url: jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC
    #    username: root
    #    password: 123456
    #    type: com.alibaba.druid.pool.DruidDataSource

整合第三方技术的通用方式:① 导入对应的starter;② 根据提供的配置格式,配置非默认值对应的配置项。

4、基于SpringBoot的SSMP整合案例

案例实现方案分析:

  1. 实体类开发——使用Lombok快速制作实体类;
  2. Dao开发——整合MyBatisPlus,制作数据层测试类;
  3. Service开发——基于MyBatisPlus进行增量开发,制作业务层测试类;
  4. Controller开发——基于Restful开发,使用PostMan测试接口功能;
  5. Controller开发——前后端开发协议制作;
  6. 页面开发——基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理(列表、新增、修改、删除、分页、查询);
  7. 项目异常处理;
  8. 按条件查询——页面功能调整、Controller修正功能、Service修正功能。

4.1、实体类快速开发

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

常用注解:

  • @Data:为当前实体类在编译期设置对应的get() / set()方法,toString()方法, hashCode()方法,equals()方法等。
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

4.2、数据层开发

技术实现方案:MyBatisPlus、Druid。

步骤:

  1. 导入MyBatisPlus与Druid对应的starter:
            <!--因为在parent中没有维护下面这2个版本,所以需要手动加-->
            <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>
  2. 配置数据源与MyBatisPlus对应的配置。(application.yml):
    # 配置端口号
    server:
      port: 80
    # 配置druid数据源
    spring:
      datasource:
        druid:
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:3306/db
          username: root
          password: 123456
    # 配置表前缀
    mybatis-plus:
      global-config:
        db-config:
          table-prefix: tbl_
          id-type: auto #设置自增策略,即执行insert语句时,id增加的方式
  3. 开发Dao接口,并继承BaseMapper并指定泛型:
    package com.clp.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.clp.domain.Book;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    
    @Mapper
    public interface BookDao extends BaseMapper<Book> {
    //    /**
    //     * MyBatis的使用方式
    //     * @param id
    //     * @return
    //     */
    //    @Select("select * from tbl_book where id = #{id}")
    //    Book getById(Integer id);
    }

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

# 配置表前缀
mybatis-plus:
  configuration:
    # 配置日志方式,设置日志输出方式为标准输出
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 

4.2.1、分页

分页操作需要设定分页对象IPage。

    /**
     * 分页功能需要添加一个拦截器(使用配置类进行配置)
     */
    @Test
    void testGetPage() {
        IPage page = new Page(2, 5);
        // 使用IPage封装分页数据,分页操作依赖MyBatis分页拦截器实现功能
        IPage iPage = bookDao.selectPage(page, null); //ipage就是page

        System.out.println(iPage.getCurrent()); // 2 当前页码值
        System.out.println(iPage.getSize()); // 5
        System.out.println(iPage.getTotal()); // 16
        System.out.println(iPage.getPages()); // 4 页数
        System.out.println(iPage.getRecords()); //记录
    }

IPage对象中封装了分页操作中的所有数据:

  • 数据;
  • 当前页码值;
  • 每页数据总量;
  • 最大页码值;
  • 数据总量。

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

/**
 * (配置类)
 */
@Configuration
public class MPConfig {
    /**
     * 配置MyBatisPlus拦截器,交给SpringBoot管理
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //创建mybatis拦截器(壳)
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //添加拦截器1(分页拦截器)
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

4.2.2、条件查询

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

    /**
     * 条件查询
     */
    @Test
    void testGetBy() {
        // 方式1
        QueryWrapper<Book> qw = new QueryWrapper<>();
        //select * from tbl_book where name like 'a';
        qw.like("name", "a");
        List<Book> books = bookDao.selectList(qw);
        System.out.println(books);

        //方式2 使用Lambda表达式
        String name = "a";
        LambdaQueryWrapper<Book> lqw  = new LambdaQueryWrapper<Book>();
        //lqw.like(Book::getName, name);
        // 如果name不为null,则进行查询
        lqw.like(name != null, Book::getName, name);
        bookDao.selectList(lqw);
    }
package com.clp.dao;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.clp.domain.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class BookDaoTest1Case {
    @Autowired
    private BookDao bookDao;

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

    @Test
    void save() {
        Book book = new Book();
        book.setType("测试数据123");
        book.setName("测试数据123");
        book.setDescription("测试数据123");

        bookDao.insert(book);
    }

    @Test
    void testUpdate() {
        Book book = new Book();
        book.setId(17);
        book.setType("abcdefg");
        book.setName("测试数据123");
        book.setDescription("测试数据123");

        bookDao.updateById(book);
    }

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

    @Test
    void testGetAll() {
        List<Book> books = bookDao.selectList(null);
        System.out.println(books);
    }

    /**
     * 分页功能需要添加一个拦截器(使用配置类进行配置)
     */
    @Test
    void testGetPage() {
        IPage page = new Page(2, 5);
        IPage iPage = bookDao.selectPage(page, null); //ipage就是page

        System.out.println(iPage.getCurrent()); // 2 当前页码值
        System.out.println(iPage.getSize()); // 5
        System.out.println(iPage.getTotal()); // 16
        System.out.println(iPage.getPages()); // 4 页数
        System.out.println(iPage.getRecords()); //记录
    }

    /**
     * 条件查询
     */
    @Test
    void testGetBy() {
        // 方式1
        QueryWrapper<Book> qw = new QueryWrapper<>();
        //select * from tbl_book where name like 'a';
        qw.like("name", "a");
        List<Book> books = bookDao.selectList(qw);
        System.out.println(books);

        //方式2 使用Lambda表达式
        String name = "a";
        LambdaQueryWrapper<Book> lqw  = new LambdaQueryWrapper<Book>();
        //lqw.like(Book::getName, name);
        // 如果name不为null,则进行查询
        lqw.like(name != null, Book::getName, name);
        bookDao.selectList(lqw);
    }
}

4.3、业务层开发

Service层接口定义和数据层接口定义具有较大区别,不要混用。Service接口名称定义成业务名称,并与Dao接口名称进行区分。

package com.clp.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.clp.domain.Book;

import java.util.List;

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.clp.service.impl;

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

import java.util.List;

/**
 * 该注解将该类定义成业务层对应的Bean
 */
@Service
public class BookServiceImpl implements BookService {
    @Autowired
    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.getById(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);
        return bookDao.selectPage(page, null);
    }
}
package com.clp.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.clp.domain.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class BookServiceTestCase {
    @Autowired
    private BookService bookService;

    @Test
    void testGetById() {
        Book book = bookService.getById(4);
        System.out.println(book);
    }

    @Test
    void save() {
        Book book = new Book();
        book.setType("测试数据123");
        book.setName("测试数据123");
        book.setDescription("测试数据123");

        bookService.save(book);
    }

    @Test
    void testUpdate() {
        Book book = new Book();
        book.setId(17);
        book.setType("abcdefg");
        book.setName("测试数据123");
        book.setDescription("测试数据123");

        bookService.update(book);
    }

    @Test
    void testDelete() {
        bookService.delete(16);
    }

    @Test
    void testGetAll() {
        List<Book> books = bookService.getAll();
        System.out.println(books);
    }

    /**
     * 分页功能需要添加一个拦截器(使用配置类进行配置)
     */
    @Test
    void testGetPage() {
        IPage iPage = bookService.getPage(2,5); //ipage就是page

        System.out.println(iPage.getCurrent()); // 2 当前页码值
        System.out.println(iPage.getSize()); // 5
        System.out.println(iPage.getTotal()); // 16
        System.out.println(iPage.getPages()); // 4 页数
        System.out.println(iPage.getRecords()); //记录
    }
}

4.3.1、业务层开发——快速开发

快速开发方案:

  1. 使用MyBatisPlus提供有业务通用接口(IService<T>)与业务层通用实现类(ServiceImpl<M,T>);
  2. 在通用类基础上做功能重载或功能追加;
  3. 注意重载时不要覆盖原始操作,避免原始提供的功能丢失。
package com.clp.service;

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

public interface IBookService extends IService<Book> {

}
package com.clp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.clp.dao.BookDao;
import com.clp.domain.Book;
import com.clp.service.IBookService;
import org.springframework.stereotype.Service;

@Service
public class IBookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
}

4.4、表现层开发

  1. 基于Resftul进行表现层接口开发;
  2. 使用Postman测试表现层接口功能。

实体数据:@RequestBody

路径变量:@PathVariable

package com.clp.controller;

import com.clp.domain.Book;
import com.clp.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private IBookService iBookService;

    @GetMapping
    public List<Book> getAll() {
        return iBookService.list();
    }
}
package com.clp.controller;

import com.clp.domain.Book;
import com.clp.service.IBookService;
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 iBookService;

    @GetMapping
    public List<Book> getAll() {
        return iBookService.list();
    }

    @PostMapping
    public Boolean save(@RequestBody Book book) {
        return iBookService.save(book);
    }

    @PutMapping
    public Boolean update(@RequestBody Book book) {
        return iBookService.modify(book);
    }

    @DeleteMapping("{id}")
    public Boolean delete(@PathVariable Integer id) {
        return iBookService.delete(id);
    }

    /**
     * http://localhost/books/2
     */
    @GetMapping("{id}")
    public Book getById(@PathVariable Integer id) {
        return iBookService.getById(id);
    }
}

4.4.1、表现层数据一致性处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值