本文开发一用户注册与登录的后端java平台。开发完后的网页效果:http://user-front.66bond.com/
后端主要提供用户的注册、查询、删除等操作。使用到的开发工具:
- IDEA2021; 关注公众号”青椒工具”,发送”IDEA”,获取windows下的IDEA安装包
- mysql 5.7;关注公众号”青椒工具”,发送”mysql”,获取windows下的mysql5.7安装包;
前面一章我们实现了controller中的login和register接口,并且测试通过。
本章我们用户管理的接口:查找用户和删除用户。
1、整体逻辑
查找用户是根据用户的账户名查询数据库,如果用户没有提供用户名,则返回所有用户的数据;
删除用户,前端给出用户的id,然后查询数据库删除,注意此处的删除是逻辑删除;
上述两个操作的接口都要”鉴权”,只有管理员才有权限调用上述这两个接口;一般用户没有权限调用;
所以,我们的接口代码中要判断当前登录用户是否是admin用户。
2、代码框架:
在/com.tfzhang.backend/controller/中新建UserController.java文件,代码结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @RestController @RequestMapping("/user") public class UserController { @Resource private UserService userService;
@GetMapping("/search") public List<User> searchUsers(String userName, HttpServletRequest request) { }
@PostMapping("/delete") public Boolean deleteUser(@RequestBody long id, HttpServletRequest request) { }
|
因为searchUsers是GET类型访问,所以采用的标签是 @GetMapping,同时参数中也不需要加@Requestbody标签。
两个方法的参数中都要添加request,因为要判断用户的权限。
3、接口代码实现:
我们先从searchUsers入手开始编写代码,要解决的两个问题:
- 根据userName查询数据库;
- 鉴权,判断当前用户是否为管理员;
我们先来看下如何鉴权,用户在login的时候,服务器端会设置session,其中我们要将userRole这个参数也设置进去,即在UserServiceImpl.java中的getSafetyUser()方法中加入如下代码:
1
| user.setUserRole(originalUser.getUserRole());
|
当用户访问searchUsers接口时,将request的session属性中的userRole变量取出来,判读是否为1,就可以判断当前用户是否为admin用户,代码片段如下:
1 2 3 4 5
| Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE); User user = (User) userObj; if(user == null || user.getUserRole() != 1){ return new ArrayList<>(); }
|
在我们的数据库中userRole为1则表示管理员,否则是普通用户。
如果是管理员,接下来可以使用mybatis-plus的queryWrapper对象访问数据库,代码片段如下:
1 2 3 4 5 6
| QueryWrapper<User> queryWrapper = new QueryWrapper<>(); if(StringUtils.isNotBlank(username)){ queryWrapper.like("username", username); } List<User> userList = userService.list(queryWrapper); List<User> list = userList.stream().map(item -> userService.getSafetyUser(item)).collect(Collectors.toList());
|
queryWrapper.like(),对于mybatis-plus而言,生成的SQL查询中包含一个条件,该条件会对username
字段进行模糊匹配。
如果username为空,则查询全部用户,并采用list返回;最后一行代码的主要作用是是对list中的每一个user进行脱敏处理。
我们将上述两个代码片段整合,获得searchUsers的完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @GetMapping("/search") public List<User> searchUsers(String username, HttpServletRequest request){
Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE); User user = (User) userObj; if(user == null || user.getUserRole() != 1){ return new ArrayList<>(); }
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); if(StringUtils.isNotBlank(username)){ queryWrapper.like("username", username); } List<User> userList = userService.list(queryWrapper); List<User> list = userList.stream().map(item -> userService.getSafetyUser(item)).collect(Collectors.toList()); return list; }
|
此处我们将原来应该写在service包的业务代码一并写到接口这边,主要原因是业务很简单,就直接写在controller这层。
==代码可优化的地方==:
- 上述代码中出现常量1,可以提取到constant包中;
- 上述判断是否管理员的代码,是一个常用的操作,值得提取出来封装为一个方法;
我们在constant包的UserConstant.java中添加:
将判断admin的语句提取为UserController.java中单独的方法isAdmin():
1 2 3 4 5 6 7 8 9
| private boolean isAdmin(HttpServletRequest request){ Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE); User user = (User) userObj;
if(user != null && user.getUserRole() == ADMIN_ROLE){ return true; } return false; }
|
经过上述的优化,searchUsers的完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @GetMapping("/search") public List<User> searchUsers(String username, HttpServletRequest request){
if(!isAdmin(request)){ return new ArrayList<>(); }
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); if(StringUtils.isNotBlank(username)){ queryWrapper.like("username", username); } List<User> userList = userService.list(queryWrapper); List<User> list = userList.stream().map(item -> userService.getSafetyUser(item)).collect(Collectors.toList()); return list; }
|
参照searchUsers,我们再完成deleteUser的代码编写:
1 2 3 4 5 6 7 8 9 10 11
| @PostMapping("/delete") public boolean deleteUser(@RequestBody long id, HttpServletRequest request){ if(!isAdmin(request)){ return false; } if(id <= 0){ return false; } boolean res = userService.removeById(id); return res; }
|
mybatis-plus自带按id删除的方法removeById,所以不需要我们自己来写,并且这个removeById操作是逻辑删除。
4、代码测试
测试的步骤与login和register接口的测试步骤相同;
注意在测试search接口时,先要采用login接口登录获取session,然后还要保证登录的账户的userRole被设置为1。
按照上述步骤,我们的search接口测试成功:在不输入username的情况下,的确获取到所有脱敏后的用户信息,测试通过。
现在测试delete接口,我们采用如下的request:
1 2 3 4 5 6
| POST http: Content-Type: application/json
{ "id": "1" }
|
访问后出现如下的错误:
1
| Required request parameter 'id' for method parameter type long is not present
|
后端没有拿到id这个参数,而我们的request中的确已经给出这个数据。我们的id按字符串对形式提供,猜测后端没有那么智能将1这个整形数据直接提取出来。那么我们将deleteUser接口重写,书写代码提取其中的id整型数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @PostMapping("/delete") public boolean deleteUser(@RequestBody Map<String, String> dataBody, HttpServletRequest request){ if(!isAdmin(request)){ return false; } String idstr = dataBody.get("id"); if(idstr==null || idstr.isEmpty()){ return false; } long id=-1; try{ id = Long.parseLong(idstr); }catch (NumberFormatException e){ return false; }
if(id <= 0){ return false; } boolean res = userService.removeById(id); return res; }
|
保存重新启动测试,这次对了,返回的值为true,图1所示,再查看数据库id=1的数据的isDelete位的确被置为1,说明逻辑删除正确执行。

图1 deleteUser测试成功
之前还有一遗漏的点,即session没有设置有效时间,我们在application.yml中添加配置:
1 2 3
| session: timeout: 86400
|
5、参考资料:
本文参考自如下知识星球中的视频教程,更多的完整的相关视频教程,见如下的收费知识星球,近3万人的学习社区,
编程有人同行,学习不再迷茫:
