'Get Request/Response Body&Header in Spring AOP

I want to get request/response body and header within my aspect before and after if it's available or how to get those .

I mean i think with before annotation should be work for request,

with after annotation should be work for response. Can be ?

What I've tried so far :

I tried logbook library it's very complicated for me i could'nt figured it out how to work with that.So i gave up.

The actuator can do trick but I am doing extra work like how many times the endpoints called etc.So therefore i can't use actuator.

Also i tried to get request headers like below at least but i think this headers coming same all the time.I couldn't get httpservletresponse like how httpservetrequest does.

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

then request.getHeader("date") but what about requestbody ?

how to get requestbody ? responsebody ? repsonseheader ?

My aspect file :

@Aspect
@Component
public class AppAspect implements ResponseInfo{

    @Before("execution(@(@org.springframework.web.bind.annotation.RequestMapping *) * *(..))")
    public void loggingStartPointRequests(JoinPoint joinPoint) {

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

}

@After("execution(@(@org.springframework.web.bind.annotation.RequestMapping *) * *(..))")
    public void loggingEndPointRequests(JoinPoint joinPoint) throws IOException {

    }

}

My Controller Class:

@RestController
public class MainController {

    @GetMapping("/people") // 
    public ResponseEntity<Poeple> getAllPeople(@RequestParam(name = "page", required = false) Integer page,
            @RequestParam(name = "size", required = false) Integer size,
            @RequestParam(name = "sortBy", required = false) Boolean sortByNameOrEpCount) {
doSomething();
}

}


Solution 1:[1]

I think what you need is to implement the interface HandlerInterceptor, it would help you being able to inspect the request and the response. For example:

public class ApiMonitor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    // when the client access to your endpoint
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    // when you finished your process 
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    // after you already returned an answer to the client
}
}

If you want to operate with the object that you're returning just before you send it to the client, then you need AOP, yes. That's an example of how I do it to modify an object on certain endpoints just before it's parsed to json.

@Component
@Aspect
public class MyCustomAOPInterceptor {

/**
* These poincuts check the execution of a method in any (*) 
* class of my.package.controller and that start with
* get/list/find plus any other word (*) . For example
* my.package.controller.UserController.getUserById()
*/
@Pointcut("execution(* my.package.controller.*.get*(..))")
public void petitionsStartWithGet() { }

@Pointcut("execution(* my.package.controller.*.list*(..))")
public void petitionsStartWithList() { }

@Pointcut("execution(* my.package.controller.*.find*(..))")
public void petitionsStartWithFind() { }

@AfterReturning(pointcut = "petitionsStartWithGet() || petitionsStartWithList() || petitionsStartWithFind()", returning = "result")
public void translateEntities(JoinPoint joinPoint, Object result) {
    // do your stuff; result is the object that you need
}

}

Solution 2:[2]

I had the same problem and if you have your @Aspect annotated with @Component (or any @Autowired candidate) you can simply get the HttpServletRequest like this:

@Aspect
@Component
public class SomeAspect {
    
   @Autowired
   HttpServletRequest request;

   @Before("...")
   public void beforeAdvice(JoinPoint jp){
       /* You will have the current request on the request property */
      System.out.println(request.getRequestURL());
   }  
}

I know this is an old question but I hope it'll be helpful.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dgarceran
Solution 2 853174