欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring boot 2.1 自定义注解拦截器

程序员文章站 2022-04-30 16:35:29
...
  • 需求

系统有很多需要上传文件的接口,这些接口需要的文件格式都是jpg格式的,所以想把这一部分提出来,可以用拦截器的方式,但是我想要的是在Controller中的某个方法上加个注解就能有这样的功能,而不是去配置拦截器URL之类的

  • 实现

显然需要用到 AOP

  • 代码

自定义注解

import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ImageNeed {

}

配置切面

import com.truthso.dto.Result;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.util.Locale;

@Aspect
@Configuration
public class FileAspect {

    private static final Logger logger = LoggerFactory.getLogger(FileAspect.class);

    @Pointcut("execution(* com.truthso.monitor.consumer.controller.*(..))")
    public void executeService() {
    }

    @Around("@annotation(com.truthso.monitor.consumer.annotation.ImageNeed)")
    public Object before(ProceedingJoinPoint joinPoint) throws Throwable {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        logger.info("------------------------------------------------------");
        logger.info("request  from   :{} ", request.getRemoteAddr());
        logger.info("request  url    :{} ", request.getRequestURL().toString());
        logger.info("request  method :{} ", request.getMethod());
        logger.info("response method :{} ", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("request  params :{} ", Arrays.toString(joinPoint.getArgs()));
        logger.info("------------------------------------------------------");

        String contentType = request.getContentType();

        if (null == contentType || !contentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/")) {
            return new Result(201, "please upload file");
        }

        MultipartResolver resolver = new StandardServletMultipartResolver();
        MultipartHttpServletRequest fileRequest = resolver.resolveMultipart(request);

        MultipartFile file = fileRequest.getFile("file");

        if (file == null) {
            return new Result(202, "please upload file");
        }

        if (file.getSize() == 0) {
            return new Result(203, "file size is 0");
        }

        return joinPoint.proceed();
    }

}
  • 使用方法
@RestController
@RequestMapping("old")
public class OldController {

    private static final Logger logger = LoggerFactory.getLogger(OldController.class);

    @ImageNeed
    @RequestMapping("compare")
    public Result compare(MultipartFile file, HttpServletRequest req) throws Exception {

        String format = sdf.format(new Date());

        String realPath = req.getServletContext().getRealPath("/upload") + format;

        File folder = new File(realPath);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        String oldName = file.getOriginalFilename();
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));

        File image = new File(folder, newName);

        file.transferTo(image);

        // do something

        image.delete();

        return Result.successResult();
    }
  • 注意的问题
  1. FileAspect 类需要用 @Configuration 注解让 Spring boot 能扫描到
  2. 定义切点 @Pointcut 具体格式可以百度
  3. 只有 @Around 才有 ProceedingJoinPoint ,才有 joinPoint.proceed() 方法,Befor 和 After 都没有
  4. 在 方法里面将 HttpServletRequest 转换成  MultipartHttpServletRequest 的方式
  5. 后续需要加深对 AOP 实现等的理解