资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

Aop+自定义注解实现接口限制

Java 更新时间: 发布时间: 计算机考试归档 最新发布

Aop+自定义注解实现接口限制

目录

1.创建@Limit注解

2.自定义切面

3.解决依赖问题

        (1).HttpStatus.MAXLIMIT 

        (2).NetworkUtils

        (3).ResponseUtil

4.使用 

5.运行错误可能的原因


1.创建@Limit注解

package com.mimiwang.common.annotation;import java.lang.annotation.*;import java.util.concurrent.TimeUnit;@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Limit {//    redisKey    String key() default "";//    最大次数    int num() default 5;//    过期时效    int duration() default 3;//    时间单位    TimeUnit timeUnit() default TimeUnit.MINUTES;}

2.自定义切面

package com.mimiwang.common.aop;import com.mimiwang.common.annotation.Limit;import com.mimiwang.common.constant.HttpStatus;import com.mimiwang.common.utils.NetworkUtils;import com.mimiwang.common.utils.ResponseUtil;import lombok.extern.slf4j.Slf4j;import org.apache.logging.log4j.util.Strings;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.lang.reflect.Method;import java.util.concurrent.TimeUnit;@Aspect@Component@Slf4jpublic class LimitAspect {    @Autowired    RedisTemplate redisTemplate;    @Pointcut("@annotation(com.mimiwang.common.annotation.Limit) || @within(com.mimiwang.common.annotation.Limit)")    void test(){    }    @Around("test()")    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {        MethodSignature signature = (MethodSignature) joinPoint.getSignature();        Method method = signature.getMethod();//        获取方法注解        Limit annotation = method.getAnnotation(Limit.class);//        获取注解参数        String preKey = annotation.key();        int maxNum = annotation.num();        int duration = annotation.duration();        TimeUnit timeUnit = annotation.timeUnit();//        如果没有设置key,则默认 key=类名:方法名:ip        if(Strings.isBlank(preKey)){            preKey=signature.getDeclaringTypeName()+":"+method.getName();        }//        获取ServletRequestAttributes        ServletRequestAttributes requestAttributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();        HttpServletRequest request = requestAttributes.getRequest();        HttpServletResponse response = requestAttributes.getResponse();//        获取ip        String ip = NetworkUtils.getIpAddress(request);        String key= preKey+":"+ip;//        redis获取        Object o = redisTemplate.opsForValue().get(key);//        第一次访问        if(o == null){//            设置redis            redisTemplate.opsForValue().set(key,1,duration,timeUnit);            log.info("[Limit] [key]:{} |  [Num]:{} |  Status:{} |  Max:{}",key,1,"ok",maxNum);//            放行            return joinPoint.proceed(joinPoint.getArgs());        }else {            int num=(int)o;//            达到最大次数,禁止访问            if( num == maxNum){                log.error("[Limit] [key]:{} |  [Num]:{} |  Status:{} |  Max:{}",key,num,"Ban",maxNum);                return this.returnLimit();            }//            未达到最大值, 值+1            Long increment = redisTemplate.opsForValue().increment(key);            log.info("[Limit] [key]:{} |  [Num]:{} |  Status:{} |  Max:{}",key,increment,"ok",maxNum);//            放行            return joinPoint.proceed(joinPoint.getArgs());        }    }//    错误响应    public String returnLimit() throws IOException {        HttpStatus MAXLIMIT = HttpStatus.MAXLIMIT;        return ResponseUtil.errorJSONData(MAXLIMIT.getCode(), MAXLIMIT.getMsg());    }}

3.解决依赖问题

此处说明

        (1).HttpStatus.MAXLIMIT 

        枚举类型

public enum  HttpStatus {    MAXLIMIT(403,"限制最大访问次数");    private String msg;    private int code;    private HttpStatus(int code, String msg) {        this.code=code;        this.msg=msg;    }    public int getCode(){        return this.code;    }    public String getMsg(){        return this.msg;    }}

        (2).NetworkUtils

        自定义Utils,用于获取请求ip

public class NetworkUtils {    public static String getIpAddress(HttpServletRequest request) {        String ip = request.getHeader("x-forwarded-for");        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("Proxy-Client-IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("WL-Proxy-Client-IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("HTTP_CLIENT_IP");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getHeader("HTTP_X_FORWARDED_FOR");        }        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();        }        // 如果是多级代理,那么取第一个ip为客户端ip        if (ip != null && ip.contains(",")) {            ip = ip.substring(0, ip.indexOf(",")).trim();        }        return ip;    }}

        (3).ResponseUtil


        基于fastjson的自定义响应包装类

import com.alibaba.fastjson.JSONObject;public class ResponseUtil extends JSONObject {    public static BaseUtil successJSONObject(String msg){        return successJSONObject(msg,null);    }    public static BaseUtil successJSONObject(String msg, Object data){        return successJSONObject(200,msg,data);    }    public static BaseUtil successJSONObject(int code,String msg, Object data){        return new BaseUtil(code, msg, data);    }    public static BaseUtil errorJSONObject(String msg){        return errorJSONObject(msg,null);    }    public static BaseUtil errorJSONObject(String msg, Object data){        return errorJSONObject(500,msg,data);    }    public static BaseUtil errorJSONObject(int code,String msg, Object data){        return new BaseUtil(code, msg, data);    }    public static String successJSONData(int code, String msg, Object data){        return toJSONString(new BaseUtil(code, msg, data));    }    public static String successJSONData(String msg, Object data){        return toJSONString(new BaseUtil(200,msg,data));    }    public static String successJSONData(Object data){        return toJSONString(new BaseUtil(200,"请求成功",data));    }    public static String successJSONData(){        return toJSONString(new BaseUtil(200,"操作成功",null));    }    public static String errorJSONData(int code, String msg, Object data){        return toJSONString(new BaseUtil(code,msg,data));    }    public static String errorJSONData(String msg, Object data){        return toJSONString(new BaseUtil(500,msg,data));    }    public static String errorJSONData(int code, String msg){        return toJSONString(new BaseUtil(code,msg,null));    }    public static String errorJSONData(){        return toJSONString(new BaseUtil(500,"系统异常,操作失败!",null));    }    public static String errorJSONData(String msg){        return toJSONString(new BaseUtil(500,msg,null));    }    public static Class getResponseClass(){        return BaseUtil.class;    }    public static class BaseUtil{                private int code;                private String msg;                private Object data;        public BaseUtil(int code, String msg, Object data) {            this.code = code;            this.msg = msg;            this.data = data;        }        public int getCode() {            return code;        }        public void setCode(int code) {            this.code = code;        }        public String getMsg() {            return msg;        }        public void setMsg(String msg) {            this.msg = msg;        }        public Object getData() {            return data;        }        public void setData(Object data) {            this.data = data;        }    }}

4.使用 

默认

@Limit()
@RestController@RequestMapping("/animal")public class AnimalController {    @Autowired    private ApplicationContext applicationContext;    @Autowired    IAnimalService animalService;    @Autowired    LoginAspect loginAspect;    @Limit()    @GetMapping("/info/id/{id}")    public String getAnimalById(@PathVariable long id){        return ResponseUtil.successJSONData(animalService.selectAnimalById(id));    }}

自定义 

@Limit(key = "aniInfo",num = 3,duration = 20,timeUnit = TimeUnit.SECONDS)
@RestController@RequestMapping("/animal")public class AnimalController {    @Autowired    IAnimalService animalService;    @Limit(key = "aniInfo",num = 3,duration = 20,timeUnit = TimeUnit.SECONDS)    @GetMapping("/info/id/{id}")    public String getAnimalById(@PathVariable long id){        return ResponseUtil.successJSONData(animalService.selectAnimalById(id));    }}

5.运行错误可能的原因

(1).yaml没有配置redis

(2).LimitAspect没被扫描到

多模块下,A模块使用B模块Component,则A模块启动类需要加上@ComponentScan注解

参考:SpringBoot关于多模块调用其他模块自定义的bean_引用另一个模块的bean_要加油!的博客-CSDN博客

转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/1097072.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【Aop+自定义注解实现接口限制】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2