curd,全局异常,返回Json序列格式化(时间,Long精度),公共字段自动更新(ThreadLocal)

新增

    @PostMapping
    public R<String> save(@RequestBody Employee employee, HttpServletRequest request) {

        log.info("新增员工 {}", employee.toString());

        //初始密码,加密处理
        employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));

        //员工信息补全
        Long empId = (Long) request.getSession().getAttribute("employee");
        employee.setCreateUser(empId);
        employee.setUpdateUser(empId);
        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());

        employeeService.save(employee);
        log.info("新增员工成功");
        return R.success("新增员工成功");
    }

全局异常设置

/**
 * 全局异常处理类
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class}) //通知,拦截类上加了@RestController,@Controller注解的异常
@ResponseBody//返回Json格式
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 差异处理方法
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){

        log.error(ex.getMessage());

        if (ex.getMessage().contains("Duplicate entry")){ //sql返回的username重复错误提示
            String[] split = ex.getMessage().split(" ");
            String msg = split[2]+"已存在";
            return R.error(msg);
        }

        return R.error("未知错误");
    }

}

分页查询

        1.配置拦截器

/**
 * 配置分页插件
 */
@Configuration
public class MybatisPlusConfig {

    /**
     * 添加分页拦截器
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }

}

        2.分页查询

  /**
     * 分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")   //http://localhost:8080/employee/page?page=1&pageSize=10&name=
    public R<Page> page(int page, int pageSize, String name) {
        log.info("分页查询 page:{},pageSize{},name:{}", page, pageSize, name);

        //构造分页构造器
        Page pageInfo = new Page(page,pageSize);

        //构造条件构造器
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();
        //添加过滤条件
        queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
        //添加排序条件
        queryWrapper.orderByDesc(Employee::getUpdateTime);

        employeeService.page(pageInfo, queryWrapper);//pageInfo已封装数据

        return R.success(pageInfo);
    }

用户根据Id的update接口

 @PutMapping
    public R<String> update(HttpServletRequest request,@RequestBody Employee employee){

        log.info("修改{}",employee.getId());

        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser((Long) request.getSession().getAttribute("employee"));
        employeeService.updateById(employee);

        return R.success("员工已更新");
    }

Long型数据响应到页面只能保证16位的精度,

修复步骤

1,提供JacksonObjectMapper,其还可以对LocalDateTime序列化为xxxx年xx月休息日

2在WebMvcConfig配置扩展Spring mvc消息转化器,加入acksonObjectMapper

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);
    }
}
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /**
     * 设置静态资源
     *
     * @param registry
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始静态资源映射配");

        //请求路径xxx/backed/xxx指向静态资源calsspath:/backed/
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        //同理
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");

    }


    /**
     * 扩展mvc的消息转换器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,用Json将java格式转换
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将转换器添加到mvc框架的转换器集合中
        converters.add(0,messageConverter); //0为加到开头

    }

编辑数据,先根据Id查询,在调用已写的修改接口即可

    @GetMapping("/{id}")
    public R<Employee> getById(@PathVariable int id){
        log.info("准备修改id:{}数据",id);
        Employee employee = employeeService.getById(id);
        return R.success(employee);
    }

mybayide-plus提供字段自动填充

                1.实体类加入@TableField注解

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

           如下:     

  @TableField(fill = FieldFill.INSERT)
  private LocalDateTime createTime;

  @TableField(fill = FieldFill.UPDATE)
  private LocalDateTime updateTime;
/**
 * 自定义元数据对象处理器
 */
@Component //交给spring处理
@Slf4j
public class MyMetObjectthandler implements MetaObjectHandler {

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

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update]");

        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", BaseContext.getCurrentId());

        log.info(metaObject.toString());

    }
}

http请求的,对应服务会分配新线程,为获得修改人Id可以使用 ThreadLocal在用户登入时保存Id,使用时获取以下为ThreadLocal使用和登入代码修改


/**
 * 基于Local封装工具类,用于保持用户登入Id
 */
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();
    }
}


  //4.判断是否登入。登入放行
        Object employee = request.getSession().getAttribute("employee");

        if (employee!=null){
            BaseContext.setCurrentId((Long) employee);//当前登入用户的线程存入Id到ThreadLocal的副本中
            filterChain.doFilter(request,response);
            log.info("Id:{}已登入",employee);
            return;
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值