您的位置:首页 > 汽车 > 新车 > 网络推广公司经营范围_网站设计论文答辩问题及答案_朋友圈软文_深圳十大网络推广公司排名

网络推广公司经营范围_网站设计论文答辩问题及答案_朋友圈软文_深圳十大网络推广公司排名

2025/10/23 20:57:38 来源:https://blog.csdn.net/m0_53926113/article/details/146502784  浏览:    关键词:网络推广公司经营范围_网站设计论文答辩问题及答案_朋友圈软文_深圳十大网络推广公司排名
网络推广公司经营范围_网站设计论文答辩问题及答案_朋友圈软文_深圳十大网络推广公司排名

用户信息查询接口

        在开发用户系统时,一个最基本的需求就是获取用户的个人信息,比如昵称、头像、改名卡次数等。本部分将介绍如何实现一个用户信息查询接口,并结合项目中的用户背包表,查询用户是否有可用的改名卡。

1. 用户信息查询逻辑

        在项目中,用户可以通过 API 调用 查询自己的个人信息,返回的数据通常包括用户的基本信息以及一些额外属性(如改名卡次数)。
在代码层面,我们可以直接调用 userService.getUserInfo(uid) 方法获取用户信息,并使用 ApiResult.success() 包装返回值,让前端可以方便地解析结果:

return ApiResult.success(userService.getUserInfo(RequestHolder.get().getUid()));

这里的 RequestHolder.get().getUid() 负责从 ThreadLocal 变量中获取 uid,这个 uid 是通过前端传来的 Token 解析 得到的(稍后详细介绍)。

2. 获取用户的改名卡次数

为什么需要查询背包表?
        改名卡并不是直接存储在 User 表里的,而是放在个人背包表中(例如 user_item_bag),所以我们需要去这个表里查询用户是否拥有可用的改名卡。

查询方式如下:

  1. 通过 uiditemid 查询该用户是否拥有改名卡。

  2. status 字段用于判断改名卡是否可用。

  3. 在项目中,我们有一个 YesOrNo 公共枚举,它定义了 0 代表无效,1 代表有效。

代码示例:

UserItem renameCard = userItemBagMapper.findItemByUidAndItemId(uid, ITEM_ID_RENAME_CARD);
boolean hasRenameCard = renameCard != null && renameCard.getStatus() == YesOrNo.YES;

最终,我们可以将 hasRenameCard 的值加入 UserInfo 返回给前端。

3. Token 解析与用户身份确定

        前端请求接口时,需要在 请求头(header) 中携带 token,这个 token 是用户登录后分配的身份凭证。例如:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

后端会解析这个 token,并从中提取出 uid,然后保存在 ThreadLocal 变量中,确保在整个请求生命周期内都能获取到该用户信息:

public class RequestHolder {private static final ThreadLocal<UserToken> threadLocal = new ThreadLocal<>();public static void set(UserToken userToken) {threadLocal.set(userToken);}public static UserToken get() {return threadLocal.get();}public static void remove() {threadLocal.remove();}
}

        这样,业务代码就可以随时通过 RequestHolder.get().getUid() 获取当前用户的 uid,不需要每个方法都手动传递 uid 了。

总结

  • 用户信息接口通过 userService.getUserInfo(uid) 获取用户数据,并返回给前端。

  • 改名卡存储在 用户背包表 中,需要通过 uid + itemid 查询,并用 status 字段判断是否可用。

  • 前端请求时需要携带 token,后端解析 token 并存入 ThreadLocal,确保在整个请求中都能获取到 uid

        这一部分实现了用户基本信息的查询,下一步,我们将开发用户改名接口,让用户可以修改自己的昵称! 🚀

用户改名接口

用户希望修改自己的昵称,但为了防止滥用,我们需要做一些必要的校验,比如:

  • 新名字不能为空,长度不能太长。

  • 用户必须拥有有效的改名卡才能改名。

  • 处理改名前后端的交互方式。

这一部分,我们来实现一个安全、合规的用户改名接口

1. 注册改名接口

UserController 中,我们用 @PutMapping("/name") 注册接口:

@PutMapping("/name")
public ApiResult<?> modifyName(@Valid @RequestBody ModifyNameRequest request) {Long uid = RequestHolder.get().getUid(); // 获取当前用户IDreturn userService.modifyName(uid, request.getNewName());
}

