六、Java框架之SpringBoot

news2024/11/18 9:23:38

黑马课程

文章目录

  • 1. SpringBoot入门
    • 1.1 SpringBoot入门案例
      • 步骤1:创建SpringBoot项目
      • 高版本springboot常见错误
      • 步骤2:创建BookController
      • 步骤3:启动服务器并运行程序
      • pom.xml示例
    • 1.2 官网创建SpringBoot
    • 1.3 SpringBoot工程快速启动
      • 问题导入
      • 打包
      • 启动
    • 1.4 SpringBoot概述
      • 起步依赖
        • spring-boot-starter-parent
        • spring-boot-starter-web
        • spring-boot-starter-test
      • 引导类和自动配置
      • 切换web服务器(辅助功能)
  • 2. SpringBoot配置文件
    • 2.1 配置文件格式
    • 2.2 yaml格式
    • 2.3 yaml配置文件数据读取
      • 方法一:@Value
      • 方法二:Environment
      • 方法三:实体类(常用)
  • 3. 多环境配置
    • 3.1 yml配置
    • 3.2 properties配置
    • 3.3 命令行配置
    • 3.4 配置方式的优先级
    • 3.5 多环境开发兼容问题
    • 3.6 配置文件分类
  • 4. SpringBoot整合
    • 4.1 SpringBoot整合Junit
      • Spring整合Junit
      • SpringBoot整合Junit
    • 4.2 SpringBoot整合MyBatis
      • Spring整合MyBatis
      • SpringBoot整合MyBatis
        • 步骤1:创建项目和导入依赖
        • 步骤2:准备数据库表并创建实体类
        • 步骤3:编写dao文件
        • 步骤4:编写配置文件application.yml
        • 步骤5:测试
      • 报错解决:serverTimezone=UTC
  • 5. 案例:SpringBoot整合SSM
    • 5.1 搭建项目
      • 创建springboot项目
      • application.yml
    • 5.2 功能模块
      • domain
      • dao
      • service
      • exception
      • controller
        • Code
        • Result
        • ProjectExceptionAdvice
        • BookController
    • 5.3 单元测试
    • 5.4 静态资源

1. SpringBoot入门

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

回顾SpringMVC项目,和SpringBoot进行比较

1.1 SpringBoot入门案例

步骤1:创建SpringBoot项目

创建之前先设置好自己的maven本地仓库

在这里插入图片描述

注意这里Spring Boot的版本,3版本容易出现冲突,如果选择2版本暂时未发现报错

在这里插入图片描述

创建好的结构如下
在这里插入图片描述

  • src, test, pom.xml这三个是必须有的

高版本springboot常见错误

之前选择了3.0.2版本的springboot,由于JDK版本较低是 JDK8 版本,所以会出现配置不统一而报错
即创建时选择了JDK8,而 SpringBoot3 最低要求是 JDK17
从而导致项目配置是JDK8,但Spring环境是JDK17,出现冲突

