[瑞吉外卖]03-员工模块

新增员工

需求分析

后台系统中可以管理员工信息, 通过新增员工来添加后台系统用户, 点击[添加员工]按钮跳转到新增页面

  1. 新增员工就是将页面录入的员工数据插入到employee表
  2. username字段加入了唯一约束, 因为username是员工的登录账号, 必须唯一

代码编写

@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    /**
     * 新增员工
     * @param employee
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody Employee employee, HttpServletRequest request) {
        log.info("新增员工,员工信息:{}", employee.toString());

        //设置初始密码123456,进行MD5加密
        employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());
        //获取当前登录用户的id
        Long empId = (Long) request.getSession().getAttribute("employee");
        employee.setCreateUser(empId);
        employee.setUpdateUser(empId);

        employeeService.save(employee);
        return R.success("新增员工成功");
    }
}
  1. 页面发送请求, 将新增的员工数据以JSON的形式提交到服务端
  2. 服务端Controller接受页面的参数, 并调用Service保存数据
  3. Service调用Mapper操作数据库

全局异常处理

因为username字段要求唯一, 当username重复时, 数据插入操作就会报错, 最后返回给前端

/**
 * 全局异常处理类
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

     /**
     * 异常处理方法
     * @param ex
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex) {
        log.error(ex.getMessage());
        if(ex.getMessage().contains("Duplicate entry")) {
            String[] split = ex.getMessage().split(" ");
            String msg = split[2] + "已存在";
            return R.error(msg);
        }
        return R.error("未知错误");
    }
}
  1. 通过 @ControllerAdvice(annotations() 注解指定异常处理类生效的范围
  2. 此处: 只要添加了RestController注解 和 Controller注解的方法就会生效
  3. 通过 @ExceptionHandler() 注解指定拦截的异常类型

分页查询

需求分析

当数据量比较大时, 一个页面展示所有数据会比较乱,不便于查看, 所以一般采用分页的形式展示数据

代码开发

配置分页插件: 使用mybatis-plus提供的分页插件进行分页查询

/**
 * 配置MP的分页插件
 */
@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        // 创建拦截器对象
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 创建分页拦截器并添加到给拦截器对象
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        // 返回拦截器对象
        return mybatisPlusInterceptor;
    }

}
  1. 使用 @Configuration注解标明配置类
  2. 使用 @Bean注解 把拦截器对象交给IOC容器管理
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    /**
     * 员工信息分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name) {
        log.info("page = {}, pageSize = {}, name = {}", page, pageSize, name);
        //构建分页构造器
        Page pageInfo = new Page(page, pageSize);

        //构建条件构造器
        LambdaQueryWrapper<Employee> queryChainWrapper = new LambdaQueryWrapper();
        //添加过滤条件
        queryChainWrapper.like(StringUtils.isNotEmpty(name), Employee::getName, name);
        //添加排序条件
        queryChainWrapper.orderByDesc(Employee::getUpdateTime);

        //执行查询
        employeeService.page(pageInfo, queryChainWrapper);
        return R.success(pageInfo);
    }
}
  1. StringUtils.isNotEmpty()方法来自 org.apache.commons.lang.StringUtils 包

功能测试

前后端联调测试

启用/禁用

需求分析

在员工管理列表页面,可以对某个员工账号进行启用或者禁用操作。账号禁用的员工不能登录系统,启用后的员工可以正常登录。

需要注意,只有管理员(admin用户)可以对其他普通用户进行启用、禁用操作,所以普通用户登录系统后启用禁用按钮不显示。

代码开发


@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    /**
     * 根据id修改员工信息
     * @param employee
     * @param request
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody Employee employee, HttpServletRequest request) {
        log.info(employee.toString());
        // 拿到当前用户的session
        Long empId = (Long) request.getSession().getAttribute("employee");
        // 补充基础字段信息
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(empId);
        // 执行更新操作
        employeeService.updateById(employee);
        // 返回结果
        return R.success("员工信息修改成功");
    }
}

功能测试

通过测试, 发现员工账号的状态并没有被更新, 经过排查, 发现前端传递过来的id是失真的, 导致无法正确更新

  1. 前端对于整数最大保留16位, 超过的话就会进行四舍五入的处理, 最终造成ID的失真
  2. 我们在服务端, 给页面响应JSON数据时进行处理, 将long型数据统一转成String

代码修复

提供对象转换器JacksonObjectMapper, 基于jackson实现java对象到json数据的转换

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);


        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))

                .addSerializer(BigInteger.class, ToStringSerializer.instance)
                .addSerializer(Long.class, ToStringSerializer.instance)
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}
  1. ObjectMapper是jackson提供的类, 通过这个类就可以把java对象转成Json对象, 要继承这个类
  2. addSerializer(Long.class, ToStringSerializer.instance)
  • addSerializer()方法就是用来添加序列化器
  • Long.class是在指定数据类型
  • ToStringSerializer.instance是在指定序列化器
  • 在序列化的过程中, 遇到Long型数据, 就转成String类型数据
  1. 还额外处理了时间类型和日期类型的数据, 使时间日期数据更好的展示

在WebMvcConfig配置类中扩展Spring Mvc的消息转换器, 在消息转换器中把java象序列化成json数据

@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    
    /**
     * 扩展mvc框架的消息转换器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 创建消息转换器
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        // 设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        // 将上面的消息转换器添加到mvc框架的转换器集合中
        // 0代表加入到掐面,优先执行
        converters.add(0, messageConverter);
    }
}

编辑员工

需求分析

在员工管理列表页面点击编辑按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击保存按钮完成编辑操作

代码开发

@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    /**
     * 根据id修改员工信息
     * @param employee
     * @param request
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody Employee employee, HttpServletRequest request) {
        log.info(employee.toString());
        // 拿到当前用户的session
        Long empId = (Long) request.getSession().getAttribute("employee");
        // 补充基础字段信息
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(empId);
        // 执行更新操作
        employeeService.updateById(employee);
        // 返回结果
        return R.success("员工信息修改成功");
    }

    /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<Employee> getById(@PathVariable Long id) {
        log.info("根据id查询员工信息...");
        Employee employee = employeeService.getById(id);

        if (employee != null) {
            return R.success(employee);
        }

        return R.error("没有查询到对应员工信息");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值