文章目录
前言
苍穹外卖day02,主要开发员工模块代码,包含新增员工、员工分页查询、启用禁用员工账号和编辑员工接口。
觉得有帮助的可以看下我的个人网站 www.yucan.dev
提示:以下是本篇文章正文内容,下面案例可供参考
一、新增员工
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
需求分析和设计
产品原型
接口设计
数据库设计(employee表)
代码开发
根据新增员工接口设计对应的DTO
用DTO封装数据而不是直接使用实体类,使用DTO可以方便在参数类上添加注解,有助于数据校验,实体类封装数据会产生不需要的变量是对性能的浪费
/**
* 新增员工
* @param employeeDTO
* @return
*/
@PostMapping // 该接口是post
@ApiOperation("新增员工") // Swagger接口文档注解, @ApiOperation用在方法上,例如Controller的方法,说明方法的用途、作用
public Result save(@RequestBody EmployeeDTO employeeDTO) { /*
* @RequestBody 注解用于将 HTTP 请求体中的 JSON 数据转换为 Java 对象
* @RequestBody 是 Spring Framework 中用于处理 HTTP 请求体的注解。
* 通常用于 RESTful Web 服务的控制器方法中,以便将请求体内容自动反序列化为 Java 对象
*/
log.info("新增员工:{}", employeeDTO); // 增加日志方便调试
// 使用 SLF4J(Simple Logging Facade for Java)或者 Log4j 等日志框架时,使用 {} 占位符来格式化日志信息
// SLF4J 会自动将后面的参数替换到占位符位置。
employeeService.save(employeeDTO);
return Result.success();
}
employeeService.save()方法
/**
* 新增员工
* @param employeeDTO
*/
@Override
public void save(EmployeeDTO employeeDTO) {
// 转DTO,传入Mapping层需要是实体类
Employee employee = new Employee();
// employee.setUsername(employeeDTO.getUsername()); // 直接设置属性过于繁琐
// 这里使用了 对象属性拷贝 ,Spring提供了BeanUtils工具类, 使用该工具类要确保属性名称保持一致
BeanUtils.copyProperties(employeeDTO, employee);
// employee实体类中属性比DTO中更多,所以需要继续将剩下属性填充
// 设置账号状态,默认正常状态 1表示正常 0表示锁定
employee.setStatus(StatusConstant.ENABLE);
// 设置密码,默认密码123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
// 设置创建时间,更新时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
// 设置d当前记录创建人id,修改人id
// TODO 创建人和修改人应该从前端传过来,动态获取,后期改变为当前用户id
employee.setCreateUser(10L);
employee.setUpdateUser(10L);
employeeMapper.insert(employee);
}
功能测试
- 通过接口文档测试
- 前后端联调测试
由于前后端是并行开发,往往后端开发某个功能后,前端对应功能未完成,导致无法进行前后端联调测试,所以在开发阶段,后端测试主要以接口文档测试为主。
token处理 - 调用员工登录接口获得一个合法的JWT令牌
- 将合法的JWT令牌添加到全局参数中
代码完善
程序存在问题:
- 录入的用户名已经存在,抛出异常之后没有处理 - 数据库中用户名字段设置成unique
- 新增员工时,creatUser和updateUser设置为了固定值
- 解决异常,通过全局异常器处理
- 2.针对第二个问题,可以通过JWT Token动态获取当前登陆员工id
JWT Token登陆流程
在拦截请求验证JWT Token环节可以反向解析Token,获取当前登陆用户id,因为在生成JWT Token环节是一个已经登陆的状态,token中包含登陆id信息。
employeeController.java
JwtTokenAdminInterceptor.java
解析出员工登陆id后,如何传递给Service的save方法?
ThreadLocal 并不是一个Thread,而是Thread的局部变量。
ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
注意:客户端发送的每次请求,后端的Tomcat服务器都会分配一个单独的线程来处理请求
所以我们可以在请求验证JWT Token环节将id存储到ThreadLocal中,然后在service中的save读取id
ThreadLocal常用方法:
public void set(T value) 设置当前线程的线程局部变量的值
public T get() 返回当前线程所对应的线程局部变量的值
public void remove() 移除当前线程的线程局部变量
我们在实际中使用ThreadLocal会进行一个简单的封装,包装成一个工具类,使用起来会更方便,初始工程中sky-common部分的 com.sky.context
二、员工分页查询
需求分析
代码开发
- 根据分页查询接口设计对应的DTO
@Data
public class EmployeePageQueryDTO implements Serializable {
//员工姓名
private String name;
//页码
private int page;
//每页显示记录数
private int pageSize;
}
- 后端所有分页查询,统一封装成PageResult对象
/**
* 封装分页查询结果
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
private long total; //总记录数
private List records; //当前页数据集合
}
- 员工信息分页查询后端返回的对象类型为:Result
data里存放的就是PageResult对象
首先在EmployeeControl.java中增加员工分页方法
/**
* 员工分页查询
* @param employeePageQueryDTO
* @return
*/
@GetMapping("/page") // 接口是GET方式请求
@ApiOperation("员工分页查询") // Swagger接口文档注解
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO) { //前端请求数据格式是Query
log.info("员工分页查询,参数为:{}", employeePageQueryDTO);
PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
return Result.success(pageResult);
}
然后在EmployeeService.java声明pageQuery接口和EmployeeServiceImpl.java中实现pageQuery接口
/**
* 员工分页查询
* @param employeePageQueryDTO
* @return
*/
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
// select * from employee limit 0, 10
// 开始分页查询,使用pagehelper插件,这里能使用PageHelper插件是因为在项目描述文件pom.xml中添加了pagehelper依赖
PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize()); // 基于MyBatis拦截器实现
// 在pageQuery()中似乎没有实现分页的SQL语句,而这里又没有将PageHelper的返回结果传递给pageQuery()方法,那么分页查询的SQL语句是如何实现的?
// 是因为,PageHelper底层是通过ThreadLocal实现的,在pageQuery中实现数据库语句之前会通过ThreadLocal将实现分页的语句拼接起来
Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
long total = page.getTotal();
List<Employee> records = page.getResult();
return new PageResult(total, records);
}
代码完善
日期显示是数组形式,格式不对
解决方法
- 方法一:在属性上加入注解,对日期进行格式化
- 方法二:在WebMvcConfiguration中扩展Spring MVC的消息转换器,统一对日期进行格式化处理
/**
* 扩展spring MVC框架的消息转换器
* @param converters
*/
//对后端返回前端的数据统一
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("开始拓展消息转换器...");
// 创建一个消息转化器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 需要为消息转换器设置一个对象转换器,对象转换器将Java对象序列化为json对象
converter.setObjectMapper(new JacksonObjectMapper());
// 将写好的对象转换器放入Spring MVC框架的容器 converters中
converters.add(0, converter);
}
三、启用禁用员工账号
需求分析
业务规则:
- 可以对状态为“启用” 的员工账号进行“禁用”操作
- 可以对状态为“禁用”的员工账号进行“启用”操作
- 状态为“禁用”的员工账号不能登录系统
代码开发
/**
* 启用禁用员工账号
* @param id
* @param status
* @return
*/
@PostMapping("/status/{status}") // 请求方式是POST,请求路径 /admin/employee/status/{status}
@ApiOperation("启用禁用员工账号")
// 两个参数,分别为路径参数status和地址栏传参id
public Result startOrStop(@PathVariable("status") Integer status, long id) { // 查询功能,返回范型,非查询功能返回result即可
log.info("启用禁用员工账号: {},{}", status, id);
employeeService.startOrStop(status, id);
return Result.success();
}
employServiceImp.java
/**
* 启用禁用员工账号
* @param status
* @param id
*/
public void startOrStop(Integer status, long id) {
// update employee set status = ? where id =?
// 在这里希望设置成动态SQL修改语句,根据传进来的参数不同可以修改不同的数据
// Employee employee = new Employee();
// employee.setId(id);
// employee.setStatus(status);
// Employee实体添加了 @Builder 构建器注解,也可以通过Employee.builder()创建对象
Employee employee = Employee.builder()
.status(status)
.id(id)
.build();
employeeMapper.update(employee);
}
EmployMapper.xml
<update id="update" parameterType="Employee"> <!--这里可以不带路径指定参数,是因为在application.yml配置文件中指明了mapper配置路径和映射路径 -->
update employee
<set>
<if test="name != null"> name = #{name},</if>
<if test="username != null"> username = #{username},</if>
<if test="password != null"> password = #{password},</if>
<if test="phone != null"> phone = #{phone},</if>
<if test="sex != null"> sex = #{sex},</if>
<if test="idNumber != null"> id_number = #{idNumber},</if>
<if test="status != null"> status = #{status},</if>
<if test="updateTime != null"> update_time = #{updateTime},</if>
<if test="updateUser != null"> update_user = #{updateUser},</if> <!-- MySQL语句不区分大小写-->
</set>
where id = #{id}
</update>
总结
day02主要是根据需求设计接口,然后通过接口文档开发代码即可,大部分内容还是通俗易懂。
标签:status,分页,day02,接口,员工,外卖,employee,苍穹,id From: https://blog.csdn.net/weixin_41975386/article/details/142602745