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

新手做网站优化怎么做宾馆网站模板

新手做网站优化怎么做,宾馆网站模板,网站建设中常见问题分析,淮南网站制作公司用户信息查询接口 在开发用户系统时,一个最基本的需求就是获取用户的个人信息,比如昵称、头像、改名卡次数等。本部分将介绍如何实现一个用户信息查询接口,并结合项目中的用户背包表,查询用户是否有可用的改名卡。 1. 用户信息查…

用户信息查询接口

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

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)可以集中管理错误信息,方便扩展

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

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

http://www.dtcms.com/a/578369.html

相关文章:

  • app软件网站开发门户网站建设思维导图
  • java学习--重载
  • 懒人手机网站模板个人网页制作成品图
  • OpenAI 生产环境终极指南:从原型到规模化
  • YL4056H单节锂电池线性充电芯片
  • 静态IP与动态IP的定义
  • RAID技术全面解析:从基础原理到组合算法
  • 2.3.5 浮点数的表示与运算【2017统考真题】
  • 购物网站建设渠道字体在线生成器
  • 阿里云官方网站 icp代备案管理系统重庆网站推广什么
  • 《十五五规划》下的AI边缘计算机遇:算力下沉与工业智能化
  • 签订网站建设合同商城类网站价格
  • 《链改2.0:从数字资产到RWA》新书宁波重磅发布
  • 基于Springboot的智慧管网灌溉系统i1agupa7(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
  • 正则表达式可视化 - 正则表达式可视化与文本匹配工具
  • JavaScript 正则表达式:选择、分组与引用深度解析
  • 20251106给荣品RD-RK3588-MID开发板跑Rockchip的原厂Android14系统时更换wallpaper墙纸
  • 桂林做网站多少钱做网站给不给源代码
  • 如何使用 Nodemon 自动重启 Node.js 应用
  • Tongweb8安装部署
  • 汽车网站设计模板网页图片批量下载
  • Playwright高级用法全解析:从自动化到工程化的进阶指南
  • 【开源】FBro 浏览器工作流自动化系统
  • 从手动到智能:XTOM-STATION自动化检测中心在复杂曲面零件全尺寸检测中的应用
  • 【题解】洛谷 P4201 [NOI2008] 设计路线 [树形 DP]
  • ES索引配置字段解读
  • linux服务器自动备份数据库脚本
  • 免费的微信视频号下载器
  • 做ic销售的各种网站dede网站安全设置
  • 绥化建设网站电子商城系统平台