在这个AI肆意编程的时代,我为什么要学习苍穹外卖?
全文接近5700字,记录我用SpringBoot写员工登录与新增员工的踩坑与思考
【作者说:现在的AI疯狂处处可见,但我认为作为一个更好的AI使用者应该更要完整的了解一个项目的核心运作,只有这样,我们对AI话语才会更加准确,效率才会更高。所以在这个AI的时代风口下,与其相信网上大篇幅的“程序员已die论”,不如努力的提升自己,要相信自己,相信自己可以将无所不能的AI作为自己的工具和“小弟”,不要盲目受网络信息的悲观因素影响,也不要陷入专业选择的泥潭,始终要坚信,我们所选择的路就是最好的道路,毕竟一个奋发向上的人拿什么输呢!!!本项目将会持续更新,感兴趣的读者可以关注点赞不迷路!】
苍穹外卖项目-day02-员工登录与新增员工模块笔记
员工登录与新增员工功能实现要点
功能描述
员工登录模块用于员工在后台系统中登录,新增员工主要是管理员在后台系统新增员工并且存储员工信息,包括姓名、账号、手机号、角色分配等字段到数据库,需保证数据合法性和唯一性。
数据库设计 员工表需包含基础字段:id(主键)、username(用户名)、password(加密存储)、name(姓名)、phone(手机号)、status(账号状态,如1启用/0禁用)。建议密码使用BCrypt或MD5加盐加密。
技术实现
- 后端接口:通常为
POST /admin/employee,接收JSON格式的员工数据。 - 数据库表:关联员工表(如
employee)和角色关联表(如role_employee)。 - 权限控制:仅限管理员角色操作,通过拦截器或注解(如
@PreAuthorize)实现。
核心代码示例
1. 实体类设计
public class Employee {
private Long id;
private String username; // 账号
private String name; // 姓名
private String phone; // 手机号
private String password; // 密码(需加密)
private Integer status; // 状态(1启用,0禁用)
// 省略getter/setter
}
2. Controller层
@PostMapping("/login")
@ApiOperation(value="员工登录")
public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
log.info("员工登录:{}", employeeLoginDTO);
Employee employee = employeeService.login(employeeLoginDTO);//后端与数据库进行匹配
//登录成功后,生成jwt令牌
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
String token = JwtUtil.createJWT(
jwtProperties.getAdminSecretKey(),
jwtProperties.getAdminTtl(),
claims);
EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()//
.id(employee.getId())
.userName(employee.getUsername())
.name(employee.getName())
.token(token)
.build();
return Result.success(employeeLoginVO);
}
Jwt令牌就是相当于“身份证”,对员工的身份信息进行整理,并且封装起来,用token表示。 这个token上不仅记录员工的信息,而且还记录一个员工的权限,例如管理员可以对员工或者菜单进行管理,他的权限是比普通员工大的。
3JWT令牌创建流程
JWT令牌由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。头部声明令牌类型和签名算法,载荷包含用户信息和其他声明,签名用于验证令牌的完整性。
头部通常采用JSON格式,指定算法如HS256。载荷包含用户ID、角色等自定义信息,可加入过期时间等标准声明。签名部分通过密钥对头部和载荷进行加密生成。
将头部、载荷和签名用Base64Url编码后,用点号连接起来形成完整的JWT令牌。令牌创建后需在服务端进行验证,确保安全性。
public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
// 指定签名的时候使用的签名算法,也就是header那部分
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 生成JWT的时间
long expMillis = System.currentTimeMillis() + ttlMillis;
Date exp = new Date(expMillis);
// 设置jwt的body
JwtBuilder builder = Jwts.builder()
// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
.setClaims(claims)
// 设置签名使用的签名算法和签名使用的秘钥
.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
// 设置过期时间
.setExpiration(exp);
return builder.compact();
}
4.关于Token的解密
/**
* Token解密
*
* @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
* @param token 加密后的token
* @return
*/
public static Claims parseJWT(String secretKey, String token) {
// 得到DefaultJwtParser
Claims claims = Jwts.parser()
// 设置签名的秘钥
.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
// 设置需要解析的jwt
.parseClaimsJws(token).getBody();
return claims;
}
4.员工退出
@PostMapping("/logout")
@ApiOperation("员工退出")
public Result<String> logout() {
return Result.success();
}
5.新增员工(开发模块)
@PostMapping()
@ApiOperation("新增员工")//
public Result save(@RequestBody EmployeeDTO employeeDTO){
log.info("新增员工,员工数据:{}",employeeDTO);
employeeService.save(employeeDTO);//这里是跟数据库进行交互
return Result.success();//返回成功result
}
DTO与VO
在2. Controller层中出现了employeeLoginDTO与employeeLoginVO再在里进行解释:
*DTO(Data Transfer Object*//“数据搬运工”
DTO是用于在不同层或系统间传输数据的对象,通常不包含业务逻辑。它的核心目的是封装数据并减少网络调用次
数(如远程接口通信),优化传输效率。DTO的属性通常与底层数据模型(如数据库表)解耦,仅包含传输所需的
字段,可能涉及多个领域模型的聚合数据。
其特点包括:
- 扁平化结构,避免嵌套复杂对象。
- 可能包含额外的传输控制字段(如分页信息、状态码)。
- 序列化友好(支持JSON、XML等格式)。
*VO(Value Object)*//“数据化妆师”
VO是展示层(如前端)使用的数据对象,关注数据的呈现形式而非存储细节。它可能包含格式化的数据(如日期字
符串)、组合字段或视图特有的计算属性,与UI需求强相关。
其特点包括:
- 包含展示逻辑(如状态字段转文字描述)。
- 结构可能嵌套,适配前端组件需求。
- 与DTO相比,更贴近用户视角而非技术视角。
注解知识点梳理(SpringBoot)
@RestController
@RestController是Spring MVC中的一个组合注解,结合了@Controller和@ResponseBody的功能。它用于标记一个类为控制器,并默认将所有方法的返回值直接序列化为HTTP响应体(如JSON或XML),无需额外配置。适用于构建RESTful API。
@Service
@Service是Spring框架的注解,用于标记类为业务逻辑层的组件(Service层)。它被Spring容器自动扫描并管理,通常用于实现业务逻辑。与@Repository或@Component类似,但语义上更明确表示服务层。
@RequestMapping
@RequestMapping用于映射HTTP请求路径到控制器方法或类。可指定URL路径、HTTP方法(如GET、POST)、请求参数等,它是前端与后端的交互入口,只负责打通前后端的请求通路。
@RequestBody
@RequestBody用于将HTTP请求体(如JSON或XML)反序列化为Java对象。通常与@PostMapping或@PutMapping配合使用,处理POST/PUT请求的请求体数据。
@PostMapping
@PostMapping是@RequestMapping(method = RequestMethod.POST)的快捷方式,专门用于处理HTTP POST请求。只要前端触发@PostMapping括号里的内容地址,那么就执行@PostMapping后面的代码逻辑。
@ApiOperation注解详解
@ApiOperation是Swagger框架中的核心注解之一,用于描述API接口的功能和细节。通常与@Api、@ApiModel等注解配合使用,生成规范的API文档。属性在这里主要使用tags,接口所属的分组标签。若未指定,默认使用Controller的类名,还有value属性,用来写接口的简要功能,notes属性用来写详细的参数说明或业务规则。
关键区别与用途
@RestController:定义RESTful控制器,替代传统@Controller+@ResponseBody。 @Service:标识业务逻辑层组件,由Spring依赖注入管理。 @RequestMapping:通用请求映射,支持所有HTTP方法。 @PostMapping:专用于POST请求的简化注解。 @RequestBody:解析请求体为Java对象,通常用于接收JSON/XML数据。
常见问题与解决
数据唯一性冲突
- 将表中的id字段设为自增主键,可以将数据按顺序存储,查询效率更高
- 数据库添加唯一索引(如
username和phone字段)。 - 后端插入前主动查询校验。
密码安全性
- 这里为了避免明文存储,使用
MD5加密,防止传给前端密码,导致账号数据丢失。还可以推荐使用 BCrypt算法 ,它生成的密码密文带有随机盐值,即使两个用户密码相同,也会输出不一样的结果,破解难度会大大增加,它的长度更长且不可逆 - 初始密码可设为随机字符串或默认值(需首次登录修改)。
日志记录
- 通过AOP或拦截器记录操作日志(如“新增员工:张三”)。
扩展功能建议
- 批量导入:支持Excel文件导入员工数据。
- 初始密码通知:通过短信或邮件发送临时密码。
- 角色分配:动态绑定角色权限(需关联角色表查询)。
以上内容可结合实际项目需求调整,重点关注数据校验、权限控制及异常处理。
实战总结与思考
本次主要完成了员工管理模块中员工登录、退出、新增等核心基础功能的开发,通过这部分功能的实战,我系统梳理并掌握了Spring Boot后端开发的核心注解与分层开发逻辑,从控制器层接收前端请求,到服务层处理业务逻辑,再到数据层操作数据库,清晰理解了各层级的职责划分与协作流程,这将会是java后端工作的核心内容。
在功能实现过程中,也针对性解决了数据唯一性冲突、密码安全存储、接口文档标注、操作日志记录等实际开发问题,学会了从数据库层面、代码层面对数据进行校验和安全处理,夯实了后端基础开发能力。
本篇笔记仅聚焦员工登录、退出、新增等基础小模块,员工信息查询、删除等核心功能将整合至后续模块统一梳理学习。后续我会继续完善员工管理全流程功能,补齐查询、删除、分页等模块,搭建完整的员工管理业务体系,进一步深化对Spring Boot框架及后端开发流程的掌握,不断优化代码逻辑与业务处理能力。