aoe1231

知之为知之,不知为不知

SpringBoot入门

1、SpringBoot简介

SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。

1.1、原生开发SpringMVC程序过程

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
/**
 * 定义一个servlet容器启动的配置类,在里面加载spring的配置(需继承AbstractDispatcherServletInitializer,这样tomcat可以探测到这个类)
 */
public class ServletConfig extends AbstractDispatcherServletInitializer {
    /*
    * 注:Web容器(Tomcat)启动时,会加载SpringMvcConfig和SpringConfig配置类。
    *   这两个配置类产生的容器对象不是同一个对象。
    *   SpringMVC容器能访问Spring容器,而Spring容器不能访问SpringMVC容器。
    * */

    // 加载SpringMVC容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }

    // 拦截请求:设置哪些请求归属SpringMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"}; // 所有请求归SpringMVC进行处理
    }

    // 加载Spring容器的配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }

    // 设置过滤器,处理中文乱码问题
    @Override
    protected Filter[] getServletFilters() {
        // Post请求中文乱码处理:配置字符过滤器,为web容器添加过滤器并指定字符集,spring-web包中提供了专用的字符过滤器
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new Filter[]{filter};
    }
}
@Configuration
@ComponentScan({"com.clp.service"})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
@EnableTransactionManagement // 开启事务管理器
public class SpringConfig {
}
@Configuration
@ComponentScan({"com.clp.controller"})
@EnableWebMvc // 开启由json数据转换成对象的功能
public class SpringMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ProjectInterceptor projectInterceptor;
    @Autowired
    private ProjectInterceptor2 projectInterceptor2;

    /**
     * 配置拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // addPathPatterns()方法的参数表示拦截的url字符串匹配则进行拦截
        // 拦截器链的执行顺序与添加顺序有关
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");
        registry.addInterceptor(projectInterceptor2).addPathPatterns("/books", "/books/*");
    }
}
/*
 * @RestController:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能。
 * @GetMapping & @PostMapping & @PutMapping & @DeleteMapping:
 *   设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping对应GET请求。
 * */
//@Controller
//@ResponseBody
@RestController // @RestController = @Controller + @ResponseBody
@RequestMapping("/books")
public class BookController {
    @Autowired
    private BookService bookService;

    //    @RequestMapping(method = RequestMethod.POST)
    @PostMapping // @PostMapping = @RequestMapping(method = RequestMethod.POST)
    public Result post(@RequestBody Book book) {
        boolean flag = bookService.save(book);
        int i = 1 / 0;
        return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag);
    }

    //    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    @DeleteMapping("/{id}") // @DeleteMapping("/{id}") = @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Result delete(@PathVariable Integer id) {
        boolean flag = bookService.delete(id);
        return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);
    }

    //    @RequestMapping(method = RequestMethod.PUT)
    @PutMapping // @PutMapping = @RequestMapping(method = RequestMethod.PUT)
    public Result put(@RequestBody Book book) {
        boolean flag = bookService.update(book);
        return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, flag);
    }

    //    @RequestMapping(value = "/{id}}", method = RequestMethod.GET)
    @GetMapping("/{id}") // @GetMapping("/{id}") = @RequestMapping(value = "/{id}}", method = RequestMethod.GET)
    public Result get(@PathVariable Integer id) {
        Book book = bookService.getById(id);
        return new Result(
                book != null ? Code.GET_OK : Code.GET_ERR,
                book,
                book != null ? "查询成功" : "查询失败"
        );
    }

    //    @RequestMapping(method = RequestMethod.GET)
    @GetMapping // @GetMapping = @RequestMapping(method = RequestMethod.GET)
    public Result getAll() {
        List<Book> bookList = bookService.getAll();
        return new Result(
                bookList != null ? Code.GET_OK : Code.GET_ERR,
                bookList,
                bookList != null ? "查询成功" : "查询失败"
        );
    }
}

1.2、SpringBoot快速入门

1.2.1、创建SpringBoot项目

创建新模块,选择Spring初始化,并配置模块相关基础信息。然后选择当前模块需要使用的技术集。

1.2.2、开发控制器类

@RestController
@RequestMapping("/books")
public class BookController {
    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id) {
        System.out.println("id: " + id);
        return "hello, springboot!";
    }
}

1.2.3、运行自动生成的Application类(引导类)