这种情况的解决思路:
1.升级JDK
2.对Spring降级(下面的方法,降到JDK8,实际上就和创建时选择版本2的SpringBoot一致了,只是用于修改已有项目)

  • java: JDK isn't specified for module 'springboot'

    原因:.idea中存放了一些项目的配置信息,如果删除将报错此错误;
    方案:重启时会自动创建新的.idea,报错时重新打开一次项目即可

  • java: 警告: 源发行版 17 需要目标发行版 17
    则检查以下三个地方的JDK版本是否正确(如这里是1.8版本)

    • Project Structure – Project – SDK (选择 1.8)

    • Project Structure – Modules – Language Level (选择 8)

    • Settings – Build,Execution,Deployment – Compiler – Project bytecode version (选择 8)
      以及同位置的Target bytecode version (输入8)

      ![在这里插入图片描述](https://img-blog.csdnimg.cn/fff5c04f80d4402ab0e246c527826c35.png =500xx`)

  • 类文件具有错误的版本 61.0, 应为 52.0

    原因:之前创建时选择了3.0.2版本的springboot,版本过高
    解决:修改pom.xml里面的相关配置,如下

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    

步骤2:创建BookController

package com.example.controller;

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

步骤3:启动服务器并运行程序

直接运行创建项目时自动生成的SpringbootApplication程序,即可启动tomcat服务器
访问:http://localhost:8080/books/1,成功看到结果

  • 不用再书写之前一大堆的配置类,springboot自动配置
  • 不用手动导入依赖,Spring相关依赖已经在pom.xml自动创建
    spring-boot-starter-webspring-boot-starter-test分别涵盖了spring web相关依赖和test相关依赖

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>
        <!-- 和之前的maven继承学习的,继承父工程的依赖 -->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <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>

1.2 官网创建SpringBoot

在1.1节,通过IDEA创建了SpringBoot项目,如果不使用IDEA,可以通过官网教程创建

进入SpringBoot官网:https://spring.io/projects/spring-boot
在这里插入图片描述

对项目进行配置

在这里插入图片描述

会下载一个springboot项目的zip文件

1.3 SpringBoot工程快速启动

问题导入

  • 问题导入

    前端开发人员需要测试前端程序就需要后端开启服务器,这需要前端人员在自己电脑上安装Tomcat和Idea

  • 解决方法

    后端将 SpringBoot 工程打成 jar 包,该 jar包运行不依赖于Tomcat和 Idea 这些工具,只需要连接到相同的 Mysql 数据库即可

打包

构建 SpringBoot 工程时自动在 pom.xml 中配置了如下插件

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

此时只需要package命令即可在target目录下生成对应的jar包

在这里插入图片描述

启动

进入jar包所在位置,在cmd命令行中输入

java -jar springboot-0.0.1-SNAPSHOT.jar

在这里插入图片描述

可以看到和在IDEA一样的执行结果

之前的maven项目也可以打成jar包,但不能像这样通过java -jar命令直接启动
依赖于 spring-boot-maven-plugin 插件

1.4 SpringBoot概述

SpringBoot程序的优点针对的是Spring的缺点

  • 自动配置。这个是用来解决Spring程序配置繁琐的问题
  • 起步依赖。这个是用来解决Spring程序依赖设置繁琐的问题
  • 辅助功能(内置服务器,…)。在启动SpringBoot程序时既没有使用本地的tomca也没有使用tomcat插件,而是使用SpringBoot内置的服务器

起步依赖

  • 在pom.xml中配置,相当于之前Spring里面的各种依赖导入

使用 Spring Initializr 方式创建的 Maven 工程的的 pom.xml 配置文件中自动生成了很多包含 starter 的依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.8</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<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>

spring-boot-starter-parent

查看该jar包,发现它又继承自spring-boot-dependencies

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.7.8</version>
</parent>

spring-boot-starter-parent主要是配置了插件管理<pluginManagement>
它的父工程spring-boot-dependencies才是配置了各种依赖及其版本

spring-boot-dependencies里面主要有<properties><dependencyManagement><build> 3个配置

  • properties

    定义了各个技术软件依赖的版本,避免了考虑版本的兼容问题
    这里的版本是和SpringBoot的版本相对应的,比如这里的SpringBoot对应的是2.7.8版本,那么几个之前用过的依赖版本如下

    <servlet-api.version>4.0.1</servlet-api.version>
    <mysql.version>8.0.32</mysql.version>
    
  • dependencyManagement

    相当于对所依赖jar包进行版本管理的管理器,它并没有导入依赖,只是锁定了版本
    子工程如果需要某个依赖,只需要引入依赖的 groupidartifactId 不需要定义 version,例如

    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>${mysql.version}</version>
        <exclusions>
            <exclusion>
                <groupId>com.google.protobuf</groupId>
                <artifactId>protobuf-java</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    

    里面还有一些版本号直接写明的依赖,表示不建议更改版本,如

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.7.8</version>
    </dependency>
    
  • build

    里面主要是<buildManagement>对各种插件进行了版本锁定

!如果由于版本原因报错:com.mysql:mysql-connector-j:jar:unknown was not found 等,还是可以自己指定版本号来解决

spring-boot-starter-web

包含了如下的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.7.8</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-json</artifactId>
        <version>2.7.8</version>
        <scope>compile</scope>
    </dependency>
    <!-- 这个依赖使得项目内置了一个tomcat,这也是之前java -jar能够运行的原因 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <version>2.7.8</version>
        <scope>compile</scope>
    </dependency>
    <!-- SpringMVC相关jar包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.3.25</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.25</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

spring-boot-starter-test

里面主要是<dependencies>标签,定义和测试相关的jar包,例如之前用过的spring-test就在这里引入

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.25</version>
    <scope>compile</scope>
</dependency>

引导类和自动配置

引导类

SpringBoot项目在创建时,会自动创建一个SpringbootApplication的引导类,如下

package com.example;

@SpringBootApplication
public class SpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}
  • SpringBoot在创建项目时,采用jar的打包方式
  • SpringBoot的引导类是项目的入口,运行main方法就可以启动项目
  • pom.xml中配置了 spring-boot-starter-web 依赖,该依赖中又包含tomcat依赖,因此运行引导类可以启动工程

