当前位置: 首页 > news >正文

论坛系统(4)

用户详情

获取用户信息

实现逻辑

⽤⼾提交请求,服务器根据是否传⼊Id参数决定返回哪个⽤⼾的详情

1. 不传⽤⼾Id,返回当前登录⽤⼾的详情(从session获取)

2. 传⼊⽤⼾Id,返回指定Id的⽤⼾详情(根据用户id去查)

俩种方式获得用户信息

参数要求

参数名描述类型默认值条件
id⽤⼾Idlong可以为空

接口规范

// 请求
GET /user/info HTTP/1.1
GET /user/info?id=1 HTTP/1.1
// 响应
HTTP/1.1 200
Content-type: applicatin/json
{
"code": 0,
"message": "成功",
"data": {
"id": 25,
"username": "user223",
"nickname": "user223",
"phoneNum": null,
"email": null,
"gender": 1,
"avatarUrl": null,
"articleCount": 0,
"isAdmin": 0,
"state": 0,
"createTime": "2023-04-08 15:06:10",
"updateTime": "2023-04-08 15:06:10"}}

用户帖子列表

实现逻辑

对应版块中显⽰的帖⼦列表以发布时间降序排列不传⼊版块Id返回所有帖⼦

1. ⽤⼾点击某个版块或⾸⻚时,将版块Id做为参数向服务器发送请求

2. 服务器接收请求,并获取版块Id,查询对应版块下的所有帖⼦

3. 返回查询结果

参数要求

参数名描述类型默认值条件
boardId版块IdLong可为空

接口规范

// 请求
// 返回指定版块下的帖⼦列表
GET http://127.0.0.1:58080/article/getAllByBoardId?boardId=1 HTTP/1.1(以传入的id为准)
// 返回所有的帖⼦列表
GET http://127.0.0.1:58080/article/getAllByBoardId HTTP/1.1 (从session中获取当前登录用户的Id)
// 响应
HTTP/1.1 200
Content-Type: application/json
{
"code": 0,
"message": "成功",
"data": [
{
"id": 17,
"boardId": 1,
"userId": 1,
"title": "测试删除",
"visitCount": 8,
"replyCount": 1,
"likeCount": 1,
"state": 0,
"createTime": "2023-07-05 04:10:46",
"updateTime": "2023-07-05 11:22:43",
"board": {
"id": 1,
"name": "Java"
},
"user": {
"id": 1,
"nickname": "bitboy",
"phoneNum": null,
"email": null,
"gender": 1,
"avatarUrl": null
},
"own": false
}}]

后端代码实现

1. 在Mapper.xml中编写SQL语句

需要定义一个根据用户Id查询的SQL


2. 在Mapper.java中定义方法

在ArticleMapper里面定义selectByUserId方法


3. 定义Service接口

在IArticleService里面定义selectByUserId接口


4. 实现Service接口

实现步骤

1> 对用户id进行非空校验

2> 调用service, 根据userId校验用户是否存在

3> 调用DAO根据用户id查询用户的帖子

