1. 新增员工的步骤
- 在
EmployeeController
类中创建save方法,封装数据,封装好之后传递给service方法进行调用 - 在
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);
}
- 调用Mapper层接口…
- 解析出登录用户ID后,如何传递给Service中的save方法?
- ThreadLocal并不是一个Thread,而是Thread的局部变量。
- ThreadLocal为每个线程提供了单独的一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问
- 通过调用
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]
- 解决方案:
- 在属性上添加注解,对日期进行格式化
- 在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); } }
- 在属性上添加注解,对日期进行格式化
启用禁用员工账号
- 在
EmployeeController类
中添加了一个名为 startOrStop 的方法,在此方法中调用ServiceImpl中的方法 - 在
Employess类
中考虑到更新操作的通用性,实现Mapper层的方法复用,采用了构造一个全新的员工对象 - 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>
编辑员工业务代码开发
- 首先根据id值查询出该员工的具体信息,做出页面回显效果
- 其次根据传递过来的数据,构造出一个新的Employee对象,使用
BeanUtils.copyProperties('被复制的对象','承接的对象')
- 调用Mapper层的update方法进行更新
导入分类模块功能代码
…