自动配置

@SpringBootApplication注解:会将引导类所在的包及其子包都扫描一遍

切换web服务器(辅助功能)

之前用的都是tomcat服务器,如果需要换成jetty服务器(nexus私服就是用的jetty服务器),可以按如下设置

步骤1:排除掉tomcat服务器

在项目的pom.xml文件中找到spring-boot-starter-web,并设置排除掉tomcat

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

此时再运行引导类,发现启动后很快停止,因为未能启动tomcat服务器

步骤2:引入jetty服务器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

此时再启动,就可以看到jetty服务器被启动了

在这里插入图片描述

jetty比tomcat更轻量级,扩展性更好,谷歌应用引擎(GAE)已经全面切换为jetty
大型应用仍使用tomcat

2. SpringBoot配置文件

2.1 配置文件格式

springboot项目创建后,在resources下会创建一个空的application.properties配置文件,修改端口号等都在此文件中配置
也可以将application.properties换成application.yml、application.yaml

  • application.properties

    server.port=80
    
  • application.yml

    必须有空格

    server:
    	port: 81
    
  • application.yaml

    必须有空格

    server:
    	port: 82
    

注意:SpringBoot 程序的配置文件名必须是 application ,只是后缀名不同而已

  • 一般写yml配置文件
  • 三个配置文件的先后优先级是:properties、yml、yaml

如果配置文件有问题,可以在如下地方进行SpringBoot的配置文件设置

在这里插入图片描述

2.2 yaml格式

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

优点

  • 容易阅读

    yaml 类型的配置文件比 xml 类型的配置文件更容易阅读,结构更加清晰

  • 容易与脚本语言交互

  • 以数据为核心,重数据轻格式

    yaml 更注重数据,而 xml 更注重格式

YAML 文件扩展名:

  • .yml (主流)
  • .yaml

语法规则

  • 大小写敏感

  • 属性层级关系使用多行描述,每行结尾使用冒号结束

  • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)

  • 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)

  • # 表示注释

  • 数组数据在数据书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔,例如

    subject:
        - Java
        - 前端
        - 大数据
    

2.3 yaml配置文件数据读取

编写application.yml文件

lesson: SpringBoot

server:
  port: 80

enterprise:
  name: company
  age: 16
  tel: 123456789
  subject:
    - java
    - c
    - python

方法一:@Value

在BookController中获取application.yml方式

@Value("${lesson}")
private String lesson;
@Value("${server.port}")
private Integer port;
@Value("${enterprise.subject[0]}")
private String subject00;

方法二:Environment

package com.example.controller;

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private Environment environment;

    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id){
        System.out.println(environment.getProperty("enterprise.age"));
        return "hello, spring boot";
    }
}

在框架中常使用,一般开发很少用

方法三:实体类(常用)

package com.example.domain;

@Component
@ConfigurationProperties(prefix = "enterprise")
public class Enterprise {
    private String name;
    private int age;
    private String tel;
    private String[] subject;
	//省略getter, setter, toString
}
package com.example.controller;

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private Enterprise enterprise;

    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id){
        System.out.println(enterprise);
        return "hello, spring boot";
    }
}

3. 多环境配置

回顾:之前在学习Maven时,多环境是通过在父工程中配置 <profiles>实现的

3.1 yml配置

application.yml 中使用 --- 来分割不同的配置,设置多环境

# 设置启动的环境
spring:
  profiles:
    active: dev

---
#开发
spring:
  profiles: dev
server:
  port: 80

---
#生产
spring:
  profiles: pro
server:
  port: 81

---
#测试
spring:
  profiles: test
server:
  port: 82

这种写法会提示过时,新的写法为

# 设置启动的环境
spring:
  profiles:
    active: dev

---
#开发
spring:
  config:
    activate:
      on-profile: dev
server:
  port: 80

可以自己选择哪种写法

3.2 properties配置

创建application.properties,如下

#设置启动的环境
spring.profiles.active=dev

创建application-dev.properties,如下

server.port=8080

同样还需要创建 application-pro.properties,application-test.properties,即可完成多环境配置

3.3 命令行配置

步骤1:打包

  • package前先clean一下

  • 如果有中文,打包可能报错,修改项目编码
    在这里插入图片描述

  • 打包方式:maven项目里面的Lifecycle

步骤2:指定环境运行项目

java -jar springboot-0.0.1-SNAPSHOT.jar --server.port=88 --spring.profiles.active=test

在jar包所在目录下(target下),打开cmd,输入如上命令
如果在命令行指定了port,它的优先级高于配置文件中的设置

3.4 配置方式的优先级

见springboot官网

https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config

3.5 多环境开发兼容问题

这部分很少用,了解即可

maven中可以配置多环境(pom.xml),springboot也可以配置多环境(application.yml),如果都配置了,谁的优先级更高?

  • pom.xml的优先级高于application.yml

现在有这样一个需求

  • 要求springboot和maven的环境统一

  • 希望springboot能读取maven里的多环境设置,使得springboot里面的环境设置跟随maven

  • 实现:在pom.xml指定默认环境,但不指定端口号;这个默认环境要被maven和springboot通用
    application.yml会设置具体的、不同环境下的端口号,但默认环境将跟随pom.xml里面的设置

步骤1:Maven中设置多环境属性(pom.xml)

<profiles>
    <!-- 开发环境 -->
    <profile>
        <id>dev</id>
        <properties>
            <profile.active>dev</profile.active>
        </properties>
        <!-- 默认环境-->
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <!-- 生产环境 -->
    <profile>
        <id>pro</id>
        <properties>
            <profile.pro>pro</profile.pro>
        </properties>
    </profile>
    <!-- 测试环境 -->
    <profile>
        <id>test</id>
        <properties>
            <profile.pro>test</profile.pro>
        </properties>
    </profile>
</profiles>

步骤2:在springboot中也设置多环境(application.yml)

# 设置启动的环境
spring:
  profiles:
    active: ${profile.active}
---
#开发
spring:
  profiles: dev
server:
  port: 80
---
#生产
spring:
  profiles: pro
server:
  port: 81
---
#测试
spring:
  profiles: test
server:
  port: 82

步骤3:开启插件(pom.xml)

允许占位符解析

<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
        <encoding>utf-8</encoding>
        <useDefaultDelimiters>true</useDefaultDelimiters>
    </configuration>
</plugin>

步骤4:打包
此时打包之后,application.yml里面的active: ${profiles.active}就变为active: dev
路径:springboot\target\springboot-0.0.1-SNAPSHOT.jar\BOOT-INF\classes\application.yml

3.6 配置文件分类

  • jar包内部的配置文件

    resouces/application.ymlresources/config/application.yml

    • 后者的优先级高于前者

    • resouces/application.yml 相当于不稳定版本,时常向里面修改
      resources/config/application.yml 相当于发布版本

  • jar包外部的配置文件

    问题:临时配置如果太多,在命令行测试jar包时,就不得不加上一堆属性

    • 解决方法:在路径下添加临时配置文件,它的优先级项目里的配置文件

    • 且同样的,config里面的配置文件优先级高于外面的配置文件

      在这里插入图片描述

    • 运行程序,发现在target/config/目录下的application.yml具有最高优先级

      java -jar springboot-0.0.1-SNAPSHOT.jar
      

      如下载各种软件,如tomcat,里面会携带各种类似的配置文件

4. SpringBoot整合

4.1 SpringBoot整合Junit

Spring整合Junit

@RunWith(SpringJUnit4ClassRunner.class)//设置运行器
@ContextConfiguration(classes = SpringConfig.class)//加载环境
public class UserServiceTest {
    @Autowired
    private BookService bookService;//注入测试对象
    
    @Test
    public void testSave(){//测试功能
        bookService.save();
    }
}

SpringBoot整合Junit

生成SpringBoot项目时,在test里面会自动生成一个SpringbootApplicationTests类,只需要在contextLoads里面调用方法,即可测试

package com.example;

@SpringBootTest
class SpringbootApplicationTests {
    @Autowired
    private BookService bookService;
    @Test
    void contextLoads() {
        bookService.save();
    }
}
  • 在引导类com.example.SpringbootApplicationTests上有注解@SpringBootTest
    它会自动扫描引导类所在的包及子包org.example,因此被@Service标注的BookServiceImpl会成为Bean,实现自动注入

  • 测试类会自动加载引导类,即初始化Spring的环境

    • 测试类必须在引导类的包或子包中,这里是com.example

      在这里插入图片描述

  • 如果测试类位置不对,可以通过如下命令为其指定启动类的位置

    @SpringBootTest(classes = SpringbootApplication.class)
    

4.2 SpringBoot整合MyBatis

Spring整合MyBatis

  • 编写配置类
    • SpringConfig:配置Spring扫描bean,引入JdbcConfig,MybatisConfig
    • JdbcConfig:设置数据库连接参数和数据源
    • MybatisConfig:获取SqlSessionFactory对象,定义映射配置(扫描dao包)

SpringBoot整合MyBatis

步骤1:创建项目和导入依赖

在创建选择依赖时,勾选以下三项:Web/Spring WebSQL/MyBatis FrameworkMySQL Driver

也可以为已经现有项目直接添加依赖来完成整合
添加的依赖版本仍需要和原项目的springboot版本相吻合!

新增了依赖

<!-- 整合mybatis相关 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>
  • 注意创建项目不会自动添加 druid 依赖,需要手动添加一下

这里要根据springboot版本,有的版本用的是如下mysql依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

步骤2:准备数据库表并创建实体类

package com.example.domain;

public class Book {
    private Integer id;
    private String name;
    private String type;
    private String description;
    //省略getter, setter, toString
}

步骤3:编写dao文件

package com.example.dao;

@Mapper
public interface BookDao {
    @Select("select * from tbl_book where id = #{id}")
    public Book getById(Integer id);
}
  • 注意这里要添加@Mapper注解,而不是@Repository

步骤4:编写配置文件application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?useSSL=false
    username: root
    password: 123456
    #下面配置数据源,使用druid
    type: com.alibaba.druid.pool.DruidDataSource
  • 如果SpringBoot版本是2.7.8,可能提示你的jdbc驱动过时了,让更换为com.mysql.cj.jdbc.Driver,改不改都行

步骤5:测试

package com.example;

@SpringBootTest
class SpringbootApplicationTests {
    @Autowired
    private BookDao bookDao;
    @Test
    void contextLoads() {
        Book book = bookDao.getById(1);
        System.out.println(book);
    }
}

运行即可获得数据库内容

  • springboot节省了大量的配置编写

报错解决:serverTimezone=UTC

SpringBoot版本低于2.4.3(不含),Mysql驱动版本大于8.0时,需要在url连接串中配置时区
jdbc:mysql://localhost:3306/ssm_db?useSSL=false&serverTimezone=UTC
或在MySQL数据库端配置时区解决此问题

在pom.xml将springboot的version改为2.4.2,即可看到这个相关报错
在这里插入图片描述

5. 案例:SpringBoot整合SSM

需求:将之前的ssm项目springmvc-ssm转为springboot项目

5.1 搭建项目

创建springboot项目

<dependencies>
    <!-- mybatis相关 -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
    <!-- web相关 -->
    <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>

application.yml

#TODO 配置数据源相关信息

server:
  port: 80
  
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?useSSL=false&serverTimeZone=UTC
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource

5.2 功能模块

domain

package com.example.domain;

public class Book {
    private Integer id;
    private String name;
    private String type;
    private String description;
    //省略了setter, getter, toString
}

dao

package com.example.dao;

//TODO 添加@Mapper
@Mapper
public interface BookDao {
    @Insert("insert into tbl_book values (null, #{type}, #{name}, #{description})")
    public int save(Book book);
    @Delete("delete from tbl_book where id = #{id}")
    public int delete(Integer id);
    @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
    public int update(Book book);
    @Select("select * from tbl_book where id = #{id}")
    public Book getById(Integer id);
    @Select("select * from tbl_book")
    public List<Book> getAll();
}

service

package com.example.service;

@Transactional
public interface BookService {
    public boolean save(Book book);
    public boolean delete(Integer id);
    public boolean update(Book book);
    public Book getById(Integer id);
    public List<Book> getAll();
}
package com.example.service.impl;

@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
    @Override
    public boolean save(Book book) {
        System.out.println(book);
        return bookDao.save(book) > 0;
    }
    @Override
    public boolean delete(Integer id) {
        return bookDao.delete(id) > 0;
    }
    @Override
    public boolean update(Book book) {
        return bookDao.update(book) > 0;
    }
    @Override
    public Book getById(Integer id) {
        if(id == 1){
            //模拟异常,抛出自定义的业务异常类
            throw new BussinessException(Code.BUSINESS_ERROR, "查询失败,请重试!");
        }
        return bookDao.getById(id);
    }
    @Override
    public List<Book> getAll() {
        return bookDao.getAll();
    }
}

exception

统一异常处理

BussinessException

package com.example.exception;

public class BussinessException extends RuntimeException{
    private Integer code;
    //构造器
    public BussinessException(Integer code, String message){
        super(message);
        this.code = code;
    }
    public BussinessException(Integer code, String message, Throwable cause){
        super(message, cause);
        this.code = code;
    }
    //getter, setter
}

SystemException

package com.example.exception;

public class SystemException extends RuntimeException{
    private Integer code;
    //构造器
    public SystemException(Integer code, String message){
        super(message);
        this.code = code;
    }
    public SystemException(Integer code, String message, Throwable cause){
        super(message, cause);
        this.code = code;
    }
    //getter, setter
}

controller

Code

package com.example.controller;

public class Code {
    //操作成功
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;
    //操作失败
    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;
    //定义异常类型
    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer BUSINESS_ERROR = 50002;
    public static final Integer SYSTEM_UNKNOWN_ERR = 59999;
}

Result

统一前后端发送数据格式

package com.example.controller;

public class Result {
    private Integer code;
    private Object data;
    private String msg;
    //构造器
    public Result(){}
    public Result(Integer code, Object data){
        this.code = code;
        this.data = data;
    }
    public Result(Integer code, Object data, String msg){
        this.code = code;
        this.data = data;
        this.msg = msg;
    }
    //getter, setter, toString
}

ProjectExceptionAdvice

异常处理器

package com.example.controller;

@RestControllerAdvice
public class ProjectExceptionAdvice {
    //1. 拦截系统异常
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex){
        //记录日志
        //发送消息给运维
        //发送消息给开发人员
        return new Result(ex.getCode(), null, ex.getMessage());
    }
    //2. 拦截业务异常
    @ExceptionHandler(BussinessException.class)
    public Result doBussinessException(SystemException ex){
        return new Result(ex.getCode(), null, ex.getMessage());
    }
    //3. 拦截其他异常
    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex){
        //记录日志
        //发送消息给运维
        //发送消息给开发人员
        return new Result(Code.SYSTEM_UNKNOWN_ERR, null, "系统繁忙,请稍后重试");
    }
}

BookController

package com.example.controller;

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private BookService bookService;
    @PostMapping
    public Result save(@RequestBody Book book){
        boolean flag = bookService.save(book);
        return new Result(flag?Code.SAVE_OK:Code.SAVE_ERR, flag);
    }
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id){
        boolean flag = bookService.delete(id);
        return new Result(flag?Code.DELETE_OK:Code.DELETE_ERR, flag);
    }
    @PutMapping
    public Result update(@RequestBody Book book){
        boolean flag = bookService.update(book);
        return new Result(flag?Code.UPDATE_OK:Code.UPDATE_ERR, flag);
    }
    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id){
        Book book = bookService.getById(id);
        Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
        String msg = book != null ? "查询成功" : "数据查询失败,请重试!";
        return new Result(code, book, msg);
    }
    @GetMapping
    public Result getAll(){
        List<Book> bookList = bookService.getAll();
        Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
        String msg = bookList != null ? "查询成功" : "数据查询失败,请重试!";
        return new Result(code, bookList, msg);
    }
}

5.3 单元测试

package com.example;

@SpringBootTest
class SpringbootApplicationTests {
    @Autowired
    private BookService bookService;
    @Test
    public void testGetById(){
        Book book = bookService.getById(2);
        System.out.println(book);
    }
    @Test
    public void testGetAll(){
        List<Book> bookList = bookService.getAll();
        System.out.println(bookList);
    }
}

可以使用postman进行测试

5.4 静态资源

将之前的做好的前端项目拷贝到 resource/static 目录下

在这里插入图片描述

启动引导类,浏览器访问页面:http://localhost/pages/books.html
在前端可以设置一个index.html页面如下

<script>
  document.location.href = "pages/books.html"
</script>

然后访问:http://localhost,即可达到主页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/338651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全实验室6.解密关

6.解密关 1.以管理员身份登录系统 url&#xff1a;http://lab1.xseclab.com/password1_dc178aa12e73cfc184676a4100e07dac/index.php 进入网站点击忘记密码的链接&#xff0c;进入到重置密码的模块 输入aaa&#xff0c;点击抓包&#xff0c;发送到重放模块go 查看返回的链接…

VScode 结合clangd 构建linux源代码阅读环境

1、背景介绍上一篇文章&#xff1a;VScode 结合Global构建linux源代码阅读环境 &#xff0c;介绍了在VS Code工具中通过remote-ssh远程登陆到Linux远程服务器&#xff0c;使用Global构建linux源代码阅读环境&#xff0c;对linux kernel代码进行解析&#xff0c;实现全局搜索、自…

Vue2创建移动端项目

一、Vscode Vscode 下载安装以及常用的插件 1、Vscode 下载 下载地址&#xff1a;Vscode 中文语言插件 搜索 chinese 主题 Atom 主题 文件图标主题 搜索 icon 源代码管理插件GitLens 搜索 GitLens Live Server _本地服务器 搜索 Live Server Prettier - Code formatt…

405 Method Not Allowed,CORS跨域,来也自动化OCR接口报错,Nginx处理OPTIONS请求

在使用来也的OCR接口时&#xff0c;请求报错了&#xff0c;提示CORS跨域。POST请求&#xff0c;请求url&#xff1a;http://mage.uibot.com.cn/v1/mage/ocr/bills&#xff0c;官方文档&#xff1a;请求与响应&#xff1a;预检请求OPTIONS正式请求错误信息看控制台和网络栏位内容…

【沁恒WCH CH32V307V-R1开发板输出DAC实验】

【沁恒WCH CH32V307V-R1开发板输出DAC实验】1. 前言2. 软件配置2.1 安装MounRiver Studio3. DAC项目测试3.1 打开DAC工程3.2 编译项目4. 下载验证4.1 接线4.2 演示效果5. 小结1. 前言 数字/模拟转换模块&#xff08;DAC&#xff09;&#xff0c;包含 2 个可配置 8/12 位数字输入…

自己动手做一个mini-chatgpt

开场最近chatgpt已经火爆了&#xff0c;几乎是家喻户晓老少皆知啊&#xff0c;公测推出60天后就已经是UV人数过亿&#xff0c;日访问量号称也是过亿。投资chatgpt研发团队的微软也是2个月内迅速推出自己的chatgpt的bing搜索&#xff0c;股票下载量都是暴增啊。前面文章已经介绍…

计算机网络自定向下 -- 浅谈可靠性之rdt协议

可靠性数据传输原理 可靠指数据在传输过程中不错&#xff0c;不丢&#xff0c;不乱 运输层要为应用层提供一种服务&#xff1a;数据可以通过一条可靠的信道进行传输&#xff0c;在该信道中传输的数据不会受到损坏或者丢失, 实现这种服务的是可靠数据传输协议。 要实现这种服…

python的opencv操作记录11——阈值分割

文章目录传统图像处理分割阈值分割一个应用场景opencv库中的阈值分割固定阈值THRESH_OTSU 大津法阈值自适应阈值传统图像处理分割 现在提到图像分割&#xff0c;很多人会直接想到当前火爆的深度学习的各种分割网络&#xff0c;比如实例分割&#xff0c;语义分割等。其实在传统…

Java爬虫Selenium+Java+ChromeDriver

一、爬虫工具 selenium 是一个模拟浏览器操作的工具&#xff0c;背后有google 维护源代码&#xff0c;支持全部主流浏览器&#xff0c;支持主流的编程语言&#xff0c;包括:java,Python,C#,PHP,Ruby,等&#xff0c;在本项目上使用的Java语言。 官网&#xff1a;https://www.sel…

【Vue】参数传递:如何同时传递 DTO 和 file 文件