这里的关键点:

  • @PutMapping("/name") 代表这是一个 PUT 请求,适用于更新操作。

  • @RequestBody ModifyNameRequest request 用于接收前端提交的 JSON 数据ModifyNameRequest 结构如下:

public class ModifyNameRequest {@NotBlank(message = "新名称不能为空")@Length(max = 20, message = "新名称不能超过20个字符")private String newName;// 省略getter/setter
}
  • @Valid 注解启用了参数校验,如果新名字为空或超过 20 个字符,就会抛出异常(下一节介绍如何捕获异常)。

2. 处理改名逻辑

UserService 里实现 modifyName() 方法:

public ApiResult<?> modifyName(Long uid, String newName) {// 1. 检查新名称是否和当前名称相同User user = userMapper.findById(uid);if (user == null) {return ApiResult.fail(CommonErrorEnum.USER_NOT_FOUND);}if (user.getName().equals(newName)) {return ApiResult.fail(CommonErrorEnum.NAME_NO_CHANGE);}// 2. 检查用户是否有可用的改名卡UserItem renameCard = userItemBagMapper.findItemByUidAndItemId(uid, ITEM_ID_RENAME_CARD);if (renameCard == null || renameCard.getStatus() != YesOrNo.YES) {return ApiResult.fail(CommonErrorEnum.NO_RENAME_CARD);}// 3. 扣除改名卡,并更新用户名userItemBagMapper.useItem(renameCard.getId()); // 标记改名卡已使用userMapper.updateUserName(uid, newName);return ApiResult.success("改名成功");
}

这里的关键点:
检查新名称是否合法(不能和当前名称相同)。
查询用户的改名卡,确保用户拥有可用的改名卡。
扣除改名卡,并更新用户昵称

3. 处理异常情况

Spring 提供了 @ExceptionHandler 让我们可以捕获异常,统一返回友好的错误信息。
GlobalExceptionHandler 里,我们添加对参数校验失败的处理:

@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResult<?> handleValidationException(MethodArgumentNotValidException e) {String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();return ApiResult.fail(CommonErrorEnum.INVALID_PARAM.getCode(), message);
}

这样,当用户提交的 newName 为空或超长时,系统会自动返回:

{"code": 400,"message": "新名称不能为空"
}

此外,我们还可以拦截所有 非预期异常,避免直接暴露给前端:

@ExceptionHandler(Throwable.class)
public ApiResult<?> handleUnknownException(Throwable e) {log.error("系统异常", e);return ApiResult.fail(CommonErrorEnum.SYSTEM_ERROR);
}

4. 前后端交互示例

前端请求示例:

PUT /api/user/name
Content-Type: application/json
Authorization: Bearer <用户的Token>{"newName": "新的昵称"
}

正常返回:

{"code": 200,"message": "改名成功"
}

错误示例(改名卡不足):

{"code": 403,"message": "没有可用的改名卡"
}

总结

  • @PutMapping("/name") 注册了改名接口,接收前端的 JSON 请求。

  • 参数校验:使用 @Valid 确保新名称不能为空且不超长

  • 业务逻辑:检查 改名卡 是否可用,成功后扣除改名卡更新用户名

  • 全局异常处理:拦截校验失败 & 其他异常,避免直接抛出错误给前端。

这样,一个完整的用户改名接口就开发完成了! 🎉
下一步,我们来看看全局异常处理,让错误信息更加清晰统一! 🚀

全局异常处理(Global Exception Handler)

        在开发接口时,异常处理是非常重要的环节。一个好的异常处理机制,能够让我们的系统更加稳定,并且可以给前端返回清晰统一的错误信息。

本节内容,我们来实现一个全局异常处理器,让系统能够优雅地应对各种异常。

1. 为什么需要全局异常处理?

在项目中,异常可能来自多个地方,比如:

  • 用户输入错误(参数为空、格式错误等)。

  • 业务逻辑异常(改名卡不足、用户不存在等)。

  • 系统异常(数据库连接失败、空指针异常等)。

如果每个接口都手动 try-catch,不仅代码冗余,还容易遗漏某些异常。全局异常处理可以拦截所有异常,统一处理后再返回给前端。

