Issue
I wrote the following sample code to check logs. This code works. I'm using Spring Boot 2.7.1.
All controllers have this line of code: log.debug("IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
Since throughout the code for this project I would like all controllers to have this line of code, I am wondering if there is a way to achieve the same result in a more compact way. In other words, I would not want to repeat this line of code every time. I would prefer the log.debug
with IP and URL to happen automatically for each controller. Is this possible?
package ...;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestMe {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@GetMapping("/testme")
@ResponseBody
public String testme(HttpServletRequest request) {
log.debug("IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
return "I'm working! :-)";
}
@GetMapping("/testerror")
@ResponseBody
public int testerror(HttpServletRequest request) {
log.debug("IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
return 1 / 0;
}
@GetMapping("/testexception")
@ResponseBody
public int testexception(HttpServletRequest request) {
log.debug("IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
throw new IllegalStateException("Test Exception");
}
@GetMapping("/testlogs")
@ResponseBody
public String testlogs(HttpServletRequest request) {
log.debug("IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
log.trace("test log TRACE level");
log.debug("test log DEBUG level");
log.info("test log INFO level");
log.warn("test log WARN level");
log.error("test log ERROR level");
return "Please check the logs";
}
/**
* Spring Controller to handle all requests not matched by the previous Controllers,
* @return
*/
@RequestMapping (value = "/**", method = {RequestMethod.GET, RequestMethod.POST})
public String greetings(HttpServletRequest request) {
log.debug("IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
log.warn("Unmapped request handling from IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
return "Greetings! Please check the logs";
}
}
Solution
Assuming that all my Controllers are in the xxx.layer1controllers
package, the following class is a possible solution:
package ...;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
// info: https://www.baeldung.com/spring-aop-pointcut-tutorial & https://stackoverflow.com/a/39508845/1277576
@Before("within(xxx.layer1controllers..*))")
public void logController(JoinPoint joinPoint) throws Exception {
if (joinPoint.getArgs().length > 0 && joinPoint.getArgs()[0] instanceof HttpServletRequest) {
HttpServletRequest request = (HttpServletRequest) joinPoint.getArgs()[0];
log.debug("IP " + request.getRemoteAddr() + " -> " + request.getRequestURI());
} else {
log.warn("Let's remember to add a HttpServletRequest parameter to " + joinPoint.getSignature().toShortString());
}
}
}
Answered By - Francesco Galgani
Answer Checked By - Candace Johnson (JavaFixing Volunteer)