【团队作业】第六周作业
package com.lin.controller;
import com.lin.pojo.Result;
import com.lin.pojo.User;
import com.lin.service.UserService;
import com.lin.utils.JwtUtil;
import com.lin.utils.Md5Util;
import com.lin.utils.ThreadLocalUtil;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/user")
@Validated
public class UserController {
@Autowired
private UserService userService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@PostMapping("/register")
public Result register(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password){
//查询用户
User u = userService.findByUserName(username);
if (u == null){
//注册
userService.register(username ,password);
return Result.success();
}else {
return Result.error("用户名已被注册");
}
}
@PostMapping("/login")
public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
//根据用户名查询用户
User loginUser = userService.findByUserName(username);
//判断该用户是否存在
if (loginUser == null) {
return Result.error("用户名错误");
}
//判断密码是否正确 loginUser对象中的password是密文
if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {
Map<String,Object> claims = new HashMap<>();
claims.put("id",loginUser.getId());
claims.put("username",loginUser.getUsername());
String token = JwtUtil.genToken(claims);
//把token存储到redis中
ValueOperations<String,String> operations = stringRedisTemplate.opsForValue();
operations.set(token,token,1, TimeUnit.HOURS);
return Result.success(token);
}
return Result.error("密码错误");
}
@GetMapping("/userInfo")
public Result<User> userInfo(/*@RequestHeader(name = "Authorization") String token*/) {
//根据用户名查询用户
/* Map<String, Object> map = JwtUtil.parseToken(token);
String username = (String) map.get("username");*/
Map<String, Object> map = ThreadLocalUtil.get();
String username = (String) map.get("username");
User user = userService.findByUserName(username);
return Result.success(user);
}
//更新用户
@PutMapping("/update")
public Result update(@RequestBody @Validated User user){
userService.update(user);
return Result.success();
}
//更新头像
@PatchMapping("/updateAvatar")
public Result updateAvatar(@RequestParam @URL String avatarUrl){
userService.updateAvatar(avatarUrl);
return Result.success();
}
//更新密码
@PatchMapping("/updatePwd")
public Result updatePwd(@RequestBody Map<String,String> params,@RequestHeader("Authorization") String token){
//校验参数
String oldPwd = params.get("old_pwd");
String newPwd = params.get("new_pwd");
String rePwd = params.get("re_pwd");
if (!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)){
return Result.error("缺少必要参数");
}
//原密码是否正确
Map<String,Object> map = ThreadLocalUtil.get();
String username = (String)map.get("username");
User loginUser = userService.findByUserName(username);
if (!loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd))){
return Result.error("原密码不正确");
}
//newPwd和rePwd是否一样
if (!rePwd.equals(newPwd)){
return Result.error("两次填写的新密码不一样");
}
//调用
userService.updatePwd(newPwd);
//删除redis对应的token
ValueOperations<String,String> operations = stringRedisTemplate.opsForValue();
operations.getOperations().delete(token);
return Result.success();
}
}
根据提供的代码片段,可以看出这段代码采用了以下几种代码规范方式:
-
注释规范:在代码中包含了注释,用于描述方法的功能和逻辑。例如,在方法上方及代码内部有一些注释,解释了一些重要的逻辑。
-
命名规范:变量、方法和类的命名符合通用的命名规范。例如,变量
username
、password
、loginUser
等的命名清晰且具有描述性。 -
参数校验规范:使用了
@Validated
注解对请求参数进行了校验,确保输入的数据符合指定的正则表达式。 -
RESTful风格:使用了
@PostMapping
、@GetMapping
、@PutMapping
、@PatchMapping
等注解,符合RESTful风格的API设计。 -
DI(依赖注入)规范:通过
@Autowired
注解完成了对依赖的注入,提高了代码的可维护性和灵活性。 -
异常处理规范:在方法中对异常情况进行了处理,并返回相应的错误信息。
-
业务逻辑规范:代码中包含了注册、登录、获取用户信息、更新用户信息等业务逻辑,并且结构清晰。
-
安全规范:通过JWT生成token并存储到Redis中,保证了用户信息的安全性。
概要部分:
-
代码符合需求和规格说明,包括注册、登录、获取用户信息、更新用户信息、更新头像、更新密码等功能。
-
代码设计考虑了用户注册、登录、信息更新等场景,使用了JWT生成token进行身份验证,对输入参数进行了校验和处理,包含了异常处理和返回结果处理,考虑了用户信息的安全性和可用性。
-
代码可读性较好,方法命名符合业务逻辑,结构清晰,注释较少但代码逻辑清晰。
-
代码容易维护,功能模块拆分清晰,逻辑简单直观,易于理解和修改。
设计规范部分:
-
设计遵从了常用的RESTful风格,将注册、登录、更新用户信息等操作以POST、GET、PUT、PATCH等HTTP请求方式进行区分,符合Web API的设计模式。
-
避免了硬编码,使用了常量、注解、参数校验等方式处理字符串和数字。
-
代码没有依赖于特定平台,是独立于具体实现的业务逻辑,易于移植和扩展。
-
开发者新写的代码能够利用已有的功能实现,如使用了Spring框架的注解、AOP等功能,避免了重复实现。
-
代码中没有明显的无用代码,结构简洁清晰,便于维护和管理。
具体代码部分: -
代码中有对错误进行处理,如注册时判断用户名是否已被注册,登录时校验用户名和密码的正确性,并返回相应的错误信息。在外部函数调用和异常处理方面,代码中没有明显的异常处理逻辑,可以考虑增加异常处理机制来提高代码的健壮性。
-
参数传递方面,代码中对用户名和密码进行了长度校验,使用了@Pattern注解进行正则校验,字符串的长度是以字符长度计算的。边界条件处理方面,可以进一步考虑对输入参数的边界情况进行测试,确保代码的稳定性。Switch语句的default分支目前没有明确处理,建议添加相应的逻辑以防止意外情况。
-
在循环中,应注意边界条件的处理,避免可能出现的死循环。可以增加对循环条件和循环体的合理设计和判断,以确保程序能正常退出。需要注意循环中的边界条件,避免死循环的发生。
-
代码中没有使用断言(Assert)来保证我们认为不变的条件得到满足,可以考虑在适当的地方添加断言以确保代码的正确性。断言可以帮助我们在调试阶段检查程序中的一些前提条件是否满足。
-
对资源的利用方面,代码中使用了StringRedisTemplate来操作Redis,并没有明显的资源泄漏情况。建议在操作资源后及时释放资源,确保资源的有效利用。对于数据库连接等资源,要注意及时释放,防止资源泄漏。
-
数据结构中没有明显用不到的元素,代码结构较简洁清晰。可以进一步审查数据结构的设计,确保不会出现无用的元素,以提高代码的效率和可读性。可以考虑进行代码优化,进一步简化和提高代码的性能。
效能: -
代码的效能在一般情况下表现良好,注册、登录等功能较为简单,不会有明显的性能问题。在最坏情况下,可能会出现数据库操作延迟或网络请求超时等情况,需要进一步优化处理异常情况。
-
在代码中,循环中是否有可优化的部分需要进一步审查。例如,是否可以避免在循环内重复创建对象或字符串操作,是否可以使用StringBuilder等工具类来优化字符串拼接操作,提高性能。建议对循环部分进行性能分析,找出可能的优化点。
-
对于系统和网络的调用,代码中应该考虑超时的情况并适当处理。可以设置适当的超时时间,对于网络请求可以使用异步操作或设置合理的超时时间来避免系统阻塞或超时问题。需要确保系统对超时情况有合理的处理逻辑,避免影响用户体验。
可读性:
-
代码的可读性较好,方法命名清晰,结构简单明了,逻辑清晰。对业务逻辑的处理较为直观,易于理解。
-
在代码中可能缺少足够的注释,建议适当增加注释来解释代码的功能、实现原理或特殊逻辑,提高代码的可读性和维护性。注释应该简洁明了,避免啰嗦冗长。
可测试性:
-
需要对代码进行更新或创建新的单元测试,确保代码的功能正确性和稳定性。针对不同的功能模块和业务逻辑,可以编写相应的单元测试用例,覆盖代码的各种情况。
-
针对特定领域的开发,可以整理专门的核查表,包括数据库操作、网络请求、多线程等方面的测试用例和检查点,以确保代码在各种情况下的正确性和稳定性。不同领域的开发可能需要针对性的测试和核查。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战