黑马 - 苍穹外卖 Day02

1. 新增员工的步骤

  1. EmployeeController类中创建save方法,封装数据,封装好之后传递给service方法进行调用
  2. EmployeeServiceImpl接口实现类中实现save方法,在调用mapper层进行向数据库填充数据
/*
     * 新增员工
     * */
    public void save(EmployeeDTO employeeDTO) {
        // 创建数据库表对应的实体对象
        Employee employee = new Employee();
        // 使用Spring提供的工具类,来快速克隆两个类中属性名一致的字段
        BeanUtils.copyProperties(employeeDTO, employee);

        /*
            额外设置employeeDTO 与 employee 相差的属性
        */

        // 设置密码 --- 密码默认为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);
    }
  1. 调用Mapper层接口…
  2. 解析出登录用户ID后,如何传递给Service中的save方法?
    • ThreadLocal并不是一个Thread,而是Thread的局部变量。
    • ThreadLocal为每个线程提供了单独的一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问
  3. 通过调用BaseContext类中的方法实现将用户ID保存到当前线程中,以便service方法获取到当前用户的ID(当前用户ID通过JWT令牌所生成的token解析出来)
// BaseContext
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();
    }

}

二、员工分页查询

问题:返回的JSON数据中时间的格式为 “createTime”: [2024,3,5,15,6,24]

  • 解决方案:
    1. 在属性上添加注解,对日期进行格式化
      在这里插入图片描述
    2. 在WebMvcConfiguration中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理
    // 
    /*
    * 扩展Spring MVC框架的消息转换器
    * 作用:
    *   后端返回给前端的数据进行统一的转换处理
    * */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 自己创建了一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    
        // 需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为JSON数据
        converter.setObjectMapper(new JacksonObjectMapper());
    
        // 将自己的消息转换器加入到容器中
        /*
        * 框架自带了一些消息转换器,直接add()的话那么自定义转换器会被排在最后一个,默认是使用不到的
        * 如果不提高自定义转换器的优先级,那么默认是使用不到的
        * 如果添加的索引为0,代表我们自定义的转换器被排在了第一位,优先使用
        * */
        converters.add(0,converter);
    }
    
    //JacksonObjectMapper 类
    package com.sky.json;
    
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
    import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
    import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
    
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    
    import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
    
    /**
     * 对象映射器:基于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_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
        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(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. EmployeeController类中添加了一个名为 startOrStop 的方法,在此方法中调用ServiceImpl中的方法
  2. Employess类中考虑到更新操作的通用性,实现Mapper层的方法复用,采用了构造一个全新的员工对象
  3. Mapper层:用动态SQL来判断哪些值需要被修改,哪些不会被修改
// EmployeeServiceImpl
 /*
     * 启用禁用员工账号
     *
     * */
    @Override
    public void startOrStop(Integer status, Long id) {
        // 为了更新操作的通用性,选择构建一个Employee对象
        // 为什么要这么做?
        /*
         * 1. 为了通用性
         * 2. 可以根据传递参数的不同从而修改到多个字段
         * */

        /*
            * 创建一个Employee实体对象
            * 与 new Employee.setStatus(status)...所达成的效果是一致的
            * 想要使用这种方法构建对象需要在实体类中添加 @Builder 注解
        */
        Employee employee = Employee.builder()
                .id(id)
                .status(status)
                .build();

        employeeMapper.update(employee);
    }
	// EmployeeMapper
    // 更新操作,根据主键(ID)来动态修改属性
    void update(Employee employee);
    
    // EmployeeMapper.xml
    <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">
                idNumber = #{idNumber},
            </if>
            <if test="updateTime != null">
                updateTime = #{updateTime},
            </if>
            <if test="updateUser != null">
                updateUser = #{updateUser},
            </if>
            <if test="status != null">
                status = #{status}
            </if>
        </set>
        where id = #{id}
    </update>

编辑员工业务代码开发

  1. 首先根据id值查询出该员工的具体信息,做出页面回显效果
  2. 其次根据传递过来的数据,构造出一个新的Employee对象,使用BeanUtils.copyProperties('被复制的对象','承接的对象')
  3. 调用Mapper层的update方法进行更新

导入分类模块功能代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值