提交 66a89030 authored 作者: Matrix's avatar Matrix

feat(书签功能): 增加了保存/更新书签的代码

增加了保存/更新书签的代码,引入了mongodb作为新的存储容器
上级 46828174
......@@ -145,6 +145,17 @@
<version>5.5.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>cn.craccd</groupId>
<artifactId>mongoHelper</artifactId>
<version>0.6.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
......@@ -156,6 +167,11 @@
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.matrix</groupId>
<artifactId>kt-user</artifactId>
</dependency>
</dependencies>
......
package org.matrix.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* CollectionName. mongoDB中的表名
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/5/26 at 5:45 PM
* Suffering is the most powerful teacher of life.
*/
@Getter
@AllArgsConstructor
public enum CollectionName {
/**
* 收藏夹
*/
BOOK_MARK("bookmark","书签");
/**
* DB中的表明
*/
private String name;
/**
* 描述
*/
private String des;
}
package org.matrix.enums;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* ConfigType. 配置类型
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/6/16 at 9:36 PM
* Suffering is the most powerful teacher of life.
*/
@AllArgsConstructor
@Getter
@ApiModel("配置类型")
public enum ConfigType {
/**
* 全局配置,使用该类型代表进行全局的配置替换
*/
ALL("all", "全局配置,使用该类型代表进行全局的配置替换"),
/**
* 书签
*/
BOOK_MARK("bookmark", "书签");
/**
* 配置类型在mongo里的字段名
*/
private final String propertyName;
/**
* 描述
*/
private final String des;
}
package org.matrix.util;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* IdGenerator. 雪花算法的id生成器
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/5/26 at 5:40 PM
* Suffering is the most powerful teacher of life.
*/
@Slf4j
@Component
public class IdGenerator {
/**
* 集群码
*/
private long workerId = 0;
/**
* 机器码
*/
private final long datacenterId = 1;
private final Snowflake snowflake = IdUtil.createSnowflake(workerId, datacenterId);
@PostConstruct
public void init() {
try {
workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
log.info("当前机器的IP: {}, workerId: {}", NetUtil.getLocalhostStr(), workerId);
} catch (Exception e) {
log.error("获取当前机器workerId 异常", e);
workerId = NetUtil.getLocalhostStr().hashCode();
}
}
/**
* 使用默认的workId 和 datacenter
*
*/
public synchronized long nextId() {
return snowflake.nextId();
}
/**
* 使用自定义的workerId 和 datacenter
*
* @param workerId workerId
* @param datacenterId datacenter
*/
public synchronized long snowflakeId(long workerId, long datacenterId) {
return IdUtil.createSnowflake(workerId, datacenterId).nextId();
}
}
......@@ -8,9 +8,9 @@ spring:
datasource:
master: #增加默认数据源
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.100.248:3306/key_stone?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
url: jdbc:mysql://192.168.100.247:3306/key_stone?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: root
password: 123456
# zentao:
# driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.100.247:3306/zentao?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&&zeroDateTimeBehavior=convertToNull
......
package org.matrix;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* BaseTest.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/5/26 at 5:51 PM
* Suffering is the most powerful teacher of life.
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class BaseTest {
}
......@@ -13,6 +13,17 @@
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>cn.craccd</groupId>
<artifactId>mongoHelper</artifactId>
<version>0.6.9</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
......@@ -67,6 +78,11 @@
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>2.0.2</version>
</dependency>
</dependencies>
......
package org.matrix.local.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
import java.util.Map;
/**
* BookmarkConfig.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/6/14 at 4:05 PM
* Suffering is the most powerful teacher of life.
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document
@ApiModel("书签配置")
public class BookmarkConfig {
@ApiModelProperty(value = "项目id",example = "22")
private Long projectId;
/**
* 用例收藏夹id
*/
@ApiModelProperty(value = "用例收藏夹id",example = "[1,2,3]")
private List<Long> hobby;
/**
* 最近几次使用的用例
*/
@ApiModelProperty(value = "最近几次使用的用例",example = "[1,2,3]")
private List<Long> recentUse;
/**
* 自定义书签,key = 书签名, value = 书签里包含的用例id
*/
@ApiModelProperty(value = "最近几次使用的用例")
private Map<String,List<Long>> customDir;
}
package org.matrix.local.entity;
import cn.craccd.mongoHelper.bean.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.data.mongodb.core.mapping.Document;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* UserConfig. 用户的个人配置
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/6/14 at 3:47 PM
* Suffering is the most powerful teacher of life.
*/
@Data
@Document
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ApiModel("用户配置")
public class UserConfig extends BaseModel {
/**
* 用户id
*/
@Min(1)
@NotNull
@ApiModelProperty(value = "用户id",example = "2")
private Long userId;
/**
* 书签配置
*/
@ApiModelProperty(value = "书签配置")
private List<BookmarkConfig> bookmark;
}
package org.matrix.local.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* CollectionName. mongoDB中的表名
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/5/26 at 5:45 PM
* Suffering is the most powerful teacher of life.
*/
@Getter
@AllArgsConstructor
public enum CollectionName {
/**
* 收藏夹
*/
BOOK_MARK("bookmark","书签");
/**
* DB中的表明
*/
private String name;
/**
* 描述
*/
private String des;
}
package org.matrix.local.enums;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* ConfigType. 配置类型
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/6/16 at 9:36 PM
* Suffering is the most powerful teacher of life.
*/
@AllArgsConstructor
@Getter
@ApiModel("配置类型")
public enum ConfigType {
/**
* 全局配置,使用该类型代表进行全局的配置替换
*/
ALL("all", "全局配置,使用该类型代表进行全局的配置替换"),
/**
* 书签
*/
BOOK_MARK("bookmark", "书签");
/**
* 配置类型在mongo里的字段名
*/
private final String propertyName;
/**
* 描述
*/
private final String des;
}
package org.matrix.local.exception;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.validation.ConstraintViolation;
import javax.validation.Path;
import java.util.List;
import java.util.Set;
@ControllerAdvice
public class ExceptionHandle {
......@@ -13,4 +23,20 @@ public class ExceptionHandle {
return ResponseEntity.ok(ImmutableMap.of("message", exception.getMessage()));
}
/**
* 处理 json 请求体调用接口对象参数校验失败抛出的异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity jsonParamsException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
List<String> errorList = Lists.newArrayList();
for (FieldError fieldError : bindingResult.getFieldErrors()) {
String msg = String.format("%s%s;", fieldError.getField(), fieldError.getDefaultMessage());
errorList.add(msg);
}
return ResponseEntity.badRequest().body(ImmutableMap.of("message", e.getMessage(), "data", errorList));
}
}
package org.matrix.local.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mongodb.BasicDBObject;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.User;
import org.matrix.local.entity.UserConfig;
import org.matrix.local.entity.UserProject;
import org.matrix.local.entity.vo.LoginInfo;
import org.matrix.local.entity.vo.UserInfo;
import org.matrix.local.enums.ConfigType;
import org.matrix.local.mapper.KsProjectMapper;
import org.matrix.local.mapper.KsUserMapper;
import org.matrix.local.mapper.KsUserProjectMapper;
import org.matrix.local.util.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
......@@ -31,12 +40,66 @@ import static java.util.Objects.nonNull;
@Service
public class UserService {
public static final String COLLECTION_NAME = "user_config";
@Autowired
private KsUserMapper ksUserMapper;
@Autowired
private KsProjectMapper ksProjectMapper;
@Autowired
private KsUserProjectMapper ksUserProjectMapper;
@Autowired
private MongoTemplate mongoTemplate;
/**
* 如果是用户的第一次配置,即库里没有配置项,则全部保存
* ● 如果已有配置项,分为部分更新和全部更新
* @param userConfig 用户配置
* @param configType 配置类型
* @return 是否更新/插入成功
*/
public boolean upsertConfig(UserConfig userConfig, ConfigType configType) {
Long userId = userConfig.getUserId();
// 首先查询该用户是否存在,不存在就抛出异常
User dbUser = ksUserMapper.selectById(userId);
if (Objects.isNull(dbUser)){
throw new RuntimeException(String.format("保存用户配置 -- 数据库里没有用户id = %d 的用户!", userId));
}
// 如果是用户的第一次配置,即配置库里没有配置项,则全部保存
boolean success;
Query userQuery = Query.query(Criteria.where("userId").is(userId));
boolean isFirst = !mongoTemplate.exists(userQuery, "user_config");
if (isFirst){
mongoTemplate.save(userConfig, COLLECTION_NAME);
success = true;
}else {
// 依据配置类型的不同来更新对应的字段,如果是all,则全部替换
Update update;
switch (configType){
case BOOK_MARK:
log.info("[用户配置] 正在给id = {} 的用户更新<书签>配置,新的书签是 {}",userId,userConfig.getBookmark());
update = Update.update(configType.getPropertyName(), userConfig.getBookmark());
UpdateResult result = mongoTemplate.upsert(userQuery, update, COLLECTION_NAME);
success = true;
break;
case ALL:
log.info("[用户配置] 正在给id = {} 的用户更新<全局>配置,新的配置是 {}",userId,userConfig);
Document doc = new Document();
mongoTemplate.getConverter().write(userConfig,doc);
update = Update.fromDocument(doc);
mongoTemplate.upsert(userQuery, update, COLLECTION_NAME);
success = true;
break;
default:
throw new RuntimeException("用户配置类型错误!当前给出的配置类型是: " + configType);
}
}
return success;
}
/**
* 登录信息缓存Map
......
......@@ -19,16 +19,6 @@
<artifactId>kt-base</artifactId>
</dependency>
<dependency>
<groupId>org.matrix</groupId>
<artifactId>kt-user</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
......
package org.matrix.autotest.controller;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.matrix.database.vo.CommonResult;
import org.matrix.database.vo.CommonResultObj;
import org.matrix.local.entity.BookmarkConfig;
import org.matrix.local.entity.UserConfig;
import org.matrix.local.entity.vo.UserInfo;
import org.matrix.local.enums.ConfigType;
import org.matrix.local.service.UserService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import static org.matrix.database.vo.CommonResult.failed;
import static org.matrix.database.vo.CommonResult.success;
/**
* UserConfigController.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/6/14 at 4:49 PM
* Suffering is the most powerful teacher of life.
*/
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/config")
@Api(tags = "用户配置")
public class UserConfigController {
private final UserService userService;
public UserConfigController(UserService userService) {
this.userService = userService;
}
@ApiOperation("保存书签")
@PostMapping("/bookmarks")
public ResponseEntity<CommonResultObj<Object>> saveBookmark(@RequestBody BookmarkConfig bookmarkConfig){
UserInfo userInfo = userService.findNow();
UserConfig config = new UserConfig(userInfo.getId(), Lists.newArrayList(bookmarkConfig));
boolean isSuccess = userService.upsertConfig(config, ConfigType.BOOK_MARK);
return isSuccess ? success("书签更新成功") : failed("更新失败");
}
}
......@@ -3,6 +3,9 @@ server:
spring:
application:
name: keystone
data:
mongodb:
uri: mongodb://192.168.100.247:27017/key_stone
datasource:
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
......
......@@ -106,6 +106,13 @@
<artifactId>freemaker</artifactId>
<version>1.8.1</version>
</dependency>
<!--参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
<!--加入打包的配置 -->
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论