@SpringBootApplication
public class Springboot0101QuickstartApplication {

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

1.3、最简SpringBoot程序所包含的基础文件

1、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.11</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.clp</groupId>
    <artifactId>module_01_quickstart</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>module_01_quickstart</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</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>
            </plugin>
        </plugins>
    </build>

</project>

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

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

实际开发:

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

2、Application类(引导类)

@SpringBootApplication
public class Module01QuickstartApplication {

    public static void main(String[] args) {
        SpringApplication.run(Module01QuickstartApplication.class, args);
    }
}

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

1.4、Spring程序与SpringBoot程序对比

Spring程序与SpringBoot程序对比
类/配置文件 Spring SpringBoot
pom文件中的坐标 手工添加 勾选添加
web 3.0 配置类 手工制作
Spring/Spring MVC 配置类 手工制作
控制器 手工制作 手工制作

注意事项:基于idea开发SpringBoot程序需要确保联网且能够加载到程序框架结构。

1.5、SpringBoot项目打包运行

步骤:

  1. 对SpringBoot项目打包(执行Maven构建指令package);
  2. 执行启动指令:java -jar springboot.jar;

注意:jar支持命令行启动需要依赖maven插件支持,请确认打包时是否具有SpringBoot对应的maven插件:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

1.6、SpringBoot内嵌tomcat

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

SpringBoot内嵌有三款服务器:

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

1.7、SpringBoot依赖管理

<?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 http://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.7.4</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

1、spring-boot-starter-parent

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

2、SpringBoot程序启动方式

@SpringBootApplication
public class Module01QuickstartApplication {

    public static void main(String[] args) {
        SpringApplication.run(Module01QuickstartApplication.class, args);
    }
}

 SpringBoot在创建项目时,采用jar的打包方式。SpringBoot的引导类是项目的入口,运行main()方法就可以启动项目。

3、可以使用maven依赖管理变更起步依赖项

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter.web</artifactId>
        <!-- 在web起步依赖环境中,排除Tomcat起步依赖 -->
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- 添加Jetty起步依赖,版本由SpringBoot的starter控制-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
</dependencies>

Jetty比Tomcat更轻量级,可扩展性更强(相较于Tomcat),谷歌应用引擎(GAE)已经全面切换为Jetty。

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(常用);
    server:
      port: 80
  • 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解析为制表符

2.3、多环境开发配置

多环境启动:application.yaml

spring:
    profiles:
        active: pro
---
spring: # 设置生产环境
    profiles: pro
server: # 生产环境具体参数设定
    port: 80
---
spring: # 设置开发环境
    profiles: dev
server: # 开发环境具体参数设定
    port: 81
---
spring: # 设置测试环境
    profiles: test
server: # 测试环境具体参数设定
    port:82

 带参数启动SpringBoot:java -jar spring.jar --spring.profiles.active=test

2.3.1、Maven与SpringBoot多环境兼容

1、Maven中设置多环境属性:

    <profiles>
        <profile>
            <id>dev_env</id>
            <properties>
                <profile.active>dev</profile.active>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>pro_env</id>
            <properties>
                <profile.active>pro</profile.active>
            </properties>
        </profile>
        <profile>
            <id>test_env</id>
            <properties>
                <profile.active>test</profile.active>
            </properties>
        </profile>
    </profiles>

2、SpringBoot中引用Maven环境:

spring:
    profiles:
        active: ${profile.active}
---
spring: # 设置生产环境
    profiles: pro
server: # 生产环境具体参数设定
    port: 80
---
spring: # 设置开发环境
    profiles: dev
server: # 开发环境具体参数设定
    port: 81
---
spring: # 设置测试环境
    profiles: test
server: # 测试环境具体参数设定
    port:82

3、执行Maven打包指令

Maven指令执行完毕后,生成了对应的包,其中类参与编译,但是配置文件并没有编译,而是复制到包中。

- 复制前:
spring:
    profiles:
        active: ${profile.active}
        
- 复制后
spring:
    profiles:
        active: ${profile.active}

解决思路:对于源码中非Java类的操作要求加载Maven对应的属性,解析${}占位符。如下:

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                    <configuration>
                        <encoding>utf-8</encoding>
                        <useDefaultDelimiters>true</useDefaultDelimiters>
                    </configuration>
                </plugin>

2.3.2、配置文件分类

SpringBoot中4级配置文件:

  • 1级:file : config/application.yml  【最高】
  • 2级:file : application.yml
  • 3级:classpath: config/application.yml
  • 4级:classpath: application.yml  【最低】

作用:

  • 1级与2级留作系统打包后设置通用属性;
  • 3级与4级用于系统开发阶段设置通用属性。

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);
            <!-- SpringBoot 整合 MyBatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <!-- 配置druid数据源 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.16</version>
            </dependency>
  2. 数据库连接相关信息转换成配置。设置数据源参数(在application.yml中):
    spring:
      datasource: # 配置数据源
        type: com.alibaba.druid.pool.DruidDataSource # 配置数据源类型:druid数据源
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://${api-server.host}:3306/mydb?serverTimezone=UTC
        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的SSM整合案例

1、pom.xml:配置起步依赖,必要的资源坐标(druid);

2、application.yaml:设置数据源、端口等;

3、配置类:全部删除;

4、dao:设置@Mapper;

5、测试类

4、基于SpringBoot的SSMP整合案例

案例实现方案分析:

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

起步依赖:

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <artifactId>3.4.1</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

设置Jdbc参数(application.yml):

spring:
  datasource: # 配置数据源
    type: com.alibaba.druid.pool.DruidDataSource # 配置数据源类型:druid数据源
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://${api-server.host}:3306/mydb?serverTimezone=UTC
    username: root
    password: 123456

注意:如果使用Druid数据源,需要导入对应坐标:

        <!-- 配置druid数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

4.1、实体类快速开发

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

常用注解:

  • @Data:为当前实体类在编译期设置对应的get() / set()方法,toString()方法, hashCode()方法,equals()方法等。
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </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对象,所有查询操作封装成方法调用。查询条件支持动态条件封装。

MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合。

/**
     * 条件查询
     */
    @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);
    }

    @Test
    void test() {
        // 查询结果包含模型中部分属性
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.select(User::getId, User::getName, User::getAge);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
        
        // 查询结果包含模型类中未定义的属性
        QueryWrapper<User> qw = new QueryWrapper<User>();
        qw.select("count(*) as nums, gender");
        qw.groupBy("gender");
        List<Map<String, Object>> maps = userDao.selectMaps(qw);
        System.out.println(maps);
    }

    @Test
    void test2() {
        // 用户登录(eq匹配)
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.eq(User::getName, userQuery.getName()).eq(User::getPassword, userQuery.getPassword());
        User loginUser = userDao.selectOne(lqw);
        System.out.println(loginUser);
        
        // 购物设定价格区间、户籍设定年龄区间(le ge匹配 或 between 匹配)
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        // 方案1:设定上限下限
        lqw.le(User::getAge, userQuery.getAge()).ge(User::getAge, userQuery.getAge2());
        // 方案2:设定范围
        lqw.between(User::getAge, userQuery.getAge(), userQuery.getAge2());
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
        
        // 查信息、搜索新闻(非全文检索版:like匹配)
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.likeLeft(User::getTel, userQuery.getTel());
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
        
        // 统计报表
        QueryWapper<User> qw = new QueryWrapper<User>();
        qw.select("gender", "count(*) as nums");
        qw.groupBy("gender");
        List<Map<String, Object>> maps = userDao.selectMaps(qw);
        System.out.println(maps);
    }
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.2.3、字段映射与表名映射

- 问题1:表字段与编码属性设计不同步。解决方案:
    名称:@TableField
    类型:属性注解
    位置:模型类属性定义上方
    作用:设置当前属性对应的数据库表中的字段关系
    范例:
        public class User {
            @TableField(value="pwd") // 对应的数据库字段名为 pwd
            private String password;
        }
    相关属性:
        value(默认):设置数据库表字段名称
        exist:设置属性在数据库表字段中是否存在,默认为true。此属性无法与value合并使用
        select:设置属性是否参与查询,此属性与select()映射配置不冲突
        
- 问题2:编码中添加了数据库中未定义的属性。解决方案:
    public class User {
        private Long id;
        private String name;
        @TableField(value="pwd");
        private String password;
        private Intager age;
        @TableField(exist=false)
        private Intager online;
    }
    
- 问题3:采用默认查询开放了更多的字段查看权限:SELECT id, name, pwd, age, tel, speciality FROM user
    public class User {
        private Long id;
        private String name;
        @TableField(value="pwd", select=false); // 设置该字段不参与查询
        private String password;
        private Intager age;
        @TableField(exist=false)
        private Intager online;
    }
    