具体代码

   @Overridepublic List<Article> selectByUserId(Long userId) {// 对userId进行非空校验if (userId == null || userId <= 0) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 校验用户是否存在User user = userService.selectById(userId);if (user == null) {// 打印日志log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString() + ", user id = " + userId);// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}// 调用DAOList<Article> articles = articleMapper.selectByUserId(userId);// 返回结果return articles;}

5. 单元测试

返回帖子列表


6. Controller实现方法并对外提供API接口

实现步骤

1> 判断userId是否为空, 是空的就去获取登录用户的userId

2> 调用Service,通过userId查询对应的作者的帖子

具体代码

    @Operation(summary = "获取用户的帖子列表")@GetMapping("/getAllByUserId")public AppResult<List<Article>> getAllByUserId(HttpServletRequest request,@Parameter(description = "用户Id") @RequestParam(value = "userId",required = false) Long userId){// 如果UserId为空, 那么就从sessionId获取当前登录的用户Idif(userId == null){// 获取SessionHttpSession session = request.getSession(false);// 获取User对象User user = (User) session.getAttribute(AppConfig.USER_SESSION);userId = user.getId();}// 调用ServiceList<Article> articles = articleService.selectByUserId(userId);// 返回结果return AppResult.success(articles);}

7. 测试API接口

不管传不传userId都能查询帖子信息

前端代码实现

构造ajax请求

实现结果

个人中心

修改个人信息

实现逻辑

只对⽤⼾的基本信息做修改,不包括密码与头像,修改密码与修改头像提供单独的修改接⼝

1. ⽤⼾打开找修改个⼈信息⻚⾯

2. 填⼊要修改的内容并提交服务器

3. 服务器获取登录⽤⼾的Id(从session中获取),并根据提交的内容修改数据

4. 返回成功或失败,如果成功返回更新后的个⼈信息

5. 浏览器刷新个⼈信息

参数要求

后端可以提供一个统一的接口, 更具用户提供参数来封装要修改的对象

参数名描述类型默认值条件
username⽤⼾名(⽤于登录)String可选,唯⼀,校验是否存在
nickname昵称String可选,
gender性别Byte可选,0⼥, 1男,2保密
email邮箱String可选
phoneNum电话String可选
remark个⼈简介String可选

接口规范

// 请求
POST http://127.0.0.1:58080/user/modifyInfo HTTP/1.1
Content-Type: application/x-www-form-urlencoded
id=1&nickname=bitboy&gender=1&email=bitboy%40bit.com&phoneNum=18888888888&remar
k=%E6%88%91%E6%98%AF%E4%B8%80%E4%B8%AA%E4%BC%98%E7%A7%80%E7%9A%84%E5%A5%BD%E9%9
D%92%E5%B9%B4
// 响应
HTTP/1.1 200
Content-Type: application/json
{
"code": 0,
"message": "成功",
"data": {
"id": 1,
"username": "bitboy",
"nickname": "bitboy",
"phoneNum": "18888888888",
"email": "bitboy@bit.com",
"gender": 1,
"avatarUrl": null,
"articleCount": 1,
"isAdmin": 1,
"remark": "我是⼀个优秀的好⻘年",
"state": 0,
"createTime": "2023-06-24 11:59:15",
"updateTime": "2023-07-09 03:05:23"
}
}

后端代码编写

1. 在Mapper.xml中编写SQL语句

2. 在Mapper.java中定义方法

直接使用动态SQL,已经生成


3. 定义Service接口

IUserService定义modifyInfo接口


4. 实现Service接口

实现modifyInfo

实现步骤

1> 对用户进行非空校验

2> 根据用户id查询用户是否存在(不存在直接抛异常)

3> 定义一个标志位

4> 设置一个对象,用来动态更新sql的时候对修改的属性进行操作

5> 对用户名进行校验是否要更改(必须验证时唯一值)

6> 对其他参数校验是否要更改

7> geng'ju

具体代码

    @Overridepublic void modifyInfo(User user) {// 1. 非空校验if (user == null || user.getId() == null || user.getId() <= 0) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 2. 根据用户id查询校验用户是否存在User existsUser = userMapper.selectByPrimaryKey(user.getId());// 如果查不到, 就直接抛异常if (existsUser == null) {// 打印日志log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}// 3. 定义一个标志位boolean checkAttr = false;// false表示没有校验通过// 4. 定义一个专门用来更新的对象, 防止用户传入的User对象设置了其他属性// 当使用动态SQL进行更新的时候, 覆盖了没有经过校验的字段User updateUser = new User();// 5. 设置用户IdupdateUser.setId(user.getId());// 6. 对每一个参数进行校验并赋值if (!StringUtil.isEmpty(user.getUsername())&& !user.getUsername().equals(existsUser.getUsername())) {// 用户名不为空并且修改后的用户名和原先用户名不一样// 更新用户名之前, 需要进行唯一性校验, 去表里面找有没有修改后的用户User checkUser = userMapper.selectByUserName(user.getUsername());if (checkUser != null) {// 用户已存在log.warn(ResultCode.FAILED_USER_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));}// 数据库中没有找到相应的用户, 表示可以修改用户名updateUser.setUsername(user.getUsername());// 更新标志位checkAttr = true;}// 7. 校验昵称if (!StringUtil.isEmpty(user.getNickname())&& !user.getNickname().equals(existsUser.getNickname())) {// 设置昵称updateUser.setNickname(user.getNickname());// 更新标志位checkAttr = true;}// 8. 校验性别if (user.getGender() != null && user.getGender() != existsUser.getGender()) {// 设置性别updateUser.setGender(user.getGender());// 合法性校验if (updateUser.getGender() > 2 || updateUser.getGender() < 0) {updateUser.setGender((byte) 2);}// 更新标志位checkAttr = true;}// 9. 校验邮箱if (!StringUtil.isEmpty(user.getEmail())&& !user.getEmail().equals(existsUser.getEmail())) {// 设置邮箱updateUser.setEmail(user.getEmail());// 更新标志位checkAttr = true;}// 9. 校验电话号码if (!StringUtil.isEmpty(user.getPhoneNum())&& !user.getPhoneNum().equals(existsUser.getPhoneNum())) {// 设置电话号码updateUser.setPhoneNum(user.getPhoneNum());// 更新标志位checkAttr = true;}// 10. 校验个人简介if (!StringUtil.isEmpty(user.getRemark())&& !user.getRemark().equals(existsUser.getRemark())) {// 设置电话号码updateUser.setRemark(user.getRemark());// 更新标志位checkAttr = true;}// 11. 根据标志位来决定是否可以执行更新if (checkAttr == false) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 12. 调用DAOint row = userMapper.updateByPrimaryKeySelective(updateUser);if (row != 1) {log.warn(ResultCode.FAILED.toString() + ", 受影响的行数不等于 1 .");throw new ApplicationException(AppResult.failed(ResultCode.FAILED));}}

5. 单元测试

修改成功


6. Controller实现方法并对外提供API接口

实现步骤

1> 接受参数, 对参数进行非空校验

2> 从session中获取要修改的用户Id

3> 封装更新的User对象

4> 调用Service中的方法

5> 查询最新的用户信息

6> 把最新的用户信息设置到session中

7> 返回结果

具体代码

// 修改个人信息@Operation(summary = "修改个人信息")@GetMapping("/modifyInfo")public AppResult modifyInfo(HttpServletRequest request,@Parameter(description = "用户名") @RequestParam(value = "username", required = false) String username,@Parameter(description = "昵称") @RequestParam(value = "nickname", required = false) String nickname,@Parameter(description = "性别") @RequestParam(value = "gender", required = false) Byte gender,@Parameter(description = "邮箱") @RequestParam(value = "email", required = false) String email,@Parameter(description = "电话号") @RequestParam(value = "phoneNum", required = false) String phoneNum,@Parameter(description = "个人简介") @RequestParam(value = "remark", required = false) String remark) {// 1. 接受参数// 2. 对参数做非空校验(全部都为空,就返回错误信息)if (StringUtil.isEmpty(username) && StringUtil.isEmpty(nickname)&& StringUtil.isEmpty(email) && StringUtil.isEmpty(phoneNum)&& StringUtil.isEmpty(remark) && gender == null) {// 返回错误信息return AppResult.failed("请输入要修改的内容");}// 3. 从session中获取用户IdHttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.USER_SESSION);// 4. 封装更新的User对象User updateUser = new User();updateUser.setId(user.getId()); // 用户IdupdateUser.setUsername(username); // 用户名updateUser.setNickname(nickname); // 昵称updateUser.setGender(gender); // 性别updateUser.setEmail(email); // 邮箱updateUser.setPhoneNum(phoneNum); // 电话updateUser.setRemark(remark); // 个人简介// 5. 调用Service中的方法userService.modifyInfo(updateUser);// 6. 查询最新的用户信息user = userService.selectById(user.getId());// 7. 把最新的用户信息设置到session中session.setAttribute(AppConfig.USER_SESSION,user);// 8. 返回结果return AppResult.success(user);}

7. 测试API接口

前端代码编写

编写ajax请求

最终的结果

修改密码

实现逻辑

• 为修改密码提供⼀个单独的接⼝及操作⻚⾯
1. ⽤⼾打开修改密码⻚⾯

2. 输⼊原密码、新密码、重复新密码并提交服务器

3. 服务器校验原密码是否正确

4. 原密码校验通过更新密码

5. 返回成功或失败

参数要求

参数名描述类型默认值条件
oldPassword原密码String必须
newPassword新密码String必须
passwordRepea t确认新密码String必须,与新密码相同

接口规范

// 请求
POST http://127.0.0.1:58080/user/modifyPwd HTTP/1.1
Content-Type: application/x-www-form-urlencoded
id=1&oldPassword=123456&newPassword=123456&passwordRepeat=123456
// 响应
HTTP/1.1 200
Content-Type: application/json
{
"code": 0,
"message": "成功",
"data": null
}

后端代码实现

1. 在Mapper.xml中编写SQL语句

2. 在Mapper.java中定义方法

1.2实现过


3. 定义Service接口

4. 实现Service接口

实现步骤

1> 对id进行非空校验

2> 根据id去数据库查询用户的信息, 并校验用户是否存在

3> 校验老密码是否正确(取出老盐, 然后和老密码进行md5加密)

4> 然后老密码和用户密码进行比对

5> 构造新的盐和新密码

6> 构造要更新的对象

7> 调用DAO

具体代码

 /*** 修改密码* @param id 用户Id* @param newPassword 新密码* @param oldPassword 老密码*/@Overridepublic void modifyPassword(Long id, String newPassword, String oldPassword) {// 对id进行非空校验if (id == null || id <= 0 || StringUtil.isEmpty(newPassword) || StringUtil.isEmpty(oldPassword)) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 查询用户的信息User user = userMapper.selectByPrimaryKey(id);// 校验用户是否存在if (user == null || user.getDeleteState() == 1) {// 打印日志log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}// 校验老密码是否正确// 对老密码进行加密, 获取密文: 获取旧的盐, 然后让旧的盐和旧的密码拼接, 然后用md5进行加密String oldEncryptPassword = MD5Util.md5Salt(oldPassword,user.getSalt());// 和用户当前的密码进行比较if(!oldEncryptPassword.equalsIgnoreCase(user.getPassword())){// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 生成一个新的盐String salt = UUIDUtil.UUID_32();// 生成新密码的密文 ((明文)md5加密+扰动字符)md5加密String encryptPassword = MD5Util.md5Salt(newPassword,salt);// 构造要更新的对象User updateUser = new User();updateUser.setId(user.getId()); // 用户idupdateUser.setSalt(salt);// 新生成的盐updateUser.setPassword(encryptPassword); // 新密码对应的密文Date date = new Date();updateUser.setUpdateTime(date); // 更新时间// 调用DAOint row = userMapper.updateByPrimaryKeySelective(updateUser);if (row != 1) {log.warn(ResultCode.FAILED.toString() + ", 受影响的行数不等于 1 .");throw new ApplicationException(AppResult.failed(ResultCode.FAILED));}}


5. 单元测试


6. Controller实现方法并对外提供API接口

实现逻辑

1> 校验新密码和确认密码是否相同

2> 获取当前登录的用户信息

3> 调用Service

4> 销毁session 回到登录页面重新登录

5> 返回结果

具体代码

    @Operation(summary = "修改密码")@PostMapping("/modifyPwd")public AppResult modifyPassword(HttpServletRequest request,@Parameter(description = "原密码") @RequestParam("oldPassword")@NonNull String oldPassword,@Parameter(description = "新密码") @RequestParam("newPassword")@NonNull String newPassword,@Parameter(description = "确认密码") @RequestParam("passwordRepeat")@NonNull String repeatPassword){// 1. 校验新密码和确认密码是否相同if(!newPassword.equalsIgnoreCase(repeatPassword)){// 返回错误描述return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME);}// 2. 获取当前登录的用户信息HttpSession session = request.getSession(false);User user =(User) session.getAttribute(AppConfig.USER_SESSION);// 3. 调用ServiceuserService.modifyPassword(user.getId(),newPassword,oldPassword);// 4. 销毁session 回到登录页面重新登录if (session != null) {session.invalidate();}// 5. 返回结果return AppResult.success();}

7. 测试API接口

站内信

发送

实现逻辑

1. 在⽬录⽤⼾详情界⾯,点击发送站内信接钮,进⼊编辑⻚⾯

2. 编写站内信内容,点击发送按钮

3. 提⽰发送结果

参数要求

参数名描述类型条件默认值
receiveUserId接收⽤⼾IdLong必须
content站内信内容String必须

接口规范

// 请求
POST http://127.0.0.1:58080/message/send HTTP/1.1
Content-Type: application/x-www-form-urlencoded
receiveUserId=2&content=%E4%BD%A0%E5%A5%BD%E5%95%8A
// 响应
HTTP/1.1 200
Content-Type: application/json
{
"code": 0,
"message": "成功",
"data": null
}

后端代码实现

1. 在Mapper.xml中编写SQL语句
2. 在Mapper.java中定义方法

实现过了


3. 定义Service接口


4. 实现Service接口

实现逻辑

1> 对Message进行非空校验

2> 根据message的id查询接收者是否存在

3> 设置默认值

4> 设置创建时间和更新时间

5> 调用DAO,插入message

具体代码

package org.xiaobai.forum.service.impl;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.xiaobai.forum.common.AppResult;
import org.xiaobai.forum.common.ResultCode;
import org.xiaobai.forum.dao.MessageMapper;
import org.xiaobai.forum.exception.ApplicationException;
import org.xiaobai.forum.model.Message;
import org.xiaobai.forum.model.User;
import org.xiaobai.forum.service.IMessageService;
import org.xiaobai.forum.service.IUserService;
import org.xiaobai.forum.utils.StringUtil;import javax.annotation.Resource;
import java.util.Date;@Service
@Slf4j
public class MessageServiceImpl implements IMessageService {@Resourceprivate MessageMapper messageMapper;@Resourceprivate IUserService userService;@Overridepublic void create(Message message) {// 非空校验if (message == null || message.getPostUserId() == null || message.getReceiveUserId() == null|| StringUtil.isEmpty(message.getContent())) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 校验接收者是否存在User user = userService.selectById(message.getReceiveUserId());if (user == null || user.getDeleteState() == 1) {// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 设置默认值message.setState((byte) 0);message.setDeleteState((byte) 0);// 设置创建与更新时间Date date = new Date();message.setCreateTime(date);message.setUpdateTime(date);// 调用DAOint row = messageMapper.insertSelective(message);if (row != 1) {log.warn(ResultCode.FAILED_CREATE.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));}}
}

5. 单元测试

6. Controller实现方法并对外提供API接口

实现逻辑

1> 获取当前登录的用户信息

2> 判断当前登录用户的状态, 如果是禁言是不能发送站内信

3> 判断发送人是不是作者(不能自己给自己发送站内信)

4> 根据接收者id校验接收者是否存在

5> 封装发送对象

6> 调用Service, 把message传进去

7> 返回结果

具体代码

package org.xiaobai.forum.controller;import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xiaobai.forum.common.AppResult;
import org.xiaobai.forum.common.ResultCode;
import org.xiaobai.forum.config.AppConfig;
import org.xiaobai.forum.model.Message;
import org.xiaobai.forum.model.User;
import org.xiaobai.forum.service.IMessageService;
import org.xiaobai.forum.service.IUserService;import javax.annotation.Resource;@Tag(name ="站内信接口",description = "给其他用户发送信息")
@RestController
@RequestMapping("/message")
@Slf4j
public class MessageController {@Resourceprivate IMessageService messageService;@Resourceprivate IUserService userService;@Operation(summary = "发送站内信")@PostMapping("/send")public AppResult send(HttpServletRequest request,@Parameter(description = "接收者Id")@RequestParam("receiveUserId") @NonNull Long receiveUserId,@Parameter(description = "内容")@RequestParam("content")@NonNull String content){// 获取当前登录的用户信息HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.USER_SESSION);// 1. 当前登录用户的状态, 如果是禁言状态是不能发送站内信if(user.getState() == 1){// 返回用户状态异常return AppResult.failed(ResultCode.FAILED_USER_BANNED);}// 2. 不能给自己发送站内信if(user.getId() == receiveUserId){return AppResult.failed("不能给自己发送站内信");}// 3. 校验接收者是否存在User receiveUser = userService.selectById(receiveUserId);// 判断接收者状态是否正常if (receiveUser == null || receiveUser.getDeleteState() == 1) {// 返回接收者状态不正常return AppResult.failed("接收者状态异常");}// 4. 封装发送对象Message message = new Message();message.setPostUserId(user.getId());// 发送者Idmessage.setReceiveUserId(receiveUserId);// 接收者Idmessage.setContent(content);// 站内信内容// 5.调用ServicemessageService.create(message);// 6. 返回结果return AppResult.success("发送成功");}
}

7. 测试API接口

未读数

实现逻辑

查询当前登录⽤⼾的未读站内信数量(直接从session中获取用户的Id)

接口规范

// 请求
GET http://127.0.0.1.41:58080/message/getUnreadCount HTTP/1.1
// 响应
HTTP/1.1 200
Content-Type: application/json
{"code":0,"message":"成功","data":1}

后端代码实现

1. 在Mapper.xml中编写SQL语句

根据用户Id查询该用户的未读数量 state = 0(0表示未读)


2. 在Mapper.java中定义方法

3. 定义Service接口

4. 实现Service接口

实现逻辑

1> 对receiverUserId进行参数非空校验

2> 直接调用DAO,通过receiverUserId查询该用户未读的信息数

3> 检查count

具体代码

    /*** 根据用户Id查询该用户的未读数* @param receiveUserId 用户id* @return 未读数*/@Overridepublic Integer selectUnreadCount(Long receiveUserId) {// 参数非空校验if(receiveUserId == null || receiveUserId <=0){// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 直接调用DAOInteger count = messageMapper.selectUnreadCount(receiveUserId);// 检查countif (count == null) {log.warn(ResultCode.ERROR_SERVICES.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));}// 返回结果return count;}

5. 单元测试

6. Controller实现方法并对外提供API接口

实现逻辑

1> 根据session获取当前登录的用户

2> 调用Service, 根据用户Id获取用户站内信未读数

3> 返回结果集

具体代码

    @Operation(summary = "获取未读数")@GetMapping("/getUnreadCount")public  AppResult<Integer> getUnreadCount(HttpServletRequest request){// 1. 获取当前登录的用户HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.USER_SESSION);// 2. 调用ServiceInteger count = messageService.selectUnreadCount(user.getId());// 当前登录的id就是接收者id// 3. 返回结果return AppResult.success(count);}


7. 测试API接口

列表

实现逻辑

⽤⼾访问API,服务器响应当前登录⽤⼾的站内信

接口规范

// 请求
GET http://127.0.0.1:58080/message/getAll HTTP/1.1
// 响应
HTTP/1.1 200
Content-Type: application/json
{
"code": 0,
"message": "成功",
"data": [{
"id": 11,
"postUserId": 32, 
"receiveUserId": 3,
"content": "真的可以发出去吗\n",
"state": 2,
"createTime": "2023-06-20 11:21:09",
"updateTime": "2023-06-25 11:24:38",
"postUser": {
"id": 32,
"nickname": "ljl",
"phoneNum": null,
"email": null,
"gender": 2,
"avatarUrl": null
}
}]}

后端代码实现

1. 在Mapper.xml中编写SQL语句
 
2. 在Mapper.java中定义方法

3. 定义Service接口

4. 实现Service接口

实现逻辑

1> 参数非空校验

2> 调用DAO

3> 返回结果

具体代码

    @Overridepublic List<Message> selectByReceiveUserId(Long receiveUserId) {// 参数非空校验if(receiveUserId == null || receiveUserId <=0){// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 调用DAOList<Message> messages = messageMapper.selectByReceiveUserId(receiveUserId);// 返回结果return messages;}

5. 单元测试

6. Controller实现方法并对外提供API接口

具体逻辑

1> 获取当前登录的用户

2> 根据用户的id获取用户的站内信列表

3> 返回结果

代码编写

    @Operation(summary = "查询用户的所有站内信")@GetMapping("/getAll")public AppResult<List<Message>> getAll(HttpServletRequest request){// 1. 获取当前登录的用户HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.USER_SESSION);// 2. 调用ServiceList<Message> messages = messageService.selectByReceiveUserId(user.getId());// 3. 返回结果return AppResult.success(messages);}

7. 测试API接口

更新状态

实现逻辑

1. ⽤⼾点击站内信,显⽰详情⻚⾯

2. 更新未读状态的站内信为已读

参数要求

参数名描述类型条件默认值
id站内信Idlong必须

接口规范

// 请求
POST http://127.0.0.1:58080/message/markRead HTTP/1.1
Content-Type: application/x-www-form-urlencoAded
id=1
// 响应
HTTP/1.1 200
Content-Type: application/json
{"code": 0,
"message": "成功",
"data": null
}

后端代码实现

1. 在Mapper.xml中编写SQL语句
2. 在Mapper.java中定义方法

之前写了


3. 定义Service接口

4. 实现Service接口

实现逻辑

1> 对id, state进行校验

2> 动态更新, 构造更新对象

3> 调用DAO,更新是否已读

具体代码

@Overridepublic void updateStateById(Long id, Byte state) {// 对id进行非空校验, state: 0 未读 1 已读 2 已回复if (id == null || id <= 0 || state < 0 || state > 2) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 更新帖子数失败// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 构造更新对象Message updateMessage = new Message();updateMessage.setId(id);updateMessage.setState(state);Date date = new Date();updateMessage.setUpdateTime(date);// 调用DAOint row = messageMapper.updateByPrimaryKeySelective(updateMessage);if(row !=1){log.warn(ResultCode.ERROR_SERVICES.toString());throw  new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));}}


5. 单元测试


6. Controller实现方法并对外提供API接口

实现逻辑

1> 根据Id查询站内信,并且查询站内信是否存在

2> 判断站内信是不是自己

3> 调用Service把id所对应的Message更新为已读状态

具体代码

    @Operation(summary = "更新为已读")@PostMapping("/markedRead")public AppResult markedRead(HttpServletRequest request,@Parameter(description = "站内信Id") @RequestParam("id") @NonNull Long id) {//1. 根据Id查询站内信Message message = messageService.selectById(id);//2. 站内信是否存在if (message == null || message.getDeleteState() == 1) {// 返回错误信息return AppResult.failed(ResultCode.FAILED_MESSAGE_NOT_EXISTS);}//3. 站内信是不是自己的HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.USER_SESSION);// 判断站内信的收件人是不是当前的登录if (user.getId() != message.getReceiveUserId()) {// 返回错误信息return AppResult.failed(ResultCode.FAILED_FORBIDDEN);}// 调用Service, 把状态更新为已读messageService.updateStateById(id,(byte)1);// 返回结果return AppResult.success();}

7. 测试API接口

回复

实现逻辑

1. ⽤⼾在站内信详情⻚⾯点击回复按钮,显⽰回复区

2. 填写回复内容并提交到服务器

3. ⽤⼾不能回复接收者不是⾃⼰的站内信

4. 站内信状态置为已回复(并且要在数据库中新增一条站内信记录, 俩个数据的修改操作在一个业务逻辑中, 因此要用事务进行管理)

参数要求

参数名描述类型条件默认值
repliedId(要回复的站内信id)站内信IdLong必须
content内容String必须

接口规范

// 请求
POST http://127.0.0.1:58080/message/reply HTTP/1.1
Content-Type: application/x-www-form-urlencoded
repliedId=1&receiveUserId=2&content=%E4%BD%A0%E5%A5%BD%E5%95%8A
// 响应
HTTP/1.1 200
Content-Type: application/json
{
"code": 0,
"message": "成功",
"data": null
}

后端代码实现

1. 在Mapper.xml中编写SQL语句
2. 在Mapper.java中定义方法
3. 定义Service接口

4. 实现Service接口

实现步骤

1> 对repliedId进行非空校验

2> 校验repliedId是不是存在

3> 更新状态为已读

4> 回复的内容写入数据库

具体代码

    /*** 回复站内信* @param repliedId 要回复的站内信Id* @param message 回复的对象*/@Overridepublic void reply(Long repliedId, Message message) {// 对repliedId进行非空校验if (repliedId == null || repliedId <= 0) {// 打印日志log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));}// 校验repliedId是不是存在Message existsMessage  = messageMapper.selectByPrimaryKey(repliedId);// 信息是否存在if (existsMessage == null || existsMessage.getDeleteState() == 1) {// 打印日志log.warn(ResultCode.FAILED_MESSAGE_NOT_EXISTS.toString());// 抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_MESSAGE_NOT_EXISTS));}// 更新状态为已回复updateStateById(repliedId,(byte)2);// 回复的内容写入数据库create(message);}


5. 单元测试


6. Controller实现方法并对外提供API接口

实现步骤

1> 校验当前登录用户的状态(是否禁言)

2> 校验要恢复的站内信状态(是否有站内信)

3> 校验是不是给自己回复

4> 构造回复对象

5> 调用Service

6> 返回结果

具体代码

    @Operation(summary = "回复站内信")@PostMapping("/reply")public AppResult reply(HttpServletRequest request,@Parameter(description = "要回复的站内信Id") @RequestParam("repliedId") @NonNull Long repliedId,@Parameter(description = "站内信的内容") @RequestParam("content")@NonNull String content){// 校验当前登录用户的状态HttpSession session = request.getSession(false);User user = (User) session.getAttribute(AppConfig.USER_SESSION);if (user.getState() == 1) {// 返回错误描述return AppResult.failed(ResultCode.FAILED_USER_BANNED);}// 校验要回复的站内信状态Message existsMessage = messageService.selectById(repliedId);if (existsMessage == null || existsMessage.getDeleteState() == 1) {// 返回错误描述return AppResult.failed(ResultCode.FAILED_MESSAGE_NOT_EXISTS);}// 不能给自己回复if (user.getId() == existsMessage.getPostUserId()) {// 返回错误描述return AppResult.failed("不能回复自己的站内信");}// 构造对象Message message = new Message();message.setPostUserId(user.getId()); // 发送者message.setReceiveUserId(existsMessage.getPostUserId()); // 接收者message.setContent(content); // 内容// 调用ServicemessageService.reply(repliedId, message);// 返回结果return AppResult.success();}

7. 测试API接口

相关文章:

  • C++核心编程_赋值运算符重载
  • 多线程(3)
  • 带sdf 的post sim 小结
  • azure web app创建分步指南系列之一
  • CMP401GSZ-REEL混合电压接口中的23ns延迟与±6V输入范围设计实现
  • const ‘不可变’到底是值不变还是地址不变
  • 痉挛性斜颈相关内容说明
  • 无人机桥梁3D建模、巡检、检测的航线规划
  • Spine工具入门教程2之导入
  • Linux安装及管理程序
  • 简易WLAN上传下载查看器by批处理
  • 95套HTML高端大数据可视化大屏源码分享
  • AI与软件工程结合的未来三年发展路径分析
  • AI对软件工程的影响及未来发展路径分析报告
  • ARXML解析与可视化工具
  • ToolsSet之:渐变色生成工具
  • 复刻真实世界的虚拟系统Goal
  • 漏洞Reconfigure the affected application to avoid use of weak cipher suites. 修复方案
  • Ts中的 可选链操作符
  • 【笔记】Suna 部署之 Supabase 数据库 schema 暴露操作
  • 阜新市住房和城乡建设委员会网站/网站seo外链平台
  • 有了网站 域名然后么做/杭州百度快照推广
  • 那个公司做网站/制作网站免费
  • 复制别人的代码做网站/网站关键词挖掘
  • 网站上展示手机页面是怎么做的/足球联赛排名
  • 网站的策划做推广/怎么制作网站?