SpringBoot + Redis implementiert die Anti-Brushing-Funktion der Schnittstelle

Szenenbeschreibung:

        Wenn in der tatsächlichen Entwicklung das Front-End das Backend anfordert und die Back-End-Verarbeitung langsam ist, der Benutzer dies jedoch nicht weiß, verarbeitet das Back-End zu diesem Zeitpunkt noch, der Front-End-Benutzer denkt jedoch, dass dies der Fall ist wurde nicht angeklickt. Wenn er also erneut klickt und eine Anfrage initiiert, wird dies der Fall sein. Infolgedessen werden in kurzer Zeit viele Anfragen an den Hintergrund gesendet, und es können Probleme wie Hintergrundabstürze oder wiederholte Datenzugabe auftreten. Wie kann man dieses Problem lösen?

        Um den Zugriff auf eine Schnittstelle in kurzer Zeit zu vermeiden, können wir der Schnittstelle über AOP + benutzerdefinierte Annotation + Redis eine benutzerdefinierte Annotation hinzufügen und dann über die Vorbenachrichtigung von AOP einen Gültigkeitszeitraumwert in Redis speichern. Beim Zugriff auf die Schnittstelle , dieser Wert ist nicht abgelaufen und es wird eine Eingabeaufforderung an das Front-End zurückgegeben, um zu vermeiden, dass die Schnittstellenmethode in kurzer Zeit geändert wird.

        In diesem Artikel wird als Beispiel eine Datei-Download-Schnittstelle verwendet: Angenommen, der Datei-Download wird innerhalb von 20 Sekunden abgeschlossen. Speichern Sie beim ersten Download einen Schlüssel in Redis und legen Sie seine Ablaufzeit auf 20 Sekunden fest. Wenn nacheinander mehrere Anfragen gestellt werden, erscheint die Meldung: Der Zugriff ist zu häufig. Bereiten Sie zunächst eine Datei vor:

 

Umsetzungsprozess:

(1) Erstellen Sie eine benutzerdefinierte Annotation, die zwei Attribute enthält: eines ist der Schlüssel und das andere ist die Gültigkeitszeit des Schlüssels in Redis.


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LimitAccess {

    /**
     * 限制访问的key
     * @return
     */
    String key();

    /**
     * 限制访问时间
     * @return
     */
    int times();
}

(2) Erstellen Sie entsprechende Aspekte



import com.example.demo.anno.LimitAccess;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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 java.util.concurrent.TimeUnit;

/**
 * AOP类(通知类)
 */
@Component
@Aspect
public class LimitAspect {

    @Autowired
    private RedisTemplate redisTemplate;

    @Pointcut("@annotation(com.example.demo.anno.LimitAccess)")
    public void pt(){};

    @Around("pt()")
    public Object aopAround(ProceedingJoinPoint pjp) throws Throwable {
        // 获取切入点上面的自定义注解
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        // 获取方法上面的注解
        LimitAccess limitAccess = methodSignature.getMethod().getAnnotation(LimitAccess.class);
        // 获取注解上面的属性
        int limit = limitAccess.times();
        String key = limitAccess.key();
        // 根据key去找Redis中的值
        Object o = redisTemplate.opsForValue().get(key);
        // 如果不存在,说明是首次访问,存入Redis,过期时间为limitAccess中的time
        if (o == null) {
            redisTemplate.opsForValue().set(key, "", limit, TimeUnit.SECONDS);
            // 执行切入点的方法
            return pjp.proceed();
        } else {
            // 如果存在,说明不是首次访问,给出提示信息
            return  "访问过于频繁";
        }
    }
}

(3) Fügen Sie Anmerkungen zu den Schnittstellen hinzu, die eingeschränkt werden müssen, und legen Sie den Schlüssel und die eingeschränkte Zugriffszeit fest.

    @GetMapping("/download")
    @LimitAccess(key = "download_key", times = 20)
    public String downLoadFile(HttpServletRequest request, HttpServletResponse response) {
        FileInputStream inputStream = null;
        BufferedInputStream bufferedInputStream = null;
        OutputStream outputStream = null;
        try {
            File file = ResourceUtils.getFile("classpath:template/show.txt");
            if (file.exists()) {
                String fileName = file.getName();
                String mineType = request.getServletContext().getMimeType(fileName);
                response.setContentType(mineType);
                response.setHeader("content-type", "application/form-data");
                response.setHeader("Content-disposition", "attachment; fileName=" + fileName);
                inputStream = new FileInputStream(file);
                bufferedInputStream = new BufferedInputStream(inputStream);
                outputStream = response.getOutputStream();
                int len = 0;
                byte[] buff = new byte[1024];
                while ((len = bufferedInputStream.read(buff)) != -1) {
                    outputStream.write(buff, 0, len);
                }

            } else {
                return "下载的文件资源不存在";
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
                if (outputStream != null) {
                    outputStream.flush();
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "success";
    }

Testergebnisse:

Erster Besuch:

Zweiter Besuch:

Wenn der download_key abläuft, können Sie mit dem Download fortfahren!

Guess you like

Origin blog.csdn.net/weixin_47382783/article/details/135438469