文章目录
前言
员工管理、分类管理。主要分析员工管理部分,分类管理中的代码逻辑和员工管理差不多,可以自己尝试着仿写。
一、员工管理
1、新增员工
以新增员工为例,给出产品原型和接口的设计。
1.1 产品原型
1.2 接口设计
怎么去看接口设计这部分,我们之后编写代码都是基于此,这是前端与后端的约定。
1、Path:请求路径 ,对应的注解@RequestMapping(“/admin/employee”)
2、Method:请求方式,方法上对应的注解@PostMapping(要不要写参数具体看path这里,如果xxcontroller类中请求路径都是admin/employee,那就把它放在类上面,后面还有具体的路径就可以写在这里)
3、请求参数:主要看请求体Body的内容,根据请求体来设计对应的实体类(DTO)。如下图。同时这部分也会作为方法的传入参数,JSON格式要记得在参数前加入@RequestBody注解。
4、返回的数据:这部分是数据被封装到Result结果集当中,主要是看返回的data数据,data数据是什么类型就按照对应的类型存入Result中。
1.3 代码开发
1、在EmployeeController中创建新增员工方法,接收前端提交的参数
@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
employeeService.save(employeeDTO);
return Result.success();
}
2、在EmployeeServiceImpl中实现新增员工方法
@Override
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
//属性拷贝
BeanUtils.copyProperties(employeeDTO,employee);
//设置账号状态
employee.setStatus(StatusConstant.ENABLE);
//加密技术
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
//这部分后面采用aop框架,所以就注释掉了
//创建时间和更新时间
//employee.setCreateTime(LocalDateTime.now());
// employee.setUpdateTime(LocalDateTime.now());
//当前创建人,修改人
//employee.setCreateUser(BaseContext.getCurrentId());
// employee.setUpdateUser(BaseContext.getCurrentId());*/
employeeMapper.insert(employee);
}
3、在EmployeeMapper中声明insert方法
@Insert("insert into employee" +
"(name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user)"+
"VALUES" +
"(#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, #{status}, #{createTime},#{updateTime},#{createUser}, #{updateUser})")
@AutoFill(value = OperationType.INSERT) //自定义注解
void insert(Employee employee);
4、新增用户信息,要检查用户是否已经存在,可以通过全局异常处理器来处理。
/**
* 捕获sql异常,用户已存在
*/
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error("异常信息:{}", ex.getMessage());
String message = ex.getMessage();
if(message.contains("Duplicate entry")){
String[] split = message.split(" ");
String name = split[2];
return Result.error(name + MessageConstant.ALREADY_EXISTS); }
return Result.error(MessageConstant.UNKNOWN_ERROR);}
}
1.4 功能测试
两种方式:
通过接口文档(Swagger)
通过前后端联调(前端界面)
2、JWT、ThreadLocal
通过某种方式动态获取当前登录员工的id。
员工登录成功后会生成JWT令牌并响应给前端:
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
String token = JwtUtil.createJWT(
jwtProperties.getAdminSecretKey(),
jwtProperties.getAdminTtl(),
claims);
通过JWT令牌可以解析出当前登录员工id,那如何传递给Service的save方法呢?
ThreadLocal
为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
常用方法:
public void set(T value) //设置当前线程的线程局部变量的值
public T get() //返回当前线程所对应的线程局部变量的值
public void remove() //移除当前线程的线程局部变量
注意:客户端发送的每次请求,后端的Tomcat服务器都会分配一个单独的线程来处理请求
方法:
(1)通过BaseContext封装ThreadLocal操作的工具类
(2)在JWT拦截器中解析当前登录员工的id,并放入线程局部变量中(BaseContext.setCurrentId(empId);)
(3)在Service中获取线程局部变量中的值。(employee.setCreateUser(BaseContext.getCurrentId());)
二、员工分页查询
1、 产品原型
2、 接口设计
根据请求参数设计实体类(DTO)
分页查询,统一封装成PageResult对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
private long total; //总记录数
private List records; //当前页数据集合
}
后端返回的对象类型:Result
3、 代码开发
1、controller层创建分页查询方法
@GetMapping("/page")
@ApiOperation("员工分页查询")
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
return Result.success(pageResult);
}
2、EmployeeService接口定义方法,EmployeeServiceImpl 中实现 pageQuery 方法
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
//基于PageHelper插件实现动态分页查询 select * from employee limit 10,20
PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());
Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
return new PageResult(page.getTotal(),page.getResult());
}
使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现。
3、在 EmployeeMapper 中声明 pageQuery 方法
4、在 EmployeeMapper.xml 中编写SQL
<select id="pageQuery" resultType="com.sky.entity.Employee">
select * from employee
<where>
<if test="name != null and name != ''">
name like concat('%',#{name},'%')
</if>
</where>
order by create_time desc
</select>
4、 日期格式问题
解决方式
(1)在属性上加入注解,对日期进行格式化。效率低
(2)在 WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//创建一个消息转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
//需要为消息转换器设置一个对象转换器,对象转换器可以将java对象序列化为JSON数据
converter.setObjectMapper(new JacksonObjectMapper());
//将自己的消息转化器加到容器中
converters.add(0,converter);
}
三、启用禁用员工账号
1、业务规则
可以对状态为“启用” 的员工账号进行“禁用”操作
可以对状态为“禁用”的员工账号进行“启用”操作
状态为“禁用”的员工账号不能登录
2、接口设计
3、代码开发
1、根据接口设计中的请求参数形式对应的在 EmployeeController 中创建启用禁用员工账号的方法
@PostMapping("/status/{status}")
@ApiOperation("启用禁用员工账号")
public Result startOrStop(@PathVariable Integer status,Long id){
log.info("启用禁用员工账号:{},{}",status,id);
employeeService.startOrStop(status,id);
return Result.success();
}
2、在 EmployeeService 接口中声明方法,在EmployeeServiceImpl 中实现
@Override
public void startOrStop(Integer status, Long id) {
//update employee set status = ? where id = ?
//方式一:
// Employee employee = new Employee();
// employee.setStatus(status);
// employee.setId(id);
//方式二:
Employee employee = Employee.builder()
.status(status)
.id(id)
/*.updateTime(LocalDateTime.now()) //运用aop减少代码冗余
.updateUser(BaseContext.getCurrentId())*/
.build();
employeeMapper.update(employee);
}
3、在 EmployeeMapper 接口中声明 update 方法
4、在 EmployeeMapper.xml 中编写SQ
<update id="update">
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>
四、修改员工信息
1、接口设计
2、代码开发
1、在 EmployeeController 中创建 update ()方法
2、在 EmployeeService 接口中声明方法,在 EmployeeServiceImpl 中实现方法
3、调用EmployeeMapper中的update()方法
总结
实现基本的增删改查操作,都是一个套路,代码编辑路线:controller->service->serviceImpl->mapper(简单的sql语句直接用注解,不需要去xml文件中编写)—>mapper.xml(编写sql语句)