日常开发时&#xff0c;如果遇到较为复杂的 DTO 对象的参数传递时&#xff0c;通常前端使用的请求头为&#xff1a;application/json&#xff08;JSON 格式的数据&#xff09;&#xff1b;而后端可以使用 RequestBody 接收一个 DTO 对象。但当需要在一个界面上同时传递 DTO 和附…

Java集合中的Map

MapMap接口键 值 对存储键不能重复&#xff0c;值可以重复Map三个实现类的存储结构HashMap&#xff1a;Hash表链表红黑树结构 线程不安全TreeMap&#xff1a; 底层红黑树实现HashTable&#xff1a;hash表链表红黑树 线程安全HashMapHashMap常用方法HashMap<String,String>…

[测开篇]设计测试用例的方法如何正确描述Bug

​ 文章目录为什么测试人员要写测试用例&#xff1f;怎样设计测试用例&#xff1f;&#xff08;总的方面&#xff09;1.基于需求设计测试用例&#xff08;总的方面&#xff09; 2.页面&#xff08;总的方面&#xff09; 3.非功能性测试&#xff08;具体方面&#xff09; 4.1 等…

「Python|环境安装|Windows」如何在Windows上安装Python环境?

本文主要介绍如何在Windows上安装Python&#xff0c;帮助初学者或者非程序员伙伴快速搭建可以运行python代码的环境。 文章目录安装python做一点小配置验证python如何安装指定版本的python编程语言的环境搭建一直是学习编程的第一道门槛。 对于如何在Linux系统上安装指定版本的…

谷歌蜘蛛池怎么搭建?Google蜘蛛池可以帮助谷歌排名吗?

本文主要分享关于谷歌蜘蛛池的搭建疑问&#xff0c;以及Google对谷歌排名的影响到底有多大。 本文由光算创作&#xff0c;有可能会被剽窃和修改&#xff0c;我们佛系对待这种行为吧。 谷歌蜘蛛池怎么搭建&#xff1f; 答案是&#xff1a;需要一个内链外链体系复杂的站群系统…

154、【动态规划】leetcode ——494. 目标和:回溯法+动态规划(C++版本)

题目描述 原题链接&#xff1a;494. 目标和 解题思路 &#xff08;1&#xff09;回溯法 本题的特点是nums中每个元素只能使用一次&#xff0c;分别试探加上nums[index]和减去nums[index]&#xff0c;然后递归的遍历下一个元素index 1。 class Solution { public:int res …

java中flatMap用法

java中map是把集合每个元素重新映射&#xff0c;元素个数不变&#xff0c;但是元素值发生了变化。而flatMap从字面上来说是压平这个映射&#xff0c;实际作用就是将每个元素进行一个一对多的拆分&#xff0c;细分成更小的单元&#xff0c;返回一个新的Stream流&#xff0c;新的…

1629_MIT_6.828_xv6_chapter1操作系统的组织

全部学习汇总&#xff1a;GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 这一次整理一下操作系统组织相关的知识&#xff0c;主要还是xv6教学操作系统相关的知识。当然&#xff0c;很多知识在这类技术领域是通用的。 1. 操作系统的主要功能…

SAP ABAP Odata

GetEntity和GetEntitys GetEntitys 创建Odata Project 导入结构 选择需要的字段 设定Key 勾选字段的creatable、updatable、sortable、nullable、filterable属性值。 再依上述步骤创建ZPOITEM结构和实体集 3. 创建ZPOHEADER和ZPOITEM的Association 两个实体集的关联字段&…

RocketMQ-消息消费模式 顺序消费

RocketMQ-消息消费模式 顺序消费RocketMQ-消息消费模式集群模式集群模式的演示(本身就默认)Rocketmq存储队列广播模式顺序消费如何改实现顺序消费RocketMQ-消息消费模式 集群模式 在消费模式为集群的情况下,如果机器是集群的,消息只会给集群中的其中一台机器消费到 集群模…

【数据结构】双向链表的模拟实现(无头)

目录 前言&#xff1a; 1、认识双向链表中的结点 2、认识并创建无头双向链表 3、实现双向链表当中的一些方法 3.1、遍历输出方法&#xff08;display&#xff09; 3.2、得到链表的长度&#xff08;size&#xff09; 3.3、查找关键字key是否包含在双链表中(contains) 3.…