苍穹外卖项目开发流程
1 密码加密
password = DigestUtils.md5DigestAsHex(password.getBytes());
if (!password.equals(employee.getPassword())) {
//密码错误
throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
}
登录
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getAdminTokenName());
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:{}", empId);
BaseContext.setCurrentId(empId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
2 员工管理
2.1 异常
- sql 插入如果同名就会异常
SQLIntegrityConstraintViolationException
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
String msg = ex.getMessage();
if(msg.contains("Duplicate")){
String[] split = msg.split(" ");
return Result.error((String) split[2]+ MessageConstant.ALREADY_EXIST);
}
log.error("异常信息:{}", ex.getMessage());
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
2.2 新增员工获取操作人
- 通过 ThreadLocal 传递 id
- ThreadLocal 可以看成全局对象, 一个线程只对应一个 key, 所以一个线程上操作的值都是同一个;
- Springboot 每接收一个socket创建一个线程, 从interceptoer中的 preHandle 到controller 到 service 到 mapper 都是一个线程执行的, 因此可以通过 inteceptor 获取到id 后添加到 ThreadLocal 中;
在Inteceptor中 添加 id
BaseContext.setCurrentId(empId);
在Service实现类中获取id
Long currentId = BaseContext.getCurrentId();
2.3 分页查询
<select id="list" 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>
2.3.1 日期格式
- springboot 版本低才会出现日期问题

@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// super.extendMessageConverters(converters);
MappingJackson2HttpMessageConverter msgConverter = new MappingJackson2HttpMessageConverter();
msgConverter.setObjectMapper(new JacksonObjectMapper());
converters.add(0,msgConverter);
log.info("扩展消息转换器");
}
/**
* 对象映射器:基于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);
}
}
修改状态
- 涉及修改只使用一个函数
<update id="update">
update employee <set>
<if test="name!=null and name!=''">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>
属性拷贝
DTO 转实体对象时,可以使用 Spring 的 BeanUtils.copyProperties 减少重复赋值代码。
BeanUtils.copyProperties(employeeDTO, employee);