- 问题4:表名与编码开发设计不同步。如表名为tbl_user,实体类名为User
    @TableName("tbl_user") // 设置对应的数据库表名
    public class User {
        private Long id;
        private String name;
        @TableField(value="pwd", select=false); // 设置该字段不参与查询
        private String password;
        private Intager age;
        @TableField(exist=false)
        private Intager online;
    }

4.2.4、id生成策略控制

不同的表应用不同的id生成策略:

  • 日志:自增(1,2,3,4,...);
  • 购物订单:特殊规则(FQ12345A415);
  • 外卖单:关联地区日期等信息(10 04 20200314 34 91);
  • 关系表:可省略id;
  • ...
@TableId(type = IdType.类型),类型有如下几类:
    AUTO0):使用数据库id自增策略控制id
    NONE1):不设置id生成策略
    INPUT2):用户手工输入id
    ASSIGN_ID3):雪花算法生成id(可兼容数值型与字符串型)
    ASSIGN_UUID4):以UUID生成算法作为id生成策略

@TableName("tbl_user") // 设置对应的数据库表名
public class User {
    @TableId(type = IdType.AUTO) // 自动递增的id生成策略
    private Long id;
    private String name;
    @TableField(value="pwd", select = false); // 设置该字段不参与查询
    private String password;
    private Intager age;
    @TableField(exist=false)
    private Intager online;
}

4.2.5、多记录操作

- 按照主键删除多条记录
    List<Long> ids = Arrays.asList(new Long[]{2, 3});
    userDao.deleteBatchIds(ids);
- 根据主键查询多条记录
    List<Long> ids = Arrays.asList(new Long[]{2, 3});
    List<User> userList = userDao.selectBatchIds(ids);

4.2.6、逻辑删除

删除操作业务问题:业务数据从数据库中丢弃。

逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中。

步骤:

  1. 数据库表中添加逻辑删除标记字段(如deleted字段);
  2. 实体类中添加对应字段,并设定当前字段为逻辑删除标记字段。
    @TableName("tbl_user") // 设置对应的数据库表名
    public class User {
        @TableId(type = IdType.AUTO) // 自动递增的id生成策略
        private Long id;
        private String name;
        @TableField(value="pwd", select = false); // 设置该字段不参与查询
        private String password;
        private Intager age;
        @TableField(exist=false)
        private Intager online;
        // @TableLogic(value = "0", delval = "1") // 不在配置文件中配置时的逻辑删除字段,标记挡墙记录是否被删除。标记为0为未删除,标记为1为逻辑删除
        @TableLogic() // 不指定value和delval的值,而是在配置文件中统一配置
        private Integer deleted;
    }
  3.  如果不想给每个value和delval定义值,可以在配置文件中统一配置逻辑删除字面值:
    mybatis-plus:
        global-config:
            db-config:
                logic-delete-field: deleted
                logic-not-deleted-value: 0
                logic-delete-value: 1

它实际会执行SQL语句:UPDATE tab_user SET deleted=1 WHERE id=? AND deleted=0

4.2.7、乐观锁

业务并发现象带来的问题:如秒杀业务。

步骤:

  1. 数据库表中添加锁标记字段;
  2. 实体类中添加对应字段,并设定当前字段为逻辑删除标记字段:
  3. @TableName("tbl_user") // 设置对应的数据库表名
    public class User {
        @TableId(type = IdType.AUTO) // 自动递增的id生成策略
        private Long id;
        private String name;
        @TableField(value="pwd", select = false); // 设置该字段不参与查询
        private String password;
        private Intager age;
        @TableField(exist=false)
        private Intager online;
        @TableLogic // 不指定value和delval的值,而是在配置文件中统一配置
        private Integer deleted;
        @Version
        private Integer version;
    }
  4. 需要配置乐观锁拦截器实现锁机制对应的动态SQL语句拼装:
    @Configuration
    public class MpConfig {
        @Bean
        public MybatisPlusInterceptor mpInterceptor() {
            // 1、定义Mp拦截器
            MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
            // 2、添加分页拦截器
            mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
            // 3、添加乐观锁拦截器
            mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return mpInterceptor;
        }
    }
  5. 使用乐观锁机制在修改前必须先获取到对应数据的version方可正常进行:
    @Test
    void testUpdate() {
        // 先查询数据,获取到version数据
        User user = userDao.selectById(1L);
        // 执行数据修改操作
        user.setName("Tom and Jerry");
        userDao.updateById(user);
    }

