目录:
开启开发者工具
激活热部署:Ctrl + F9
小结:
ctrl+alt+shift+/
激活方式:Idea失去焦点5秒后启动热部署
热部署Idea专业版spring boot(spring mvc)项目_idea springmvc 热部署-CSDN博客
默认不触发重启的目录列表
自定义不参与重启排除项
属性加载优先顺序
设置高优先级属性禁用热部署
@EnableConfigurationProperties注解可以将使用@ConfigurationProperties注解对应的类加入Spring容器
注意事项
解除使用@ConfigurationProperties注释警告
注意事项
@ConfigurationProperties绑定属性支持属性名宽松绑定
注意事项
JDK8支持的时间与空间计量单位
数据校验
添加JSR3日3规范坐标与Hibernate校验框架对应坐标
对Bean开启校验功能
设置校验规则
字面值表达方式
application.yml
servers:
ipAddress: 192.168.0.1
# ipaddress: 192.168.0.1
# ip_address: 192.168.0.1
# ip-address: 192.168.0.1
# IPADDRESS: 192.168.0.1
# IP_ADD_R-E_SS: 192.168.0.1
port: 4444
timeout: -1
serverTimeOut: 3
dataSize: 10240
dataSource:
driverClassName: com.mysql.jdbc.Driver456
password: 0127
ApplicationTests
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Value("${dataSource.password}")
private String password;
@Value("${servers.ipAddress}")
private String msg;
@Test
void contextLoads() {
System.out.println(msg);
System.out.println(password);
}
}
运行结果:(0127)转换成了8进制
在启动测试环境时可以通过properties参数设置测试环境专用的属性
优势:比多环境开发中的测试环境影响范围更小,仅对当前测试类有效
在启动测试环境时可以通过args参数设置测试环境专用的传入参数
Sprintboot14TestApplicationTests
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
//@SpringBootTest(properties = {"test.prop=testValue1"})
//@SpringBootTest(args = {"--test.prop=testValue2"})
@SpringBootTest(properties = {"test.prop=testValue1"}, args = {"--test.prop=testValue2"})
class Sprintboot14TestApplicationTests {
@Value("${test.prop}")
private String msg;
@Test
void contextLoads() {
System.out.println(msg);
}
}
application.yml
test:
prop: testValue
使用@Import注解加载当前测试类专用的配置
MsgConfig.class
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MsgConfig {
@Bean
public String msg() {
return "bean msg";
}
}
ConfigurationTest.class
package com.example;
import com.example.config.MsgConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
@SpringBootTest
@Import({MsgConfig.class})
public class ConfigurationTest {
@Autowired
private String msg;
@Test
void testConfiguration() {
System.out.println(msg);
}
}
运行结果:
模拟端口
WebTest.class
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class WebTest {
@Test
void test() {
}
}
虚拟请求测试
BookController.class
package com.example.controller;
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 {
@GetMapping
public String getById() {
System.out.println("getById is running...");
return "sprintboot";
}
}
WebTest.class
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureMockMvc
public class WebTest {
@Test
void test() {
}
@Test
void testWeb(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
mvc.perform(builder);
}
}
运行结果:
虚拟请求状态匹配
WebTest.class
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureMockMvc
public class WebTest {
@Test
void testWeb(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
mvc.perform(builder);
}
@Test
void testStatus(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
StatusResultMatchers status = MockMvcResultMatchers.status();
ResultMatcher ok = status.isOk();
action.andExpect(ok);
}
}
虚拟请求响应体匹配
WebTest.class
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.ContentResultMatchers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureMockMvc
public class WebTest {
@Test
void testWeb(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
mvc.perform(builder);
}
@Test
void testStatus(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
StatusResultMatchers status = MockMvcResultMatchers.status();
ResultMatcher ok = status.isOk();
action.andExpect(ok);
}
@Test
void testBody(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher result = content.string("springboot");
action.andExpect(result);
}
}
虚拟请求响应体(json)匹配
BookController.class
package com.example.controller;
import com.example.domain.Book;
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 {
// @GetMapping
// public String getById() {
// System.out.println("getById is running...");
// return "springboot";
// }
@GetMapping
public Book getById() {
System.out.println("getById is running...");
Book book = new Book();
book.setId(1);
book.setName("springboot");
book.setType("springboot");
book.setDescription("springboot");
return book;
}
}
WebTest.class
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.ContentResultMatchers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureMockMvc
public class WebTest {
@Test
void testWeb(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
mvc.perform(builder);
}
@Test
void testStatus(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
StatusResultMatchers status = MockMvcResultMatchers.status();
ResultMatcher ok = status.isOk();
action.andExpect(ok);
}
@Test
void testBody(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher result = content.string("springboot");
action.andExpect(result);
}
@Test
void testJson(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher result = content.json("{\"id\":1,\"name\":\"springboot\",\"type\":\"springboot\",\"description\":\"springboot\"}");
action.andExpect(result);
}
}
虚拟请求响应头匹配
WebTest.class+
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.ContentResultMatchers;
import org.springframework.test.web.servlet.result.HeaderResultMatchers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureMockMvc
public class WebTest {
@Test
void testWeb(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
mvc.perform(builder);
}
@Test
void testStatus(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
StatusResultMatchers status = MockMvcResultMatchers.status();
ResultMatcher ok = status.isOk();
action.andExpect(ok);
}
@Test
void testBody(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher result = content.string("springboot");
action.andExpect(result);
}
@Test
void testJson(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher result = content.json("{\"id\":1,\"name\":\"springboot\",\"type\":\"springboot\",\"description\":\"springboot\"}");
action.andExpect(result);
}
@Test
void testContentType(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
HeaderResultMatchers header = MockMvcResultMatchers.header();
ResultMatcher contentType = header.string("Content-Type", "application/json");
action.andExpect(contentType);
}
@Test
void testGetById(@Autowired MockMvc mvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
ResultActions action = mvc.perform(builder);
StatusResultMatchers status = MockMvcResultMatchers.status();
ResultMatcher ok = status.isOk();
action.andExpect(ok);
HeaderResultMatchers header = MockMvcResultMatchers.header();
ResultMatcher contentType = header.string("Content-Type", "application/json");
action.andExpect(contentType);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher result = content.json("{\"id\":1,\"name\":\"springboot\",\"type\":\"springboot\",\"description\":\"springboot\"}");
action.andExpect(result);
}
}
为测试用例添加事务,SpringBoot会对测试用例对应的事务提交操作进行回滚
如果想在测试用例中提交事务,可以通过@Rollback注解设置
测试用例数据通常采用随机值进行测试,使用SpringBoot提供的随机数为其赋值
现有数据层解决方案技术选型
格式一
格式二
SpringBoot提供了3种内嵌的数据源对象供开发者选择
通用配置无法设置具体的数据源配置信息,仅提供基本的连接相关配置,如需配置,在下一级配置中设置具体设定
现有数据层解决方案技术选型
内置持久化解决方案——JdbcIemplate
JdbcTemplate配置
SpringBoot提供了3种内嵌数据库供开发者选择,提高开发测试效率
导入H2相关坐标
设置当前项目为web工程,并配置H2管理控制台参数
访问用户名sa,默认密码123456
操作数据库(创建表)
设置访问数据源
H2数据库控制台仅用于开发阶段,线上项目请务必关闭控制台功能
SpringBoot可以根据url地址自动识别数据库种类,在保障驱动类存在的情况下,可以省略配置
现有数据层解决方案技术选型
BookDao.interface
package com.example.springboot_15_sql.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springboot_15_sql.domain.Book;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BookDao extends BaseMapper {
}
Book.class
package com.example.springboot_15_sql.domain;
import lombok.Data;
@Data
public class Book {
private int id;
private String name;
private String type;
private String description;
}
Sprintboot15SqlApplication.class
package com.example.springboot_15_sql;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Springboot15SqlApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot15SqlApplication.class, args);
}
}
application.yml
#server:
# port: 8080
#
#spring:
# datasource:
# url: jdbc:mysql://localhost:3308/test_db
# hikari:
# driver-class-name: com.mysql.cj.jdbc.Driver
# username: root
# password: 666666
# maximum-pool-size: 50
#mybatis-plus:
# global-config:
# db-config:
# table-prefix: tbl_
# id-type: auto
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
server:
port: 8080
spring:
h2:
console:
enabled: true
path: /h2
datasource:
url: jdbc:h2:~/test
hikari:
driver-class-name: org.h2.Driver
username: sa
password: 123456
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pom.xml
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.7.17
com.example
springboot_15_sql
0.0.1-SNAPSHOT
springboot_15_sql
springboot_15_sql
1.8
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-data-jpa
com.h2database
h2
com.baomidou
mybatis-plus-boot-starter
3.4.1
org.springframework.boot
spring-boot-maven-plugin
paketobuildpacks/builder-jammy-base:latest
org.projectlombok
lombok
Sprintboot15SqlApplicationTests.class
package com.example.springboot_15_sql;
import com.example.springboot_15_sql.dao.BookDao;
import com.example.springboot_15_sql.domain.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
@SpringBootTest
class Springboot15SqlApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void test() {
bookDao.selectById(1);
}
@Test
void testJdbcTemplate(@Autowired JdbcTemplate jdbcTemplate) {
String sql = "select * from tbl_book";
// List
市面上常见的NoSQL解决方案
Redis是一款key-value存储结构的内存级NoSQL数据库
Redis下载(Windows版)
Redis安装与启动( Windows版)
导入SpringBoot整合Redis坐标
配置Redis(采用默认配置)
RedisTemplate提供操作各种数据存储类型的接口API
客户端:RedisTemplate
pom.xml
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.5.4
com.example
sprintboot_16_redis
0.0.1-SNAPSHOT
sprintboot_16_redis
sprintboot_16_redis
1.8
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
paketobuildpacks/builder-jammy-base:latest
application.yml
spring:
redis:
host: localhost
port: 6379
Springboot16RedisApplicationTests.class
package com.example.sprintboot_16_redis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
@SpringBootTest
class Sprintboot16RedisApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void set() {
ValueOperations ops = redisTemplate.opsForValue();
ops.set("age", "41");
}
@Test
void get() {
ValueOperations ops = redisTemplate.opsForValue();
Object age = ops.get("age");
System.out.println(age);
}
@Test
void hset() {
HashOperations ops = redisTemplate.opsForHash();
ops.put("info", "a", "aa");
}
@Test
void hget() {
HashOperations ops = redisTemplate.opsForHash();
Object val = ops.get("info", "a");
System.out.println(val);
}
}
客户端:RedisTemplate以对象作为key和value,内部对数据进行序列化
客户端: StringRedisTemplate以字符串作为key和value,与Redis客户端操作等效
StringRedisTemplateTest.class
package com.example.sprintboot_16_redis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
@SpringBootTest
public class StringRedisTemplateTest {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void get1() {
ValueOperations ops = stringRedisTemplate.opsForValue();
String name = ops.get("name");
System.out.println(name);
}
@Test
void get2() {
ValueOperations ops = redisTemplate.opsForValue();
Object name = ops.get("name");
System.out.println(name);
}
}
客户端选择:jedis
配置客户端
配置客户端专用属性
lettcus与jedis区别