在启动测试环境时可以通过properties参数设置测试环境专用的属性
@SpringBootTest(poperties = {"test.prop=testValue1"})
public class PropertiesAndArgsTest {
@Value("${test.prop}")
private String msg;
@Test
void testProperties(){
System.out.println(msg);
}
}
在启动测试环境时可以通过args参数设置测试环境专用的传入参数
@SpringBootTest(args = {"--test.prop=testValue2"})
public class PropertiesAndArgsTest {
@Value("${test.arg}")
private String msg;
@Test
void testProperties(){
System.out.println(msg);
}
}
使用@Import注解加载当前测试类专用的配置
@Configuration
public class MsgConig {
@Bean
public String msg() {
return "bean msg";
}
}
@SpringBootTest
@Import(MsgConfig.class)
public class ConfigurationTest {
@Autowired
private String msg;
@Test
void testConfiguration(){
System.out.println(msg);
}
}
总结:
加载测试范围配置应用于小范围测试环境
@SpringBootTest(webEnviroment = SpringBootTest.WebEnviroment.RANDOM_PORT)
public class WebTest {
@Test
void testRandomPort () {
}
}
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping
public String getById(){
System.out.println("getById is running......");
return "springboot";
}
}
@SpringBootTest(webEnviroment = SpringBootTest.WebEnviroment.RANDOM_PORT)
//开启虚拟MVC调用
@AutoConfigureMockMvc
public class WebTest {
@Test
//注入虚拟MVC调用对象
void testRandomPort (@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求,当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
//执行请求
mvc.perform(builder);
}
}
@SpringBootTest(webEnviroment = SpringBootTest.WebEnviroment.RANDOM_PORT)
//开启虚拟MVC调用
@AutoConfigureMockMvc
public class WebTest {
@Test
//注入虚拟MVC调用对象
void testRandomPort (@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求,当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
//执行请求
ResultActions action = mvc.perform(builder);
//匹配执行状态(是否预期值)
//定义执行状态匹配器
StatusResultMatchers status = MockMvcResultMatchers.status();
//定义预期执行状态
ResultMatcher ok = status.isOk();
//使用本次真实执行结果与预期结果进行对比
action.andExpect(ok);
}
}
@SpringBootTest(webEnviroment = SpringBootTest.WebEnviroment.RANDOM_PORT)
//开启虚拟MVC调用
@AutoConfigureMockMvc
public class WebTest {
@Test
//注入虚拟MVC调用对象
void testRandomPort (@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求,当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
//执行请求
ResultActions action = mvc.perform(builder);
//匹配执行结果(是否预期值)
//定义执行结果匹配器
ContentResultMatchers content = MockMvcResultMatchers.content();
//定义预期执行结果
ResultMatcher result = content.string("springboot");
//使用本次真实执行结果与预期结果进行对比
action.andExpect(ok);
}
}
虚拟请求体(json)匹配
@Data
public class Book {
private int id;
private String name;
private String type;
private String description;
}
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping
public String 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;
}
}
@SpringBootTest(webEnviroment = SpringBootTest.WebEnviroment.RANDOM_PORT)
//开启虚拟MVC调用
@AutoConfigureMockMvc
public class WebTest {
@Test
//注入虚拟MVC调用对象
void testRandomPort (@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求,当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
//执行请求
ResultActions action = mvc.perform(builder);
//匹配执行结果(是否预期值)
//定义执行结果匹配器
ContentResultMatchers content = MockMvcResultMatchers.content();
//定义预期执行结果
ResultMatcher result = content.json("{\"id\":1,\"name\":\"SpringBoot2\"}");
//使用本次真实执行结果与预期结果进行对比
action.andExpect(ok);
}
}
虚拟请求头匹配
@SpringBootTest(webEnviroment = SpringBootTest.WebEnviroment.RANDOM_PORT)
//开启虚拟MVC调用
@AutoConfigureMockMvc
public class WebTest {
@Test
//注入虚拟MVC调用对象
void testRandomPort (@Autowired MockMvc mvc) throws Exception {
//创建虚拟请求,当前访问/books
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
//执行请求
ResultActions action = mvc.perform(builder);
//匹配执行结果(是否预期值)
//定义执行结果匹配器
HeaderResultMatchers content = MockMvcResultMatchers.header();
//定义预期执行结果
ResultMatcher result = content.string("Content-Type","application/json");
//使用本次真实执行结果与预期结果进行对比
action.andExpect(ok);
}
}
总结:
web环境模拟测试
为测试用例添加事务,SpringBoot会对测试用例对应的事务操作进行回滚
@SpringBootTest
@Transactional
public class DaoTest {
@Autowired
private BookService bookService;
}
如果想在测试用例中提交事务,可以通过@Rollback注解设置
@SpringBootTest
@Transactional
@Rollback(false)
public class DaoTest {
}
总结:
测试用例回滚事务
测试用例数据通常采用随机值进行测试,使用SpringBoot提供的随机数为其赋值
testcase:
book:
id: ${random.int} #随机数
id2: ${random.int(10)} #10以内随机数
type: ${random.int(10,20)} #10到20随机数
uuid: ${random.uuid} #随机uuid
name: ${random.value} #随机字符串,MD5字符串,32位
publishTime: ${random.long} #随机整数(Long范围)
现有数据层解决方案技术选型
Druid + MyBatis-Plus + MySQL
格式一:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
格式二:
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
SpringBoot提供了3种内嵌的数据源对象供开发者选择
spring:
datasource:
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
hikari:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
注意:这个url跟hikari是同一级别
内置持久化解决方案-JdbcTemplate
@SpringBootTest
class SpringbootSSqlApplicationTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
void testJdbc(){
String sql = "select * from tbl_book where id = 1";
List<Book> query = jdbcTemplate.query(sql, new RowMapper<Book>() {
@Override
public Book mapRow(ResultSet rs,int rowNum) throws SQLException {
Book temp = new Book();
temp.setId(rs.getInt("id");
temp.setName(rs.getString("name");
temp.setType(rs.getString("type");
temp.setDescription(rs.getString("description"));
return temp;
}
});
System.out.println(query);
}
}
使用JdbcTemplate得引入依赖:
<dependency>
<groupId>org.springframework.book</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
JdbcTemplate配置:
spring:
jdbc:
template:
query-timeout: -1 # 查询超时时间
max-rows: 500 # 最大行数
fetch-size: -1 # 批处理数量
总结:
1.SpringBoot内置JdbcTemplate持久化解决方案
2.使用JdbcTemplate需要导入spring-boot-starter-jdbc
SpringBoot提供了3种内嵌数据库供开发者选择,提高开发测试效率
设置当前项目为web工程,并配置H2管理控制台参数
server:
port: 80
spring:
datasource:
url: jdbc:h2:~/test
hikari:
driver-class-name: org.h2.Driver
username: sa
password: 123456
h2:
console:
path: /2
enabled: true
访问用户名sa,默认密码123456
浏览器,打开地址 localhost/h2 即可在浏览器中看h2数据库
操作数据库(创建表)
create table tbl_book(id int,name varchar,type varchar,description varchar)
H2数据库控制台仅用于开发阶段,线上项目请务必关闭控制台功能
server:
port: 80
spring:
h2:
console:
path: /h2
enabled: false
总结:
现有数据层解决方案技术选型
Druid + MyBatis-Plus + MySQL
数据源 | 持久化 | 数据库 |
---|---|---|
Druid | MyBatis-Plus | MySQL |
HiKari | MyBatis | H2 |
JdbcTemplate |
SQL
NoSQL
市面上常见的NoSQL解决方案
Redis是一款key-value存储结构的内存级NoSQL数据库
Redis下载(Windows版)
Redis安装与启动(Windows版)
redis-server.exe redis.windows.conf
redis-cli.exe
总结:
1.Redis安装(Windows版)
2.Redis基本操作
1.导入SpringBoot整合Redis坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</denpendency>
2.配置Redis坐标(采用默认配置)
spring:
redis:
host: localhost # 127.0.0.1
port: 6379
3.RedisTemplate提供操纵各种数据存储类型的接口API
4.客户端: RedisTemplate
@SpringBootTest
class SpringbootNosqlApplicationTests {
@Test
void set(@Autowired RedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
ops.set("testKey","testValue");
}
@Test
void set(@Autowired RedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
Object val = ops.get("testKey");
System.out.println(val);
}
}
@SpringBootTest
class SpringbootNosqlApplicationTests {
@Test
void set(@Autowired RedisTemplate redisTemplate) {
HashOperations ops = redisTemplate.opsForHash();
opsH.set("testKeyH","testFieldH","testValueH");
}
@Test
void set(@Autowired RedisTemplate redisTemplate) {
HashOperations opsH = redisTemplate.opsForHash();
Object valH = opsH.get("testKeyH","testFieldH");
System.out.println(valH);
}
}
总结:
SpringBoot整合Redis
客户端: RedisTemplate以对象作为key和value,内部对数据进行序列化
@SpringBootTest
class SpringbootNosqlApplicationTests {
@Test
void set(@Autowired RedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
ops.set("testKey","testValue");
}
@Test
void set(@Autowired RedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
Object val = ops.get("testKey");
System.out.println(val);
}
}
客户端:StringRediTemplate以字符串作为key和value,与Redis客户端操作等效
@SpringBootTest
class SpringbootNosqlApplicationTests {
@Test
void set(@Autowired StringRedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
ops.set("testKey","testValue");
}
@Test
void set(@Autowired StringRedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
Object val = ops.get("testKey");
System.out.println(val);
}
}
总结:
1.RedisTemplate
2.StringRedisTemplate(常用)
SpringBoot操作Redis客户端实现技术切换(jedis)
客户端选择:jedis
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
配置客户端
spring:
redis:
host: localhost # 127.0.0.1
port: 6379
clent-type: lettuce
用jedis, clent-type就指定jedis,用lettuce,客户端类型就指定lettuce(也可不指定,默认就是lettuce)
配置客户端专用属性
spring:
redis:
host: localhost # 127.0.0.1
port: 6379
clent-type: lettuce
lettuce:
pool:
max-active: 16
jedis:
pool:
max-active: 16
lettcus与jedis区别
总结:
SpringBoot整合Redis客户端选择
MongoDB是一个开源、高性能、无模式的文档型数据库。NoSQL数据库产品中的一种,是最像关系型数据库的非关系型数据库
应用场景:
淘宝用户数据
游戏装备数据、游戏道具数据
直播数据、打赏数据、粉丝数据
物联网数据
总结:
Mongodb应用场景
Windows版Mongo下载
Window版Mongo安装
Windows版Mongo启动
- 服务端启动
mongod --dbpath=//\data\db
- 客户端启动
mongo -- host=12.0.0.1 --port=2701
Windows版Mongo安装问题及解决方案
由于找不到VCRUNTIMEE140_1.dll,无法继续执行代码。重新安装程序可能会解决此问题。
步骤一: 下载对应的dll文件(通过互联网搜索即可)
步骤二: 拷贝到windows安装路径下的system32目录中
步骤三: 执行命令注册对应dll文件
regsve32 vcruntime140_1.dll
总结:
新增
db.集合名称.insert/sava/insertOne(文档)
修改
db.集合名称.remove(条件)
删除
db.集合名称.update(条件,{操作种类:{文件}})
1.基础查询
2.条件查询
总结:
Mongodb基础CRUD
导入Mongodb驱动
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
配置客户端
spring:
data:
mondodb:
url: mongodb://localhost/luxifa
客户端读写Mongodb
@Test
void testSave(@Autowired MongoTemplate mongoTemplate) {
Book boo = new Book();
book.setId(1);
book.setType("springboot");
book.setName("springboot");
book.setDescription("springboot");
mongoTemplate.save(book);
}
@Test
void testFind(@Autowired MongoTemplate mongoTemplate) {
List<Book> all = mongoTemplate.findAll(Book.class);
System.out.println(all);
}
总结:
SpringBoot整合Mongodb
- 导入缓存技术对应的starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
- 启用缓存
@SpringBootApplication
@EnableCaching
public class SpringbootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootCacheApplication.class,args);
}
}
- 设置当前操作的结果数据进入缓存
@Cacheable(value="cacheSpace",key="#id")
public Book getById(Integer id) {
return bookDao.selectById(id);
}
总结:
SpringBoot启动缓存的方式
- @EnableCaching
- Cacheable
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
spring:
cache:
type: ehcahe
ehcache:
config: ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://echcache.org/ehcache.xsd"
updateCheck="false">
<defaultCache
eternal="false"
diskPersistent="false"
maxElementsInMemory="1000"
overflowToDisk="60"
timeToldleSeconds="60"
timeToLiveSeconds="60"
memoryStoreEvictionPolict="LRU" />
ehcache>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://echcache.org/ehcache.xsd"
updateCheck="false">
<cache
name="smsCode"
eternal="false"
diskPersistent="false"
maxElementsInMemory="1000"
overflowToDisk="60"
timeToldleSeconds="60"
timeToLiveSeconds="60"
memoryStoreEvictionPolict="LRU" />
ehcache>
总结:
变更缓存供应商为Ehcache
检测易失数据(可能会过期的数据集server.db[i].expires)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
redis:
host: localhost
port: 6379
cache:
type: redis
spring:
redis:
host: localhost
port: 6379
cache:
type: redis
redis:
use-key-prefix: true #是否使用前缀名(系统定义前缀名)
key-prefix: sms_ #追加自定义前缀名
time-to-live: 10s #有效时长
cache-null-value: false #是否允许存储空值
总结:
变更供应商为Redis
安装memcached
安装
memcached.exe -d install
运行memcached
mamcached.exe -d start
memcached.exe -d stop
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.7</version>
</dependency>
memcached:
# memcached服务器地址
servers: localhost:11211
# 连接池的数量
poolSize: 10
# 设置默认操作超时
opTimeout: 3000
@Component
@ConfigurationProperties(prefix = "memcached")
@Data
public class XMemcachedProperties {
private String servers;
private Integer poolSize;
private Long opTimeout;
}
@Configuration
public class XMemcachedConfig {
@Autowired
private XMemcachedProperties xMemcachedProperties;
@Bean
public MemcachedClient getMemcachedClient() throws IOException{
MemcachedClientBuilder builder = new XMemcachedClientBuilder(xMemcachedProperties.getServers());
MemcachedClient memcachedClient = builder.build();
return memcachedClient;
}
}
@Service
public class SMSCodeServiceMemcacheImpl implements SMSCodeService {
@Autowired
private CodeUtils codeUtils;
@Autowired
private MemcachedClient memcachedClient;
@Ovrride
public String sendCodeToSMS(String tele) {
String code = this.codeUtils.generator(tele);
//将数据加入memcache
try {
memcachedClient.set(tele,0,code); //key,timeout,value
} catch (Exception e) {
e.printStackTrace();
}
return code;
}
public String checkCode(CodeMsg codeMsg) {
String value = null;
try {
value = memcachedClient.get((code.getTele()).toString(); //key,timeout,value
} catch (Exception e) {
e.printStackTrace();
}
return codeMsg.getCode().equals(value);
}
}
总结:
1.xmemcache客户端加载方式(bean初始化)
2.xmemcache客户端使用方式(set & get)
jetCache对SpringCache进行了封装,在原有功能基础上实现了多级缓存、缓存统计、自动刷新、异步调用、数据报表等功能
jetCache设定了本地缓存与远程缓存的多级缓存解决方案
本地缓存(local):linkedHashMap、Caffeine
远程缓存(remote): Redis、 Tair
加入jetcache坐标
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.6.2</version>
</dependency>
jetcache:
remote:
default:
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50
sms:
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50
jetcache:
local:
default:
type: linkedhashmap
keyConvertor: fastjson
jetcache:
statIntervalMinutes: 15
areaInCacheName: false
local:
default:
type: linkedhashmap
keyConvertor: fastjson
limit: 100
remote:
default:
host: localhost
port: 6379
type: redis
keyConvertor: fastjson
valueEncoder: java
valueDecoder: java
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
属性 | 默认值 | 说明 |
---|---|---|
jetcache.statIntervalMinutes | 0 | 统计间隔,0表示不统计 |
jetcache.hiddenPackages | 无 | 自动生成name时,隐藏指定的包名前缀 |
jetcache.(local或remote).${area}.type | 无 | 缓存类型,本地支持linkedhashmap、caffeine,远程支持redis、tair |
jetcache.(local或remote).${area}.keyConvertor | 无 | key转换器,当前仅支持fastjson |
jetcache.(local或remote).${area}.valueEncoder | java | 仅remote类型的缓存需要指定,可选java和kryo |
jetcache.(local或remote).${area}.valueDecoder | java | 仅remote类型的缓存需要指定,可选java和kryo |
jetcache.(local或remote).${area}.limit | 100 | 仅local类型的缓存需要指定,缓存实例最大元素数 |
jetcache.(local或remote).${area}.expireAfterWriteInMillis | 无穷大 | 默认过期时间,毫秒单位 |
jetcache.${area}.expireAfterAccessInmillis | 0 | 仅local类型的缓存有效,毫秒单位,最大不活动间隔 |
@SpringBootApplication
@EnableCreateCacheAnnotation
public class SpringbootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootCacheApplication.class,args);
}
}
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
@Autowired
private CodeUtils codeUtils;
@CreateCache(name = "smsCache" , expire = 3600)
private Cache<String,String> jetSMSCache;
}
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
@Override
public String sendCodeToSMS(String tele) {
String code = this.codeUtils.generator(tele);
jetSMSCache.put(telw,code);
return code;
}
@Override
public boolean checkCode(CodeMsg codeMsg) {
String value = jetSMSCache.get(codeMsg.getTele());
return codeMsg.getCode().equals(value);
}
}
总结:
1、jetcache简介
2、jetcache远程缓存使用方式
3、jetcache本地缓存使用方式
@SpringBootApplication
@EnableCreateCacheAnnotation
@EnableMethodCache(basePackages = "com.ithema")
public class SpringBootJetCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJetCacheApplication.class,args);
}
}
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Cache(name = "smsCache_",key = "#id", expire = 3600)
@CacheRefresh(refresh = 10,timeUnit = TimeUnit.SECONDS)
public Book getById(Integer id) {
return bookDao.selectById(id);
}
}
@Service
public class BookServiceImpl implement BookService {
@CacheUpdate(name = "smsCache_", key = "#book.id", value = "#book")
public boolean update(Book book) {
return bookDao.updateById(book) > 0;
}
@CacheInvalidate(name = "smsCache_", key = "#id")
public boolean delete(Integer id) {
return bookDao.deleteById(id) > 0;
}
}
@Data
public class Book implements Serializable {
}
jetcache:
remote:
default:
type: redis
keyConvertor: fastjson
valueEncoder: java
valueDecoder: java
总结:
jetcache方法注解使用方式
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-spring-boot2-starter</artifactId>
<version>2.8.0-release</version>
</dependency>
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>2.8.4-release</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>jehcache</artifactId>
</dependency>
j2cache:
config-location: j2cache.properties
# 配置1级缓存
j2cache.L1.provider_class = ehcache
ehcache.configXml = ehcache.xml
# 配置1级缓存数据到2级缓存的广播方式:可以使用redis提供的消息订阅模式,也可以使用groupd多播实现
j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy
# 配置2级缓存
j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
j2cache.L2.config_section = redis
redis.hosts = localhost:6379
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
@Autowired
private CodeUtils codeUtils;
@Autowired
private CacheChannel cacheChannel;
}
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
@Override
public String sendCodeToSMS(String tele) {
String code = codeUtils.generator(tele);
cacheChannel.set("sms",tele,code);
return code;
}
@Override
public boolean checkCode(SMSCode smsCode) {
String code = cacheChannel.get("sms",smsCode.getTele()).asString();
return smsCode.getCode().equals(code);
}
}
总结:
j2cache缓存的基础使用
小结:
1.spring-cache
simple
ehcache
redis
memcached
2.jetcache
3.j2cache