2. 如何实现全局异常处理?

        Spring 提供了 @ControllerAdvice@ExceptionHandler 让我们可以全局捕获异常,并返回统一格式的 JSON 响应。

我们创建一个 GlobalExceptionHandler 处理所有的异常情况。

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {/*** 处理参数校验失败(@Valid 校验)*/@ExceptionHandler(MethodArgumentNotValidException.class)public ApiResult<?> handleValidationException(MethodArgumentNotValidException e) {String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();return ApiResult.fail(CommonErrorEnum.INVALID_PARAM.getCode(), message);}/*** 处理业务异常(自定义异常)*/@ExceptionHandler(BusinessException.class)public ApiResult<?> handleBusinessException(BusinessException e) {return ApiResult.fail(e.getErrorCode(), e.getMessage());}/*** 处理所有未知异常(兜底)*/@ExceptionHandler(Throwable.class)public ApiResult<?> handleUnknownException(Throwable e) {log.error("系统异常", e);return ApiResult.fail(CommonErrorEnum.SYSTEM_ERROR);}
}

3. 代码解析

1️⃣ 处理参数校验失败
如果用户输入的数据不符合 @Valid 校验(如改名时名字为空),会抛出 MethodArgumentNotValidException,我们在这里提取错误信息并返回给前端:

@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResult<?> handleValidationException(MethodArgumentNotValidException e) {String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();return ApiResult.fail(CommonErrorEnum.INVALID_PARAM.getCode(), message);
}

示例错误返回

{"code": 400,"message": "新名称不能为空"
}

2️⃣ 处理业务异常
对于我们自己定义的业务异常(如用户没有改名卡),可以创建 BusinessException 并统一处理:

public class BusinessException extends RuntimeException {private final int errorCode;public BusinessException(CommonErrorEnum errorEnum) {super(errorEnum.getMessage());this.errorCode = errorEnum.getCode();}public int getErrorCode() {return errorCode;}
}

然后,在全局异常处理器中捕获:

@ExceptionHandler(BusinessException.class)
public ApiResult<?> handleBusinessException(BusinessException e) {return ApiResult.fail(e.getErrorCode(), e.getMessage());
}

示例错误返回

{"code": 403,"message": "没有可用的改名卡"
}

3️⃣ 兜底处理所有未知异常
如果某个异常没有被前面捕获,我们用 Throwable.class 兜底处理,同时记录日志,方便排查问题:

@ExceptionHandler(Throwable.class)
public ApiResult<?> handleUnknownException(Throwable e) {log.error("系统异常", e);return ApiResult.fail(CommonErrorEnum.SYSTEM_ERROR);
}

示例错误返回

{"code": 500,"message": "系统错误,请稍后再试"
}

4. 错误码枚举(CommonErrorEnum)

为了让错误信息更规范,我们用一个枚举类来管理所有的错误码:

@Getter
public enum CommonErrorEnum {INVALID_PARAM(400, "请求参数错误"),USER_NOT_FOUND(404, "用户不存在"),NAME_NO_CHANGE(400, "新名称不能与当前名称相同"),NO_RENAME_CARD(403, "没有可用的改名卡"),SYSTEM_ERROR(500, "系统错误,请稍后再试");private final int code;private final String message;CommonErrorEnum(int code, String message) {this.code = code;this.message = message;}
}

这样,所有的错误信息都在这里管理,后续扩展也非常方便! 🎯

5. 前后端交互示例

前端请求

PUT /api/user/name
Content-Type: application/json{"newName": ""
}

返回(参数校验失败)

{"code": 400,"message": "新名称不能为空"
}

返回(没有改名卡)

{"code": 403,"message": "没有可用的改名卡"
}

返回(系统异常)

{"code": 500,"message": "系统错误,请稍后再试"
}

6. 总结

  • 全局异常处理统一管理错误,避免代码中大量 try-catch

  • @ExceptionHandler 用于捕获特定异常,让错误信息友好一致

  • 错误码枚举CommonErrorEnum)可以集中管理错误信息,方便扩展

  • 日志记录能帮助我们快速排查问题,避免未知错误影响用户体验。

至此,我们的全局异常处理机制完成了! 🎉
现在,无论用户输入错误,还是系统出现异常,前端都能收到清晰规范的错误信息! 🚀

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com