• 瑞吉外卖项目实战Day02


    瑞吉外卖项目实战Day02

    1.添加员工信息

    返回添加成功的信息

        //新增员工
        @PostMapping
        private R save(HttpServletRequest request,@RequestBody Employee employee){
    
            //同一设定初始密码MD5加密
         employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
            //设置创建时间
           employee.setCreateTime(LocalDateTime.now());
    //        //更新时间
           employee.setUpdateTime(LocalDateTime.now());
            //创建人
         Long employee1 = (Long)request.getSession().getAttribute("employee");
    
          employee.setCreateUser(employee1);
           employee.setUpdateUser(employee1);
    
          
    
    //数据库添加
            employeeService.save(employee);
            return R.success("添加成功");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    当出现账号相同的情况,会报sql异常

    Duplicate entry ‘baixiaoyun’ for key ‘employee.idx_username’] with root cause

    处理方法:

    定义一个异常处理器捕获全局的异常进行处理

    //全局异常处理
    @ControllerAdvice(annotations = {RestController.class, Controller.class})
    @ResponseBody
    public class GloableExceptionHandler {
    
    
        //捕获异常进行处理
        @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
        public R<String> exception(SQLIntegrityConstraintViolationException ex){
            //判断异常信息里面是否是Duplicate entry(名字重复)
            if (ex.getMessage().contains("Duplicate entry")){
                // 异常信息:Duplicate entry 'admin' for key 'employee.idx_username'
                String msg=ex.getMessage().split(" ")[2]+"已存在";
                return R.error(msg);
            }
            return R.error("未知错误");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20220728144848982

    image-20220728144631716

    2.分页展示和模糊查询

    并且按照更新的时间进行排序

    1.配置MybatisPlus的分页插件

    @Configuration
    //配置MybatisPlus分页插件
    public class MybatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
    
            MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
            mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
            return mybatisPlusInterceptor;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.做分页查询

        //分页查询
        @GetMapping("/page")
      public R<Page> page( int page,int pageSize,String name){
    
            //配置分页构造器
            //当前页,当前页的大小
            Page pageInfo=new Page(page,pageSize);
            //条件过滤器
            LambdaQueryWrapper<Employee> queryWrapper=new LambdaQueryWrapper();
            queryWrapper.like(name!=null,Employee::getName,name);
            //添加排序条件--更新时间
            queryWrapper.orderByDesc(Employee::getUpdateTime);
    
            employeeService.page(pageInfo,queryWrapper);
            return  R.success(pageInfo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.启用/禁用员工账号

    //修改员工信息
        @PutMapping
        public R update(HttpServletRequest request,@RequestBody Employee employee){
    
            employee.setUpdateTime(LocalDateTime.now());
            Long employeeId=(Long)request.getSession().getAttribute("employee");
            employee.setUpdateUser(employeeId);
            employeeService.updateById(employee);
            return R.success("员工信息修改成功");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    但是:当我们点击禁用,账号并没有被禁用

    原因:

    image-20220730102620975

    image-20220730102656491

    js对long型数据进行处理时会导致丢失精度,导致提交的id和数据库的id不一致

    解决办法:

    long类型数据统一转为String字符串

    导入一个对象映射器:

    /**
     * 对象映射器:基于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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在WebMvcConfig类(继承WebMvcConfigurationSupport)中

    //扩展MVC框架的消息转换器
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
      //创建消息转换器对象
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter=new MappingJackson2HttpMessageConverter();
       //设置对象转换器,底层使用Jackson将对象转为JSON
        mappingJackson2HttpMessageConverter.setObjectMapper(new JacksonObjectMapper());
       //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0,mappingJackson2HttpMessageConverter);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.编辑员工信息

    1.回显数据

    根据id查询数据

    //根据id查询员工信息
    @GetMapping("/{id}")
    public R<Employee> getById(@PathVariable Long id){
        Employee byId = employeeService.getById(id);
       if (byId!=null){
           return R.success(byId);
       }
       return R.error("没有查询到员工信息");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.修改数据

    直接会调用

    //修改员工信息
        @PutMapping
        public R update(HttpServletRequest request,@RequestBody Employee employee)
    
    • 1
    • 2
    • 3

    进行修改

    4.代码优化

    由于每次更新和新增都需要设置时间和更新人的id,代码重复

    解决办法:

    公共字段自动填充

    实现步骤:

    1.在实体类的属性中加入@TableField,指定为自动填充的策略

    @TableField(fill = FieldFill.INSERT)//插入时填充字段
    private LocalDateTime createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新填充字段
    private LocalDateTime updateTime;
    
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.按照框架要求编写元数据对象处理器,在此类中同一为公共字段赋值,此类需要实现MetaObjectHandler接口

    //元数据对象处理器
    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            metaObject.setValue("createTime", LocalDateTime.now());
            metaObject.setValue("updateTime",LocalDateTime.now());
            metaObject.setValue("createUser",new Long(1));//先默认设置为1,后期优化
            metaObject.setValue("updateUser",new Long(1));
            
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    将添加和修改方法中有关更新时间和修改人的id的部分删除即可

    优化公共字段填充

    ThreadLocal:

    ThreadLocal并不是一个Thread,而是Thread的局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立的改变自己的副本而不会影响其他线程对应的副本。TheadLocal为每个线程提供单独的一份存储空间,具有线程隔离的效果,只有在线程内才能获取对应的值,线程外则不能访问

    实现步骤:

    //基于ThreadLocal封装工具类,用保存和获取当前登陆的id
    
    public class BaseContext {
        private static ThreadLocal<Long> threadLocal=new ThreadLocal<>();
        public static void setCuttrntid(Long id){
            threadLocal.set(id);
        }
        public static Long getCuttrntid(){
    
            return threadLocal.get();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    //元数据对象处理器
    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            metaObject.setValue("createTime", LocalDateTime.now());
            metaObject.setValue("updateTime",LocalDateTime.now());
            metaObject.setValue("createUser",BaseContext.getCuttrntid());
            metaObject.setValue("updateUser",BaseContext.getCuttrntid());
    
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    Java客户端_zkclient库操作Zookeeper
    #分支语句详解
    信息收集分类
    【10. 信号量和管程】
    AQS介绍
    从输入URL到网页显示,期间发生了什么(详解)
    机器学习强基计划2-3:图文详解决策树预剪枝、后剪枝原理+Python实现
    python KNN分类算法实战(使用鸢尾花数据集)
    DHCP协议从入门到部署DHCP服务器进行实验
    【数据结构】树状数组C++详解
  • 原文地址:https://blog.csdn.net/qq_57907966/article/details/126069940