4.2.8、代码生成器

模板:MyBatisPlus提供。

数据库相关配置:读取数据库获取信息。

开发自定义配置:手工配置。

先导入所需坐标:

pom.xml:

    <!-- 代码生成器 -->
    <depedency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>2.3</version>
    </depedency>
    <!-- velocity模板引擎 -->
    <dependency>
        <groupId>org.apache.velocity</groupId>
        <artifactId>velocity-engine-core</artifactId>
        <version>2.3</version>
    </dependency>
public class Generator {
    public static void main(String[] args) {
        // 1、获取代码生成器的对象
        AutoGenerator autoGenerator = new AutoGenerator();
        
        // 2、设置数据库相关配置
        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        sutoGenerator.setDataSource(dataSource);
        
        // 3、设置全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir") + "/project/src/main/java"); // 设置输出代码的位置
        globalConfig.setOpen(false); // 设置生成完毕后是否打开生成代码所在的目录
        globalConfig.setAuthor("xxx"); // 设置作者
        globalConfig.setFileOverride(true); // 设置是否覆盖原始生成的文件
        globalConfig.setMapperName("%sDao"); // 设置数据层接口名,%s为占位符,指代模块名称
        globalConfig.setIdType(IdType.ASSIGN_ID); // 设置Id生成策略
        autoGenerator.setGlobalConfig(globalConfig);
        
        // 4、设置包名相关配置
        PackageConfig packageInfo = new PackageConfig();
        packageInfo.setParent("com.itheima"); // 设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
        packageInfo.setEntity("domain"); // 设置实体类包名
        packageInfo.setMapper("dao"); // 设置数据层包名
        autoGenerator.setPackageInfo(packageInfo);
        
        // 5、策略设置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tbl_user"); // 设置当前参与生成的表名,参数为可变参数
        strategyConfig.setTablePrefix("tbl_"); // 设置数据库表的前缀名称,模块名 = 数据库名称 - 前缀名。例如:tbl_user => User
        strategyConfig.setRestControllerStyle(true); // 设置是否启用Rest风格
        strategyConfig.setVersionFieldName("version"); // 设置乐观锁字段名
        strategyConfig.setLogicDeleteFieldName("deleted"); // 设置逻辑删除字段名
        strategyConfig.setEntityLombokModel(true); // 设置是否启用lombok
        autoGenerator.setStrategy(strategyConfig);
        
        autoGenerator.execute();
        
    }
}

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、表现层数据一致性处理

 

posted on   啊噢1231  阅读(87)  评论(0编辑  收藏  举报

导航

统计信息

回到顶部
点击右上角即可分享
微信分享提示

1、SpringBoot简介
1.1、原生开发SpringMVC程序过程
1.2、SpringBoot快速入门
1.2.1、创建SpringBoot项目
1.2.2、开发控制器类
1.2.3、运行自动生成的Application类(引导类)
1.3、最简SpringBoot程序所包含的基础文件
1.4、Spring程序与SpringBoot程序对比
1.5、SpringBoot项目打包运行
1.6、SpringBoot内嵌tomcat
1.7、SpringBoot依赖管理
2、基础配置
2.1、属性配置
2.1.1、修改配置
2.2、YMAL配置
2.2.1、yaml语法规则
2.2.2、数据读取
2.2.3、yml文件中的变量引用
2.3、多环境开发配置
2.3.1、Maven与SpringBoot多环境兼容
2.3.2、配置文件分类
3、整合第三方技术
3.1、整合JUnit
3.2、整合MyBatis
3.3、整合MyBatis-Plus
3.4、整合Druid
4、基于SpringBoot的SSM整合案例
4、基于SpringBoot的SSMP整合案例
4.1、实体类快速开发
4.2、数据层开发
4.2.1、分页
4.2.2、条件查询
4.2.3、字段映射与表名映射
4.2.4、id生成策略控制
4.2.5、多记录操作
4.2.6、逻辑删除
4.2.7、乐观锁
4.2.8、代码生成器
4.3、业务层开发
4.3.1、业务层开发——快速开发
4.4、表现层开发
4.4.1、表现层数据一致性处理