springboot下一些小工具记录

本文介绍了如何使用Spring AOP和ExpiringMap实现接口的访问次数限制,以及如何提供JSON和图片资源的网页显示。同时,展示了如何设置文件下载,并修改图片的hash值进行随机命名。内容涵盖了限流策略、文件服务和图片处理方法。
摘要由CSDN通过智能技术生成

访问接口–指定时间限制次数

1.maven引入2个依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>

        <dependency>
            <groupId>net.jodah</groupId>
            <artifactId>expiringmap</artifactId>
            <version>0.5.9</version>
        </dependency>

2.创建一个注解

import java.lang.annotation.*;

@Documented
@Target(ElementType.METHOD) // 说明该注解只能放在方法上面
@Retention(RetentionPolicy.RUNTIME)
public @interface LimitRequest {
    long time() default 6000; // 限制时间 单位:毫秒
    int count() default 1; // 允许请求的次数
}

3.创建一个切面

import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class LimitRequestAspect {

    private static ConcurrentHashMap<String, ExpiringMap<String, Integer>> book = new ConcurrentHashMap<>();

    // 定义切点
    // 让所有有@LimitRequest注解的方法都执行切面方法
    @Pointcut("@annotation(limitRequest)")
    public void excudeService(LimitRequest limitRequest) {
    }

    @Around("excudeService(limitRequest)")
    public Object doAround(ProceedingJoinPoint pjp, LimitRequest limitRequest) throws Throwable {

        // 获得request对象
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        // 获取Map对象, 如果没有则返回默认值
        // 第一个参数是key, 第二个参数是默认值

        ExpiringMap<String, Integer> uc = book.getOrDefault(request.getRequestURI(), ExpiringMap.builder().variableExpiration().build());
        Integer uCount = uc.getOrDefault(request.getRemoteAddr(), 0);

        String requestURI = request.getRequestURI();
        String remoteAddr = request.getRemoteAddr();


        if (uCount >= limitRequest.count()) { // 超过次数,不执行目标方法
            return "接口请求超过次数";
        } else if (uCount == 0) { // 第一次请求时,设置有效时间
            /** Expires entries based on when they were last accessed */
//            ACCESSED,
            /** Expires entries based on when they were created */
//            CREATED;
            uc.put(request.getRemoteAddr(), uCount + 1, ExpirationPolicy.CREATED, limitRequest.time(), TimeUnit.MILLISECONDS);
        } else { // 未超过次数, 记录加一
            uc.put(request.getRemoteAddr(), uCount + 1);
        }
        book.put(request.getRequestURI(), uc);

        // result的值就是被拦截方法本身的返回值
        Object result = pjp.proceed();

        return result;
    }

}

4.放在任意一个方法上就行,可以自定义时间次数,这个是以请求方ip作为标志

    @RequestMapping("/test")
    @LimitRequest(time = 2000,count = 2)
    public String testController() {
        return "hello";
    }

网页显示资源–图片或json文件

json
    @GetMapping("/json/{path}")
    public ResponseEntity<FileSystemResource> json(@PathVariable String path) {
        ResponseEntity<FileSystemResource> body = ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(new FileSystemResource("C:\\Users\\Administrator\\Desktop\\" + path));
        return body;
    }
图片
    @GetMapping("/pic/{path}")
    public ResponseEntity<FileSystemResource> pic(@PathVariable String path) {
        ResponseEntity<FileSystemResource> body = ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(new FileSystemResource("C:\\Users\\Administrator\\Desktop\\" + path));
        return body;
    }

这样就只需要修改:C:\Users\Administrator\Desktop\

如果显示txt文件,可能出现中文乱码,在yml里设置

#设置网页编码为UTF-8
server:
  servlet:
    encoding:
      charset: UTF-8
      force: true
      enabled: true

提供文件下载

比如一个docx文件——文档.docx

    @GetMapping("/doc/{path}")
    public ResponseEntity<FileSystemResource> download(@PathVariable String path) throws UnsupportedEncodingException {
        String contentDisposition = ContentDisposition
                .builder("attachment")  //表示提供下载
                .filename(path)              //文件下载后显示的名字
                .build().toString();
        String encode = URLEncoder.encode(contentDisposition, StandardCharsets.UTF_8.toString());       //转换成URL编码,以免filename无法显示中文
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, encode)
                .contentType(MediaType.TEXT_PLAIN)
                .body(new FileSystemResource("C:\\Users\\Administrator\\Desktop\\" + path));
    }

下载后标题、正文编码正常


修改图片hash,并随机命名(支持单张复制为多张,或者多张批量修改)

public class ChangeHash {

    /**
     * 同一图片改变hash,并随机命名
     * 依赖hutool
     * 
     * @param count    需要复制多少张,单次不要超过9999张
     * @param filePath 原始照片地址
     * @param outDir   新照片输出文件夹
     * @param length   随机生成的文件名长度
     */
    public static void changeHashForSinglePic(int count, String filePath, String outDir, int length) {
        //确保为标准的文件格式
        outDir += FileUtil.FILE_SEPARATOR;

        for (int i = 1; i <= count; i++) {
            //轻微调整压缩比小数点后2位开始的值,
            double a = 0.9 + i * 0.00001;
            Img.from(FileUtil.file(filePath))
                    .setQuality(a)//压缩比率,改变hash值,同时随机生成指定位数文件名(数字、字符)
                    .write(FileUtil.file(outDir + RandomUtil.randomString(length) + ".jpg"));
        }
    }

    /**
     * 批量改变多张照片的hash值,可以重命名,也可以不用
     * 依赖hutool
     * 
     * @param fileDir  原始照片的文件夹
     * @param outDir   输出照片的文件夹
     * @param rate     压缩比率,建议0.9
     * @param isRename 是否随机生成字符串用于重命名,如果填false。length可以填0
     * @param length   如果重命名,随机字符串长度
     */
    public static void changeHashForMultiPic(String fileDir, String outDir, double rate, boolean isRename, int length) {
        //确保为标准的文件格式
        fileDir += FileUtil.FILE_SEPARATOR;
        outDir += FileUtil.FILE_SEPARATOR;

        //获取所有原始照片的名字
        List<String> fileNames = FileUtil.listFileNames(fileDir);

        for (String fileName : fileNames) {
            //重命名
            if (isRename) {
                FileUtil.mkdir(outDir);
                Img.from(FileUtil.file(fileDir + fileName))
                        .setQuality(rate)//压缩比率,改变hash值,同时随机生成指定位数文件名(数字、字符)
                        .write(FileUtil.file(outDir + RandomUtil.randomString(length) + ".jpg"));
            } else {
                FileUtil.mkdir(outDir);
                Img.from(FileUtil.file(fileDir + fileName))
                        .setQuality(rate)//压缩比率,改变hash值,按原文件名命名
                        .write(FileUtil.file(outDir + fileName));
            }
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值