六、Java框架之SpringBoot
黑马课程
文章目录
- 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)
-
-
类文件具有错误的版本 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-web
和spring-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包进行版本管理的管理器,它并没有导入依赖,只是锁定了版本
子工程如果需要某个依赖,只需要引入依赖的groupid
和artifactId
不需要定义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: SpringBootserver:port: 80enterprise:name: companyage: 16tel: 123456789subject:- 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 {@Autowiredprivate 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 {@Autowiredprivate 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.yml
和resources/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 {@Autowiredprivate BookService bookService;//注入测试对象@Testpublic void testSave(){//测试功能bookService.save();}
}
SpringBoot整合Junit
生成SpringBoot项目时,在test里面会自动生成一个SpringbootApplicationTests类,只需要在contextLoads
里面调用方法,即可测试
package com.example;@SpringBootTest
class SpringbootApplicationTests {@Autowiredprivate BookService bookService;@Testvoid 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 Web
,SQL/MyBatis Framework
,MySQL 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.Driverurl: jdbc:mysql://localhost:3306/ssm_db?useSSL=falseusername: rootpassword: 123456#下面配置数据源,使用druidtype: com.alibaba.druid.pool.DruidDataSource
- 如果SpringBoot版本是2.7.8,可能提示你的jdbc驱动过时了,让更换为
com.mysql.cj.jdbc.Driver
,改不改都行
步骤5:测试
package com.example;@SpringBootTest
class SpringbootApplicationTests {@Autowiredprivate BookDao bookDao;@Testvoid 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: 80spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/ssm_db?useSSL=false&serverTimeZone=UTCusername: rootpassword: 123456type: 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 {@Autowiredprivate BookDao bookDao;@Overridepublic boolean save(Book book) {System.out.println(book);return bookDao.save(book) > 0;}@Overridepublic boolean delete(Integer id) {return bookDao.delete(id) > 0;}@Overridepublic boolean update(Book book) {return bookDao.update(book) > 0;}@Overridepublic Book getById(Integer id) {if(id == 1){//模拟异常,抛出自定义的业务异常类throw new BussinessException(Code.BUSINESS_ERROR, "查询失败,请重试!");}return bookDao.getById(id);}@Overridepublic 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 {@Autowiredprivate BookService bookService;@PostMappingpublic 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);}@PutMappingpublic 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);}@GetMappingpublic 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 {@Autowiredprivate BookService bookService;@Testpublic void testGetById(){Book book = bookService.getById(2);System.out.println(book);}@Testpublic 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,即可达到主页
相关文章:

六、Java框架之SpringBoot
黑马课程 文章目录1. SpringBoot入门1.1 SpringBoot入门案例步骤1:创建SpringBoot项目高版本springboot常见错误步骤2:创建BookController步骤3:启动服务器并运行程序pom.xml示例1.2 官网创建SpringBoot1.3 SpringBoot工程快速启动问题导入打…...

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

人工智能轨道交通行业周刊-第33期(2023.2.6-2.12)
本期关键词:高铁激光清洗、高铁确认列车、无线通信系统、推理服务优化、量子信息技术 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟V…...

五分钟看懂Java字节码:极简手册
字节码新手很容易被厚厚的 JVM 书籍劝退,即使我看过相关书籍,工作真正用到时也全忘了,还得现学。 等我有了一定的字节码阅读经验,才发现字节码其实非常简单,只需要三步就能快速学会: 先了解 JVM 的基本结…...

C++ 类与对象(下)
✅<1>主页:我的代码爱吃辣 📃<2>知识讲解:C 🔥<3>创作者:我的代码爱吃辣 ☂️<4>开发环境:Visual Studio 2022 💬<5>前言:C类与对象的收尾工作&#…...

Java基础——I/O
一、异常 异常是程序中可能出现的问题,它的父类是Exception。异常分为两类,编译时异常、运行时异常。 编译时异常:没有继承RuntimeException的异常,直接继承于Exception。编译阶段就会错误提示。运行时异常:RuntimeE…...

关于@hide的理解
在上一篇文章《学习HandlerThread》我们提到虽然HandlerThread类里有getThreadHandler()方法得到Handler,但是我们不可能调用到它。因为这个方法用hide注释了 /*** return a shared {link Handler} associated with this thread* hide*/NonNullpublic Handler getT…...

使用python加密主机文件几种方法实现
本文主要介绍了使用python加密主机文件几种方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧数据加密是一种保护数据安全的技术,通过对数据进行编…...

西湖论剑 2023 比赛复现
WEB real_ez_node 在 route/index.js 中: router.post(/copy,(req,res)>{res.setHeader(Content-type,text/html;charsetutf-8)var ip req.connection.remoteAddress;console.log(ip);var obj {msg: ,}if (!ip.includes(127.0.0.1)) {obj.msg"only for…...

微信小程序更换管理员/重置管理员
方式1: 首先进入微信公众平台官网进入并登录后在管理中找到成员管理选项找到管理员点击后方的修改选项需要使用原管理员的微信进行扫码验证扫码后在手机上确认绑定新管理员,注意:如果是个人账号不可以更改成其他人。 方式2:原管…...

企业进存销管理系统
技术:Java、JSP等摘要:随着当今世界计算机技术的飞速发展,计算机在企业管理中应用的普及,利用计算机实现企业进销存管理势在必行。本系统结合公司实际的进销存制度,通过对本公司的供应商、客户、商品、进货、销售、进销…...

C++入门
变量变量创建的语法: 数据类型 变量名 变量初始值;int a 10;cout << a << endl;常量作用:用于记录程序中不可更改的教国C定义常量两种方式1).#define 宏常量:#define 常量名 常量值通常在文件上方定义。表示一个常量2).const 修饰的变量const 数据类型 常量名 常…...

视频知识点(20)- H264码流如何在SPS中获取宽高信息?
《音视频开发》系列-总览 前沿 了解H264视频编码格式的小伙伴都知道,H264编码中存在两个非常重要的参数集。没错,它们就是序列参数集(SPS)和图像参数集(PPS),而且通常情况下,PPS会依赖SPS中的部分参数信息,同时,视频码流的宽高信息也存储在SPS中。那么如何从中获取视…...

鲜花数据集实验结果总结
从read_split_data中得到:训练数据集,验证数据集,训练标签,验证标签。的所有的具体详细路径 数据集位置:https://download.csdn.net/download/guoguozgw/87437634 import os #一种轻量级的数据交换格式, …...

ElasticJob-Lite架构篇 - 认知分布式任务调度ElasticJob-Lite
前言 本文基于 ElasticJob-Lite 3.x 版本展开分析。 如果 Quartz 集群中有多个服务端节点,任务决定在哪个服务端节点上执行的呢? Quartz 采用随机负载,通过 DB 抢占下一个即将触发的 Trigger 绑定的任务的执行权限。 在 Quartz 的基础上&…...

【直击招聘C++】2.6 对象之间的复制
2.6 对象之间的复制一、要点归纳1. 对象之间的复制操作1.1 运算符1.2 拷贝构造函数2. 对象之间的浅复制和深复制2.1 对象的浅复制2.2 对象的深复制二、面试真题解析面试题1面试题2一、要点归纳 1. 对象之间的复制操作 同一个类的对象之间可以进行复制操作,即将一个…...

学了这么久python,不会连自己啥python版本都不知道吧?
人生苦短,我用Python 源码资料电子书:点击此处跳转文末名片获取 查看 Python 版本 我们可以在命令窗口(Windows 使用 winR 调出 cmd 运行框)使用以下命令查看我们使用的 Python 版本: python -V 或 python --version 以上命令执行结果如下: …...

Revive:从间谍软件进化成银行木马
2022 年 6 月,Cleafy 研究人员发现了一个新的安卓银行木马 Revive。之所以选择 Revive 这个名称,是因为恶意软件为防止停止工作启用的一项功能名为 revive。 Revive 属于持续潜伏的那一类恶意软件,因为它是为特定目标开发和定制的。这种类型…...

Python 之 NumPy 简介和创建数组
文章目录一、NumPy 简介1. 为什么要使用 NumPy2. NumPy 数据类型3. NumPy 数组属性4. NumPy 的 ndarray 对象二、numpy.array() 创建数组1. 基础理论2. 基础操作演示3. numpy.array() 参数详解三、numpy.arange() 生成区间数组四、numpy.linspace() 创建等差数列五、numpy.logs…...

与六年测试工程师促膝长谈,他分享的这些让我对软件测试工作有了全新的认知~
不知不觉已经从事软件测试六年了,2016年毕业到进入外包公司外包给微软做软件测试, 到现在加入著名的外企。六年的时间过得真快。长期的测试工作也让我对软件测试有了比较深入的认识。但是我至今还是一个底层的测试人员,我的看法都比较狭隘&am…...

裕太微在科创板上市:市值约186亿元,哈勃科技和小米基金为股东
2月10日,裕太微电子股份有限公司(下称“裕太微”,SH:688515)在上海证券交易所上市。本次上市,裕太微的发行价为92元/股,发行2000万股,发行市盈率不适用,发行后总股本8000万股。 根据…...

毕业后5年,我终于变成了月薪13000的软件测试工程师
我用了近2个月的时间转行,在今年1月底顺利入职了一家北京的互联网公司,从事的是软件测试的工作。 和大家看到的一样,我求职的时间花费的比较短,求职过程非常顺利,面试了一周就拿到了3家offer,3家offer的薪…...

实践指南|如何在 Jina 中使用 OpenTelemetry 进行应用程序的监控和跟踪
随着软件和云技术的普及,越来越多的企业开始采用微服务架构、容器化、多云部署和持续部署模式,这增加了因系统失败而给运维/ SRE / DevOps 团队带来的压力,从而增加了开发团队和他们之间的摩擦,因为开发团队总是想尽快部署新功能&…...

MySQL 创建数据表
在创建数据库之后,接下来就要在数据库中创建数据表。所谓创建数据表,指的是在已经创建的数据库中建立新表。 创建数据表的过程是规定数据列的属性的过程,同时也是实施数据完整性(包括实体完整性、引用完整性和域完整性)…...

一文详解网络安全事件的防护与响应
网络安全事件的发生,往往意味着一家企业的生产经营活动受到影响,甚至数据资产遭到泄露。日益复杂的威胁形势使现代企业面临更大的网络安全风险。因此,企业必须提前准备好响应网络安全事件的措施,并制定流程清晰、目标明确的事件响…...

vue directive 注册局部指令
注册局部指令 vue directive 在注册局部指令时,是通过在组件 options 选项中设置 directives 属性。如下: directives: {focus: {// 指令的定义inserted: function (el) {el.focus()}} }在模板中的任何元素上都可以使用新的 v-focus propertyÿ…...

LC-70-爬楼梯
原题链接:爬楼梯 个人解法 思路: 动态规划 状态表示:f[i]表示走到第n阶台阶有几种方法 状态转移:f[i] f[i -1] f[i - 2] 这实际上就是斐波那契数列,通过转移可以看到,我们只用了三个变量,故…...

Scratch少儿编程案例-可爱的简约贪吃蛇
专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

编译 Android 时如何指定输出目录?
文章目录0. 导读1. 指定 Android 编译输出目录2. 指定 Android dist 编译输出目录3. 指定 Android 模块编译输出目录4. Android 源码中编译相关的文档0. 导读 偶尔会有朋友问编译 Android 时如何指定输出目录? 这里有两种情况: 一是如何将 Android 默认的输出目…...

CF1574C Slay the Dragon 题解
CF1574C Slay the Dragon 题解题目链接字面描述题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示代码实现题目 链接 https://www.luogu.com.cn/problem/CF1574C 字面描述 题面翻译 给定长度为 nnn 的序列 aaa,mmm 次询问,每次询…...