用户中心:集中提供用户的检索、操作、注册、登录、鉴权
此接口与用户关系紧密,在【用户中心】项目后端新增一个接口——根据标签搜索用户
- AND:允许用户传入多个标签,多个标签都存在才能搜索出来
- OR:允许用户传入多个标签,有任何一个标签存在就能搜索出来
本文演示两种方式进行标签搜索:
- 使用 SQL 查询:通过 Mybatis-plus 的 like 方法实现标签信息 tags 的模糊匹配,优点是实现简单
- 使用内存查询:优点是可以在代码中呈现,使用灵活
1. 使用 MybatisX 插件简化开发(在插件商店直接搜索 MybatisX 点击 install 进行插件的安装)
选择要操作的表,自动生成下列文件,提高开发效率
数据库表 - Java 实体类映射文件:Tag.java
针对 tag 表的数据库业务层操作:TagService.java 和 TagServiceImpl.java
针对 tag 表的数据库持久层操作:TagMapper.java
数据库操作映射 SQL(较复杂的 SQL 语句)文件:TagMapper.xml
2.?编写模糊查询匹配用户标签的业务代码
/**
* 根据标签搜索用户
* @param tagNameList 用户的标签列表
* @return 匹配该标签列表的用户列表
*/
public List<User> searchUsersByTags(List<String> tagNameList) {
// 1. 判断参数是否为空
if (CollectionUtils.isEmpty(tagNameList)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
// 2. 构造查询器
QueryWrapper<User> queryWrapper = new QueryWrapper();
for (String tagName : tagNameList) {
queryWrapper = queryWrapper.like("tags", tagName);
}
// 3. 根据标签列表查找用户
List<User> userList = userMapper.selectList(queryWrapper);
// 4. 返回脱敏后的用户列表
return userList.stream().map(this::getSafetyUser).collect(Collectors.toList());
}
3. 开启 Mybatis-plus 的 SQL 语句日志输出:在项目配置文件 application.yml 中添加下列配置信息
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志
?4. Junit 单元测试
@Test
public void testSearchUsersByTags() {
List<String> tagNameList = new ArrayList<>();
tagNameList.add("java");
tagNameList.add("python");
List<User> userList = userService.searchUsersByTags(tagNameList);
Assertions.assertNotNull(userList);
}
使用 SQL 全量查询出所有用户,在内存中计算过滤符合条件的用户
1. 先查询所有用户,遍历用户并取出用户的标签信息
2. 在内存中判断 tags 是否包含所要求的标签
/**
* 根据标签搜索用户
* @param tagNameList 用户的标签列表
* @return 匹配该标签列表的用户列表
*/
public List<User> searchUsersByTags(List<String> tagNameList) {
// 1. 判断参数是否为空
if (CollectionUtils.isEmpty(tagNameList)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
/**
* 方式二:使用内存查询
*/
// 1. 查询所有用户
QueryWrapper<User> queryWrapper = new QueryWrapper();
List<User> userList = userMapper.selectList(queryWrapper);
Gson gson = new Gson();
return userList.stream().filter(user -> {
// 2. 遍历用户取出标签信息
String tagsStr = user.getTags();
if (StringUtils.isEmpty(tagsStr)) {
return false;
}
// 3. 在内存中判断是否包含要求标签
Set<String> tempTagsNameSet = gson.fromJson(tagsStr, new TypeToken<Set<String>>(){}.getType());
for (String tagName : tagNameList) {
if (!tempTagsNameSet.contains(tagName)) {// 用户标签不包含所要求的标签
return false;
}
}
return true;
}).map(this::getSafetyUser).collect(Collectors.toList());
}
3. Junit 单元测试
4. 判断两种方式的效率
5. 思路扩展:如果两种查询不相上下,时而 SQL 查询快,时而内存查询快,如何选择?
1. 序列化和反序列化:将对象转换为字节流以便在网络中进行传输和存储的过程
2. 几种 JSON 序列化库