Spring boot 2.1 自定义注解拦截器

  • 需求

系统有很多需要上传文件的接口,这些接口需要的文件格式都是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 实现等的理解

你可能感兴趣的:(spring-boot)