学习日记4 2022.11.07

1.员工退出

清除登录时存入的session

/**
 * 员工退出方法
 *
 * @param request
 * @return
 */
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request) {
    //清除session
    request.getSession().removeAttribute("emp");
    return R.success("退出成功");
}

2.后端拦截器(防止用户直接访问后台页面,不经过登录)

* 全局异常处理
 * ControllerAdvice控制器通知(AOP)
 * @RequestBody和@ControllerAdvice
 **/
@Slf4j
@RestControllerAdvice(annotations = {Controller.class, RestController.class})
public class GlobalExceptionHandler {

    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException exception){
        log.info(exception.getMessage());
        if(exception.getMessage().contains("Duplicate entry")){
            String[] s = exception.getMessage().split(" ");
            String msg = "账号" + s[2] + "已存在";
            return R.error(msg);
        }
        return R.error("未知的错误");
    }
}

3.新增员工

/**
 * 新增员工
 *
 * @param employee
 * @return
 */
@PostMapping()
public R<String> save(HttpServletRequest request, @RequestBody Employee employee) {
    log.info("新增员工:{}", employee.toString());
    //设置初始密码,加密
    employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));


    //设置创建时间
    employee.setCreateTime(LocalDateTime.now());
    employee.setUpdateTime(LocalDateTime.now());


    //设置创建人
    Long empID = (Long) request.getSession().getAttribute("emp");
    employee.setCreateUser(empID);
    employee.setUpdateUser(empID);


    employeeService.save(employee);
    return R.success("添加员工成功");
}

4.分页查询

/**
 *  分页查询
 */
@GetMapping("/page")
public R<Page> page(HttpServletRequest request, Integer page, Integer pageSize, String name){
    log.info("员工{} page: {} pageSize:{}",(Long)request.getSession().getAttribute("emp"),page,pageSize);

    //创建分页构造器
    Page pageInfo = new Page(page,pageSize);
    //如果查询条件name不为空,则添加过滤条件 like
    LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
    if(name != null){
        queryWrapper.like(Employee::getName,name);
    }
    //排序条件orderBy
    queryWrapper.orderByDesc(Employee::getUpdateTime);

    //执行查询(查询之后page里面就封装了此次查询的所有结果包括总记录数等等...前端可以自取)
    employeeService.page(pageInfo, queryWrapper);
    return R.success(pageInfo);
}

5.修改员工状态

@PutMapping
public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
    log.info("修改用户{}",employee.toString());
    //修改 修改记录
    Long updateUserId = (Long) request.getSession().getAttribute("emp");
    employee.setUpdateUser(updateUserId);
    employee.setUpdateTime(LocalDateTime.now());

    //修改信息
    employeeService.updateById(employee);

    return R.success("员工信息修改成功");
}

6.修改员工状态时的bug

之前新创建员工id时使用的雪花算法,有19位数字,当数据传给前端之后后面的数字会被四舍五入,导致需要修改信息的时候无法根据id查询.

解决:

1.加入对象映射器

/**
 * 对象映射器:基于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);
    }
}

2.扩展MVC的转换器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    /**
     * 扩展MVC转换器
     * @param converters
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("配置扩展MVC消息转换器...");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //把上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0,messageConverter);
    }
}

7.修改信息数据回显

/**
 * 修改员工信息时,数据回显
 * @param id
 * @return
 */
@GetMapping("/{id}")
public R<Employee> getById(@PathVariable Long id){
    log.info("用户id:{}数据已回显",id);
    Employee employee = employeeService.getById(id);
    if(employee!=null){
        return R.success(employee);
    }
    return R.error("未查询到员工信息");
}

8.设置修改人和修改时间会出现重复代码

MP提供解决方法

1.在实体类加入TableField注解,指定自动填充策略

2.编写元数据对象处理器,在此类统一为公共字段赋值,此类实现MetaObjectHandler接口

//FieldFill.INSERT插入时填充  FieldFill.INSERT_UPDATE插入和修改时自动填充
@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;
/**
 * @author MaiDou
 * @version 1.0
 * @date 2022/11/7 22:04
 * 自定义元数据对象处理器
 **/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入时自动填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        Long id = BaseContext.getCurrentId();
        log.info("公共字段自动填充 Insert  {}",metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("createUser", id);
        metaObject.setValue("updateUser", id);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        Long id = BaseContext.getCurrentId();
        log.info("公共字段自动填充 update {}",metaObject.toString());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", id);
    }
}

而获取修改人id时需要ThreadLocal类(线程的局部变量)可以携带信息(每次请求会开启一个线程处理,dofilter 和 登录拦截器可以验证)

1.创建BaseContext工具类

public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }

    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

2.在登录拦截器里给BaseContext工具类里的ThreadLocal赋值

//3.判断是不是已经登录,已经登录,放行
if (request.getSession().getAttribute("emp") != null) {
    Long id = (Long) request.getSession().getAttribute("emp");
    BaseContext.setCurrentId(id);
    log.info("请求:{}用户id{}已登录,已放行",requestURI,request.getSession().getAttribute("emp"));
    filterChain.doFilter(request, response);
    return;
}

3.在元对象处理器里获取id,并赋值

@Override
public void insertFill(MetaObject metaObject) {
    Long id = BaseContext.getCurrentId();
    log.info("公共字段自动填充 Insert  {}",metaObject.toString());
    metaObject.setValue("createTime", LocalDateTime.now());
    metaObject.setValue("updateTime", LocalDateTime.now());
    metaObject.setValue("createUser", id);
    metaObject.setValue("updateUser", id);
}

@Override
public void updateFill(MetaObject metaObject) {
    Long id = BaseContext.getCurrentId();
    log.info("公共字段自动填充 update {}",metaObject.toString());
    metaObject.setValue("updateTime", LocalDateTime.now());
    metaObject.setValue("updateUser", id);
}

写完,睡觉去咯~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值