提交 8fc71498 authored 作者: Matrix's avatar Matrix

fix(缓存): 添加了测试用例接口的缓存代码

上级 04d3bc87
...@@ -33,6 +33,15 @@ ...@@ -33,6 +33,15 @@
<version>4.5.10</version> <version>4.5.10</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<!-- httpclient缓存--> <!-- httpclient缓存-->
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
......
...@@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Value; ...@@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
...@@ -22,6 +23,7 @@ import java.net.Socket; ...@@ -22,6 +23,7 @@ import java.net.Socket;
* @author matrix * @author matrix
*/ */
@Slf4j @Slf4j
@EnableCaching
@SpringBootApplication @SpringBootApplication
@MapperScan(basePackages = {"org.matrix.database.mapper", "org.matrix.zentao.mapper"}) @MapperScan(basePackages = {"org.matrix.database.mapper", "org.matrix.zentao.mapper"})
public class BaseBootApplication implements CommandLineRunner { public class BaseBootApplication implements CommandLineRunner {
......
...@@ -42,7 +42,8 @@ public class IDataSourceServiceImpl implements IDataSourceService { ...@@ -42,7 +42,8 @@ public class IDataSourceServiceImpl implements IDataSourceService {
} }
/** /**
* 将当前使用的数据替换为参数提供的数据源,如果还没有,则会添加,如果已经有了,则不会添加 * 将当前使用的数据替换为参数提供的数据源
* 如果还没有该数据则会添加,如果已经有了,则不会添加
* *
* @param dto 数据源信息 * @param dto 数据源信息
* @return 当前存在的数据源集合 * @return 当前存在的数据源集合
......
...@@ -97,7 +97,7 @@ public class MoveActuator implements Actuator { ...@@ -97,7 +97,7 @@ public class MoveActuator implements Actuator {
if (matcher.find()) { if (matcher.find()) {
col = matcher.group("col"); col = matcher.group("col");
if (StringUtils.isEmpty(col)) { if (StringUtils.isEmpty(col)) {
throw new GlobalException("动作语法里必须包含形如${pre1.name}这样的字符串!您提供的是: " + dynamicString); throw new GlobalException("[行为执行器]动作语法里必须包含形如${pre1.name}这样的字符串!您提供的是: " + dynamicString);
} }
row = matcher.group("row"); row = matcher.group("row");
...@@ -114,7 +114,7 @@ public class MoveActuator implements Actuator { ...@@ -114,7 +114,7 @@ public class MoveActuator implements Actuator {
pathResolution = true; pathResolution = true;
} }
} else { } else {
throw new GlobalException("提供的语法不正确!正确的语法应当是形如 ${pre1.name}[0]<$.book> 这样的,您提供的是 :" + dynamicString); throw new GlobalException("[行为执行器]提供的语法不正确!正确的语法应当是形如 ${pre1.name}[0]<$.book> 这样的,您提供的是 :" + dynamicString);
} }
// 解析,解释 col、row、jp // 解析,解释 col、row、jp
...@@ -188,7 +188,7 @@ public class MoveActuator implements Actuator { ...@@ -188,7 +188,7 @@ public class MoveActuator implements Actuator {
} else if (actionType == WAIT_ACTION) { } else if (actionType == WAIT_ACTION) {
waitActionHandler(runtimeDetail); waitActionHandler(runtimeDetail);
} else { } else {
throw new GlobalException("不支持的行为类型: " + actionType); throw new GlobalException("[行为执行器]不支持的行为类型: " + actionType);
} }
log.info("[动作执行器] 动作执行完毕"); log.info("[动作执行器] 动作执行完毕");
...@@ -202,6 +202,22 @@ public class MoveActuator implements Actuator { ...@@ -202,6 +202,22 @@ public class MoveActuator implements Actuator {
resSet = ThreadLocal.withInitial(HashMap::new); resSet = ThreadLocal.withInitial(HashMap::new);
} }
/**
* 线程等待执行器
*
* @param runtimeDetail 要等待的时间,单位毫秒ms
*/
private void waitActionHandler(String runtimeDetail) {
try {
int sleepMills = Integer.parseInt(runtimeDetail);
Thread.sleep(sleepMills);
} catch (InterruptedException e) {
log.error("[线程异常] 线程休眠时发生异常,异常信息 : " + e.getMessage());
} catch (Exception e) {
log.error("[参数/转换异常] 执行行为时参数抓换时发生异常,异常信息 " + e.getMessage());
}
}
/** /**
* 将行为语法里的col部分转化为threadLocal里的key值 * 将行为语法里的col部分转化为threadLocal里的key值
* *
...@@ -211,39 +227,23 @@ public class MoveActuator implements Actuator { ...@@ -211,39 +227,23 @@ public class MoveActuator implements Actuator {
private MoveRegularObject col2RegularObj(String col) { private MoveRegularObject col2RegularObj(String col) {
String[] colArray = col.split("\\."); String[] colArray = col.split("\\.");
if (colArray.length != 2) { if (colArray.length != 2) {
throw new GlobalException("行为语法里定位部分的语法不符合规范,您提供的部分是: " + col); throw new GlobalException("[行为执行器]行为语法里定位部分的语法不符合规范,您提供的部分是: " + col);
} }
String strategy = colArray[0].substring(0, 3).toUpperCase() + "_MOVE"; String strategy = colArray[0].substring(0, 3).toUpperCase() + "_MOVE";
if (!STRATEGY_LIST.contains(strategy)) { if (!STRATEGY_LIST.contains(strategy)) {
throw new GlobalException("行为语法里定位部分的语法不符合规范(需要至少包含pre/mid/aft),您提供的部分是:" + col); throw new GlobalException("[行为执行器]行为语法里定位部分的语法不符合规范(需要至少包含pre/mid/aft),您提供的部分是:" + col);
} }
int actionId; int actionId;
try { try {
actionId = Integer.parseInt(colArray[0].substring(3)); actionId = Integer.parseInt(colArray[0].substring(3));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new GlobalException("行为语法里定位部分的语法没有提供合适的actionId!例如需要提供pre1,pre2,您提供的部分是: " + col); throw new GlobalException("[行为执行器]行为语法里定位部分的语法没有提供合适的actionId!例如需要提供pre1,pre2,您提供的部分是: " + col);
} }
String key = strategy + "_" + actionId; String key = strategy + "_" + actionId;
LogQueueRuntime.addNewLog("行为执行器KEY值拼接完成,KEY值 = " + key); LogQueueRuntime.addNewLog("行为执行器] KEY值拼接完成,KEY值 = " + key);
return new MoveRegularObject(key, colArray[1]); return new MoveRegularObject(key, colArray[1]);
} }
/**
* 线程等待执行器
*
* @param runtimeDetail 要等待的时间,单位毫秒ms
*/
private void waitActionHandler(String runtimeDetail) {
try {
int sleepMills = Integer.parseInt(runtimeDetail);
Thread.sleep(sleepMills);
} catch (InterruptedException e) {
log.error("[线程异常] 线程休眠时发生异常,异常信息 : " + e.getMessage());
} catch (Exception e) {
log.error("[参数/转换异常] 执行行为时参数抓换时发生异常,异常信息 " + e.getMessage());
}
}
/** /**
* 用例行为解析器 * 用例行为解析器
* *
......
package org.matrix.config;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
/**
* CacheConfig. 缓存组件的配置
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/3/10 at 3:12 PM
* Suffering is the most powerful teacher of life.
*/
@Configuration
public class CacheConfig {
@Bean
public Caffeine caffeineConfig(){
return Caffeine.newBuilder().expireAfterWrite(60, TimeUnit.MINUTES);
}
@Bean
public CacheManager cacheManager(Caffeine caffeine) {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
caffeineCacheManager.setCaffeine(caffeine);
return caffeineCacheManager;
}
}
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
<artifactId>mybatis-plus-generator</artifactId> <artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version> <version>3.5.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
......
...@@ -2,14 +2,16 @@ package org.matrix; ...@@ -2,14 +2,16 @@ package org.matrix;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
/** /**
* Hello world! * Hello world!
* *
* @author 27795 * @author 27795
*/ */
@EnableCaching
@SpringBootApplication @SpringBootApplication
public class App { public class WebBootApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(BaseBootApplication.class); SpringApplication.run(BaseBootApplication.class);
} }
......
...@@ -14,6 +14,10 @@ import org.matrix.database.vo.CommonResultObj; ...@@ -14,6 +14,10 @@ import org.matrix.database.vo.CommonResultObj;
import org.matrix.database.vo.MoveAction; import org.matrix.database.vo.MoveAction;
import org.matrix.database.vo.TestCaseData; import org.matrix.database.vo.TestCaseData;
import org.matrix.exception.GlobalException; import org.matrix.exception.GlobalException;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
...@@ -57,8 +61,12 @@ public class TestCaseController { ...@@ -57,8 +61,12 @@ public class TestCaseController {
* @param projectId 项目id * @param projectId 项目id
* @return 分页查询的结果, 用例 * @return 分页查询的结果, 用例
*/ */
@ApiOperation(value = "分页查询用例")
@GetMapping("/{projectId}") @GetMapping("/{projectId}")
@ApiOperation(value = "分页查询用例")
@Cacheable(cacheNames = "casePageCache",
key = "#pageNum + '_' + #pageSize",
condition = "#pageSize != null && #pageNum !=null",
unless = "#result.statusCodeValue != 200")
public ResponseEntity<CommonResultObj<Page<TestCase>>> findPageTestCase( public ResponseEntity<CommonResultObj<Page<TestCase>>> findPageTestCase(
@RequestParam(defaultValue = "10") int pageSize, @RequestParam(defaultValue = "10") int pageSize,
@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "1") int pageNum,
...@@ -79,8 +87,9 @@ public class TestCaseController { ...@@ -79,8 +87,9 @@ public class TestCaseController {
* @param testCaseId 用例id * @param testCaseId 用例id
* @return {@link TestCaseData} * @return {@link TestCaseData}
*/ */
@ApiOperation(value = "根据用例id查,用例以及,用例下的数据组")
@GetMapping("/testCase/{testCaseId}") @GetMapping("/testCase/{testCaseId}")
@ApiOperation(value = "根据用例id查,用例以及,用例下的数据组")
@Cacheable(cacheNames = "caseCache", key = "#testCaseId", condition = "#p0 !=null", unless = "#result.statusCodeValue != 200")
public ResponseEntity<CommonResultObj<TestCaseData>> findByIdTestCaseData(@PathVariable Long testCaseId) { public ResponseEntity<CommonResultObj<TestCaseData>> findByIdTestCaseData(@PathVariable Long testCaseId) {
TestCase byId = testCaseService.getById(testCaseId); TestCase byId = testCaseService.getById(testCaseId);
if (byId == null) { if (byId == null) {
...@@ -101,8 +110,13 @@ public class TestCaseController { ...@@ -101,8 +110,13 @@ public class TestCaseController {
* @param testCaseData 用例以及用例下的数据组 * @param testCaseData 用例以及用例下的数据组
* @return 添加的用例和数据组, 以及是否添加成功的提示信息 * @return 添加的用例和数据组, 以及是否添加成功的提示信息
*/ */
@ApiOperation(value = "添加用例和数据组")
@PostMapping @PostMapping
@ApiOperation(value = "添加用例和数据组")
@Caching(
put = {@CachePut(cacheNames = "caseCache", key = "#result.body.data.testCase.id",
condition = "#p0 !=null", unless = "#result.statusCodeValue != 200")
},
evict = {@CacheEvict(cacheNames = "casePageCache", allEntries = true)})
public ResponseEntity<CommonResultObj<TestCaseData>> insertTestCaseData(@RequestBody TestCaseData testCaseData) { public ResponseEntity<CommonResultObj<TestCaseData>> insertTestCaseData(@RequestBody TestCaseData testCaseData) {
Boolean testCaseBoolean = Optional.of(testCaseService.saveOrUpdate(testCaseData.getTestCase())) Boolean testCaseBoolean = Optional.of(testCaseService.saveOrUpdate(testCaseData.getTestCase()))
.orElseThrow(GlobalException::new); .orElseThrow(GlobalException::new);
...@@ -128,9 +142,16 @@ public class TestCaseController { ...@@ -128,9 +142,16 @@ public class TestCaseController {
* @param testCaseData 用例以及用例下的数据组 * @param testCaseData 用例以及用例下的数据组
* @return {@link TestCaseData} * @return {@link TestCaseData}
*/ */
@ApiOperation(value = "修改用例以及数据组")
@PutMapping @PutMapping
@ApiOperation(value = "修改用例以及数据组")
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Caching(
put = {@CachePut(cacheNames = "caseCache", key = "#result.body.data.testCase.id",
condition = "#p0 !=null", unless = "#result.statusCodeValue != 200")
},
evict = {
@CacheEvict(cacheNames = "casePageCache", allEntries = true, condition = "#p0 != null "),
@CacheEvict(cacheNames = "caseCache", key = "#p0.testCase.id", condition = "#p0 != null ")})
public ResponseEntity<CommonResultObj<TestCaseData>> updateTestCaseData(@RequestBody TestCaseData testCaseData) { public ResponseEntity<CommonResultObj<TestCaseData>> updateTestCaseData(@RequestBody TestCaseData testCaseData) {
Boolean update = Optional.of(testCaseService.updateById(testCaseData.getTestCase())) Boolean update = Optional.of(testCaseService.updateById(testCaseData.getTestCase()))
.orElseThrow(GlobalException::new); .orElseThrow(GlobalException::new);
...@@ -154,9 +175,12 @@ public class TestCaseController { ...@@ -154,9 +175,12 @@ public class TestCaseController {
* @param testCaseId 用例id * @param testCaseId 用例id
* @return 是否删除成功 * @return 是否删除成功
*/ */
@ApiOperation(value = "删除行用例和数据组")
@DeleteMapping("/{testCaseId}") @DeleteMapping("/{testCaseId}")
@ApiOperation(value = "删除行用例和数据组")
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Caching(evict = {
@CacheEvict(cacheNames = "casePageCache", allEntries = true, condition = "#p0 != null "),
@CacheEvict(cacheNames = "caseCache", key = "#testCaseId", condition = "#p0 != null")})
public ResponseEntity<CommonResultObj<MoveAction>> deleteTestCaseData(@PathVariable Long testCaseId) { public ResponseEntity<CommonResultObj<MoveAction>> deleteTestCaseData(@PathVariable Long testCaseId) {
Boolean testCaseBoolean = Optional.of(testCaseService.removeById(testCaseId)) Boolean testCaseBoolean = Optional.of(testCaseService.removeById(testCaseId))
.orElseThrow(() -> new GlobalException(String.format("没有查到指定的用例,你提供的用例id是%d", testCaseId))); .orElseThrow(() -> new GlobalException(String.format("没有查到指定的用例,你提供的用例id是%d", testCaseId)));
......
...@@ -261,7 +261,7 @@ parseVarByName("$name[1]") - 附带了 name 与 index0 ...@@ -261,7 +261,7 @@ parseVarByName("$name[1]") - 附带了 name 与 index0
#### 图片示例 #### 图片示例
![测试用例](/home/hct/MyProjects/kt-keystone/docs/images/zentao/测试用例.png) ![测试用例](docs/images/zentao/测试用例.png)
### 测试结果(**zt_testresult**) ### 测试结果(**zt_testresult**)
...@@ -284,4 +284,4 @@ parseVarByName("$name[1]") - 附带了 name 与 index0 ...@@ -284,4 +284,4 @@ parseVarByName("$name[1]") - 附带了 name 与 index0
#### 图片示例 #### 图片示例
![测试结果](/home/hct/MyProjects/kt-keystone/docs/images/zentao/测试结果.png) ![测试结果](docs/images/zentao/测试结果.png)
\ No newline at end of file \ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论