/**
* 新增员工
* @param employeeDTO
*/
@Override
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
// 对象属性拷贝
BeanUtils.copyProperties(employeeDTO, employee);
// 设置账号状态,默认正常
employee.setStatus(StatusConstant.ENABLE);
// 设置密码,默认密码123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
// 设置当前记录的创建时间和修改时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
// 设置当前记录创建人id和修改人id
// TODO 后期需要改为当前登录用户的Id
employee.setCreateUser(10L);
employee.setUpdateUser(10L);
employeeMapper.insert(employee);
}
/**
* 插入员工数据
* @param employee
*/
@Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user,status) " +
"values " +
"(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")
void insert(Employee employee);
/**
* 新增员工
* @param employeeDTO
* @return
*/
@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
log.info("新增员工: {}", employeeDTO);
employeeService.save(employeeDTO);
return Result.success();
}
注意:由于开发阶段前端和后端是并行开发的,后端完成某个功能后,此时前端对应的功能可能还没有开发完成,导致无法进行前后端联调测试。所以在开发阶段,后端测试主要以接口文档测试为主。
程序存在的问题:
解决方法:
/**
* 处理SQL异常
* @param exception
* @return
*/
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException exception){
// Duplicate entry 'zhangsan' for key 'idx_username'
String message = exception.getMessage();
if (message.contains("Duplicate entry")){
String[] split = message.split(" ");
String username = split[2];
String msg = username.substring(1, username.length() - 1) + MessageConstant.ALREADY_EXISTS;
return Result.error(msg);
}else {
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
}
程序存在的问题:
解决方法:
ThreadLocal常用方法:
在JwtTokenAdminInterceptor中,加入BaseContext.setCurrentId(empId);,设置id
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:", empId);
BaseContext.setCurrentId(empId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
在EmployeeServiceImpl中,BaseContext.getCurrentId() 获取id,并存入数据库
// 设置当前记录创建人id和修改人id
// TODO 后期需要改为当前登录用户的Id
employee.setCreateUser(BaseContext.getCurrentId());
employee.setUpdateUser(BaseContext.getCurrentId());
业务规则:
根据页码展示员工信息
每页展示10条数据
分页查询时可以根据需要,输入员工姓名进行查询
EmployeeController,根据接口定义创建分页查询方法:
/**
* 员工分页查询
* @param employeePageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("员工分页查询")
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
log.info("员工分页查询,参数为:{}",employeePageQueryDTO);
PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
return Result.success(pageResult);
}
在EmployeeServiceImpl声明pageQuery方法,及其父类接口:
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
//select * from employee limit 10,20
//基于PageHelper插件实现动态分
PageHelper.startPage(employeePageQueryDTO.getPage(),
employeePageQueryDTO.getPageSize());
Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
注意:此处使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现
在 EmployeeMapper 中声明 pageQuery 方法:
/**
* 分页查询
* @param employeePageQueryDTO
* @return
*/
Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);
在 EmployeeMapper.xml 中编写SQL:
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.EmployeeMapper">
<select id="pageQuery" resultType="com.sky.entity.Employee">
select * from employee
<where>
<if test="name != null and name != ''">
and name like concat('%', #{name},'%')
if>
where>
order by create_time desc
select>
mapper>
程序存在的问题:
解决办法:
在实体类中,添加注解
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
/**
* 扩展Spring MVC框架的消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器");
// 创建一个小希转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
converter.setObjectMapper(new JacksonObjectMapper());
// 将自己的消息转换器加入到容器中
converters.add(0, converter);
}
业务规则:
根据接口设计中的请求参数形式对应的在 EmployeeController 中创建启用禁用员工账号的方法:
/**
* 启用禁用员工账号
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("启用禁用员工账号")
public Result startOrStop(@PathVariable Integer status, Long id){
log.info("启用禁用员工账号:{}, {}", status, id);
employeeService.startOrStop(status, id);
return Result.success();
}
在 EmployeeServiceImpl 中声明启用禁用员工账号的业务方法,及其父类接口:
/**
* 启用禁用员工账号
* @param status
* @param id
*/
@Override
public void startOrStop(Integer status, Long id) {
Employee employee = Employee.builder()
.status(status)
.id(id)
.build();
employeeMapper.update(employee);
}
在 EmployeeMapper 接口中声明 update 方法:
/**
* 根据id修改员工信息
* @param employee
*/
void update(Employee employee);
在 EmployeeMapper.xml 中编写SQL:
<update id="update" parameterType="Employee">
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="updateTime != null">update_time = #{updateTime},if>
<if test="updateUser != null">update_user = #{updateUser},if>
<if test="status != null">status = #{status},if>
set>
where id = #{id}
update>
编辑员工功能涉及到两个接口:
在 EmployeeController 中创建 getById 方法:
/**
* 根据Id查询员工
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据Id查询员工信息")
public Result<Employee> getById(@PathVariable Long id){
Employee employee = employeeService.getById(id);
return Result.success(employee);
}
在 EmployeeServiceImpl 中实现 getById 方法,及其父类接口:
/**
* 根据Id查询员工
* @param id
* @return
*/
@Override
public Employee getById(Long id) {
Employee employee = employeeMapper.getById(id);
employee.setPassword("****");
return employee;
}
在 EmployeeMapper 接口中声明 getById 方法:
/**
* 根据Id查询员工
* @param id
* @return
*/
@Select("select * from employee where id = #{id}")
Employee getById(Long id);
在 EmployeeController 中创建 update 方法:
/**
* 编辑员工信息
* @param employeeDTO
* @return
*/
@PutMapping
@ApiOperation("编辑员工信息")
public Result update(@RequestBody EmployeeDTO employeeDTO){
log.info("编辑员工信息,{}", employeeDTO);
employeeService.update(employeeDTO);
return Result.success();
}
在 EmployeeServiceImpl 中实现 update 方法,及其父类接口:
/**
* 编辑员工信息
* @param employeeDTO
*/
@Override
public void update(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO, employee);
employee.setUpdateTime(LocalDateTime.now());
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.update(employee);
}
在启用禁用员工账号开发时,已在EmployeMapper.xml中编写了动态的update方法,所以在此方法中需要更新员工信息,也可以调用此方法
业务规则:
接口设计: