自定义注解实现验证信息的功能

自定义注解实现验证逻辑

  • 导包
        <!-- hibernate 验证框架 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
  • 定义BO对象,前端传来的业务对象,对象中的属性需要校验
package com.imooc.boapi;

//import com.imooc.annotationcustom.VlogId;
import com.imooc.annotationcustom.VlogId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class VlogBOApi {
    private String id;
   @VlogId(message = "用户不存在,禁止插入视频")
    private String vlogerId;
    private String url;
    private String cover;
    private String title;
    private Integer width;
    private Integer height;
    private Integer likeCounts;
    private Integer commentsCounts;
}
  • 定义一个校验注解
package com.imooc.annotationcustom;




import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = VlogIdValidator.class) //校验的逻辑处理类
public @interface VlogId {
    String message();

    /**
     * 将validator进行分类,不同的类group中会执行不同的validator操作
     *
     * @return validator的分类类型
     */
    Class<?>[] groups() default {};

    /**
     * 主要是针对bean,很少使用
     *
     * @return 负载
     */
    Class<? extends Payload>[] payload() default {};
}

  • 同时需要一个校验类,实现一个注解检验的逻辑
package com.imooc.annotationcustom;

import com.imooc.mapper.UsersMapper;
import com.imooc.pojo.Users;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

@Slf4j
@Component
public class VlogIdValidator implements ConstraintValidator<VlogId, String> {


    @Autowired
    UsersMapper usersMapper;

    @Override
    public void initialize(VlogId constraintAnnotation) {
        log.info("注解逻辑初始化");
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        Users user = new Users();
        user.setId(s);
        Users reslut = usersMapper.selectByPrimaryKey(user);
        System.out.println("注解拦截生效+package com.imooc.annotationcustom;");
        if (reslut == null) {
            return false;
        } else {
            return true;
        }
    }

}

  • 业务代码
    @PostMapping("publish")
    public GraceJSONResult publish(@Valid @RequestBody VlogBOApi vlogBO) {

//        vlogService.createVlog(vlogBO);
        return GraceJSONResult.ok();
    }
  • 校验失败异常,定义一个全局异常捕获,将这个错误返回给前端
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public GraceJSONResult returnMethodArgumentNotValid(MethodArgumentNotValidException e) {
        BindingResult result = e.getBindingResult();
        Map<String, String> map = getErrors(result);
        return GraceJSONResult.errorMap(map);
    }

自定义注解来简化开发

目的:做一个点赞次数拦截的功能。过程:需要拦截以后自行确定多少时间内的点赞次数

  • 定义注解:
package com.imooc.annotationcustom;


import java.lang.annotation.*;


@Inherited
@Documented
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {
    /**
     * 时间内 秒为单位
     * @return
     */
    int second() default 10;

    /***
     * 允许访问次数
     * @return
     */

    int maxCount() default 5;
}
  • 拦截器代码,这里需要获取接口上的自定义注解handlerMethod.getMethodAnnotation
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod =  (HandlerMethod) handler;
            //获取RequestLimit注解
            RequestLimit requestLimit = handlerMethod.getMethodAnnotation(RequestLimit.class);
            if (null == requestLimit) {
                System.out.println("没有获取到注解");
                return true; //每加注解说明没有限制,多少次都ok
            }
            //限制的时间范围
            int seconds = requestLimit.second();
            //限制时间内的最大次数
            int maxCount = requestLimit.maxCount();
            //获取用户ip
            String userIp = IPUtil.getRequestIp(request);
            //判断redis中是否有ip
            boolean keyIsExist = redis.keyIsExist(LIKE_VLOG_OPERATE_COUNT + ":" + userIp);

            //如果没有这个键,说明当前用户在20s内没有点过赞,因为这个拦截器就是拦截点赞的后端接口,所以如果没有这个键就设置一个键
            if (keyIsExist == false) {
                redis.set(LIKE_VLOG_OPERATE_COUNT + ":" + userIp, "0", seconds);
                System.out.println("ok");
                return  true;
            }
            // 返回true,就要判断这个键对应的值的个数
            String res = redis.get(LIKE_VLOG_OPERATE_COUNT + ":" + userIp);
            if (Integer.valueOf(res) >= maxCount) {
                GraceException.display(ResponseStatusEnum.LIKE_VLOG_WAIT_ERROR);
                return false;
            }
        }





        return true;
    }
  • 业务代码
    @PostMapping("like")
    //TODO: 这里需要调试
    @RequestLimit(maxCount = 3, second = 60)
    public GraceJSONResult like(@RequestParam String userId,
                                @RequestParam String vlogerId,
                                @RequestParam String vlogId,
                                HttpServletRequest request) {
        vlogService.userLikeVlog(userId, vlogId);
        redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
        redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);

        redis.set(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId, "1");

        //------------------------------------------//
        //新增功能,限制点赞次数,
        String userIp = IPUtil.getRequestIp(request);
        redis.increment(LIKE_VLOG_OPERATE_COUNT + ":" + userIp,1);
        //-------------------------------------------//


        return GraceJSONResult.ok();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值