苍穹外卖项目开发流程

苍穹外卖项目开发流程

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);