How to get custom annotations within spring-boot filter

2.1k Views Asked by At

I have a spring boot application with a custom filter:

import javax.servlet.Filter

public class MyFilter implements Filter{

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        System.out.println("MyFilter");
    }
}

Some controllers in the application have custom annotations over their methods. All custom annotations implement the myAnnotation interface.

    @GetMapping("/")
    @MyCustomAnnotation
    @AnotherCustomAnnotation
    public ResponseEntity<String> get(){
        addSomeMetric();
        return new ResponseEntity<>("Hello world", HttpStatus.OK);
    }

How can get i get a list of all annotations defined on the URI endpoint from within the doFilter code?

2

There are 2 best solutions below

0
R.G On

Spring AOP can be used to decide if a controller method need to be executed based on request/user.

Following code is one way of implementing the same.

@Aspect
@Component
public class AnnotationFilterAspect {
    
    @Pointcut("execution(public * package.controller..*(..))")
    public void allControllerMethods() {
        
    }
    
    @Around("allControllerMethods()")
    public Object checkAccess(ProceedingJoinPoint pjp) {
        Object retObject = null;
        Method method = getMethod(pjp);
        for(Annotation anno : method.getAnnotations()){
            System.out.println(anno.annotationType());
            // Annotation details
        }
        
        // Logged in user details
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String currentUserName = authentication.getName();
        //or
        //Get the HttpServletRequest currently bound to the thread.
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        
        // Logic to proceed to the controller method based on the logged in user or request can be done here. 
        
        try {
            retObject = pjp.proceed();
        } catch (Throwable e) {
            // Handle the exception
        }
        
        return retObject;
    }
    
    //Refer : https://stackoverflow.com/q/5714411/4214241
    private Method getMethod(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        if (method.getDeclaringClass().isInterface()) {
            try {
                method= pjp.getTarget().getClass().getDeclaredMethod(pjp.getSignature().getName(),
                        method.getParameterTypes());
            } catch (final SecurityException exception) {
                //...
            } catch (final NoSuchMethodException exception) {
                //...                
            }
        }   
        return method;
    }

}

Also note that the annotation RetentionPolicy must be RUNTIME , for this code to work.

0
user12396421 On

I eventually used a HandlerInterceptor and not a filter.

Since I am only aiming for web requests, it seems a better and easier solution than AOP.

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) {
       MyAnnotation myAnnotation = getMyAnnotation(handler);

    }

    private MyAnnotation getMyAnnotation(Object handler) {
       HandlerMethod handlerMethod = (HandlerMethod) handler;
       Method method = handlerMethod.getMethod();
       return method.getAnnotation(MyAnnotation.class);
}