O 管理端发出的请求,统一使用/admin作为前缀
O 用户端发出的请求,统一使用/user作为前缀
根据新增员工接口设计对应的DTO
从前端接收到DTO实体,转化成数据库对应的entity,在Service层添加代码:
/*
* 新增员工
* */
@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);
}
程序存在的问题:
o 录入的用户名已经存在
o 新增员工时,创建人id和修改人id设置为了固定值
1、处理用户名重复问题,设置异常处理器:
// 处理异常信息,处理SQL异常
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
// Duplicate entry 'zhaoliu' for key 'idx_username'
String message = ex.getMessage();
if(message.contains("Duplicate entry")){
String[] split = message.split(" ");
String username = split[2];
String msg = username + MessageConstant.ALREADY_EXISTS;
return Result.error(msg);
}
else {
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
}
2、获取登录用户的id
ThreadLocal:并不是Thread,而是Thread的局部变量。ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
整个程序在同一线程中执行,获取线程中正在登录的id,通过一个中间件得到:
package com.sky.context;
public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id) {
threadLocal.set(id);
}
public static Long getCurrentId() {
return threadLocal.get();
}
public static void removeCurrentId() {
threadLocal.remove();
}
}
需求分析和设计:根据展示员工信息,每页展示10条数据,分页查询时可以根据需要,输入员工姓名进行模糊查询:
contorller层:
//员工分页查询
@ApiOperation(value = "员工分页查询")
@GetMapping("/page")
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
log.info("员工分页查询,参数为:{}",employeePageQueryDTO);
PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
return Result.success(pageResult);
}
service层:
//员工分页查询
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
//开始分页查询,插件省去字符串的拼接
PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
long total = page.getTotal();
List<Employee> records = page.getResult();
return new PageResult(total,records);
}
sql语句:
<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 asc
</select>
前后端联调:
结果优化,代码完善,对操作时间进行完善:
对日期进行格式化:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
或者在WebMvcConfiguration中扩展SpringMVC的消息转换器,统一对日期类型进行格式化处理:
//扩展SpringMVC框架的消息转换器,日期类型的格式化
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("拓展消息转换器...");
//创建一个消息转换器
MappingJackson2HttpMessageConverter convertor = new MappingJackson2HttpMessageConverter();
//需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
convertor.setObjectMapper(new JacksonObjectMapper());
//将自己的消息转换器加入容器中
converters.add(0,convertor);
}
controller层:
/**
* 启用禁用员工账号
* @param status
* @param id
* @return
*/
@ApiOperation(value = "启用禁用员工账号")
@PostMapping("/status/{status}")
public Result startOrStop(@PathVariable("status") Integer status,Long id){
log.info("启用禁用员工账号:{},{}",status,id);
employeeService.startOrStop(status,id);
return Result.success();
}
service实现层:
/**
* 启用禁用员工账号
* @param status
* @param id
*/
@Override
public void startOrStop(Integer status, Long id) {
// update employee set status = ? where id = ?
//动态更新,构造一个实体类
Employee build = Employee.builder()
.status(status)
.id(id)
.build();
employeeMapper.update(build);
}
数据层:(动态Sql语句,便于重复利用)
<update id="update" parameterType="com.sky.entity.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>
编辑员工信息功能涉及到两个接口:
1、根据id查询员工信息(用于页面的回显)
2、编辑员工信息(更新到数据库)
controller层:
/**
* 根据id查询员工信息
* @param id
* @return
*/
@ApiOperation(value = "根据id查询员工信息")
@GetMapping("/{id}")
public Result<Employee> getById(@PathVariable Long id){
Employee employee = employeeService.getById(id);
return Result.success(employee);
}
/**
* 编辑员工信息
* @param employeeDTO
* @return
*/
@ApiOperation(value = "编辑员工信息")
@PutMapping
public Result update(@RequestBody EmployeeDTO employeeDTO){
log.info("编辑员工信息,{}",employeeDTO);
employeeService.update(employeeDTO);
return null;
}
service实现层:
/**
* 根据id查询员工信息
* @param id
* @return
*/
@Override
public Employee getById(Long id) {
Employee employee = employeeMapper.getById(id);
employee.setPassword("******");
return employee;
}
/**
* 编辑员工信息
* @param employeeDTO
*/
@Override
public void update(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO,employee);
employee.setUpdateUser(BaseContext.getCurrentId());
employee.setUpdateTime(LocalDateTime.now());
employeeMapper.update(employee);
}
Dao、mapper层:(update重用动态sql代码)
/**
* 根据id查询员工信息
* @param id
* @return
*/
@Select("select * from employee where id=#{id}")
Employee getById(Long id);
菜品分类管理模块业务规则:
1、分类名称必须是唯一的
2、分类按照类型可以分为菜品分类和套餐分类
3、新添加的分类状态默认为”禁用“
接口设计:
1、新增分类
2、分类分页查询
3、根据id删除分类
4、修改分类
5、启用禁用分类
6、根据类型查询分类
导入分类管理模块功能代码: