2

I'm creating a simple SpringMVC project,and want to logging all incoming requests, include uri/query/payload/clientIp... , all info.

All resources I can find are about Spring Bootfor example: https://www.javadevjournal.com/spring/log-incoming-requests-spring/

I also read the official docs and found enableLoggingRequestDetails option, but there's no detail about it, I tried and not working. https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-logging

So, how to implement this in pure SpringMVC framework (without Spring Boot)?

Is there a SpringMVC built-in approach to do it?

3 Answers 3

2

1. You can implement a Filter class extending from OncePerRequestFilter and then every request will go through you filter. Then you can log what you want inside this class.

    @Slf4j
    @Component
    public class RequestLoggingFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            log.debug(
                    String.format("FILTERED URL: %s", request.getRequestURI())
            );

            //continue filtering
            filterChain.doFilter(request, response);
        }
    }

2. Another way is to implement an Interceptor class extending from HandlerInterceptorAdapter.

    @Slf4j
    @Component
    public class RequestLoggingHandler extends HandlerInterceptorAdapter {

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.debug(
                    String.format("HANDLER(pre) URL: %s", request.getRequestURI())
            );

            return super.preHandle(request, response, handler);
        }

        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.debug(
                    String.format("HANDLER(post) URL: %s", request.getRequestURI())
            );

            super.postHandle(request, response, handler, modelAndView);
        }
    }

But you have to enable this interceptor by adding it via configuration explicitly.

    @Configuration
    public class WebApplicationConfiguration implements WebMvcConfigurer {

        @Setter(onMethod_ = @Autowired)
        private RequestLoggingHandler requestLogger;

        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(requestLogger);
        }
    }

3. One more way is to use standard CommonsRequestLoggingFilter.

This way you should configure it with configuration like:

@Configuration
public class RequestLoggingFilterConfig {

    @Bean
    public CommonsRequestLoggingFilter logFilter() {
        CommonsRequestLoggingFilter filter
          = new CommonsRequestLoggingFilter();
        filter.setIncludeQueryString(true);
        filter.setIncludePayload(true);
        filter.setMaxPayloadLength(10000);
        filter.setIncludeHeaders(false);
        filter.setAfterMessagePrefix("REQUEST DATA : ");
        return filter;
    }
}

And then enable it into logback.xml:

<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter">
    <level value="DEBUG" />
</logger>
Sign up to request clarification or add additional context in comments.

6 Comments

Sorry, I am new to Java, can u explain what a 'logback.xml' is? I don't have this file in may project.
@guojiubo logback-spring.xml - is the settings file for logger used by SpringBoot. You may check out an example in official Spring docs docs.spring.io/spring-boot/docs/current/reference/html/…
@guojiubo check out my post, i have updated it with examples.
Thank u, but i'm not using SpringBoot right now, currently i'm trying to use SpringMVC only, some day i will try it.
@guojiubo you can use it all in spring without any changes if you enable annotation processing in application-context.xml. Or you may instantiate these beans right into application-context.xml.
|
0

Well in order to enable logging in Spring Application all you need is

Log library and its property file

To make Log4j work with the default JCL dependency (commons-logging) all you need to do is put Log4j on the classpath, and provide it with a configuration file (log4j.properties or log4j.xml in the root of the classpath).

<dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
      <scope>runtime</scope>
   </dependency>

log4j.properties

log4j.rootCategory=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n

log4j.category.org.springframework.beans.factory=DEBUG

Refer Spring doc and sample project

1 Comment

Very helpful, I followed your instruction and see a log now: "17:37:50,264 DEBUG http-nio-8080-exec-4 support.DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'homeController'". But how can i logging incoming requests's info, like URI, query...etc.?
0

Using Interceptor you can achieve this one.Check below links,you will get an idea

enter link description here

spring-mvc-handlerinterceptor

spring-mvc-4-how-to-intercept-request-with-a-handlerinterceptor

Edit:

Using CommonsRequestLoggingFilter

Spring MVC provides CommonsRequestLoggingFilter which can log request URL, body and other related information.

CommonsRequestLoggingFilter

LoggingConfig.java


import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource("classpath:logging.properties")
public class LoggingConfig {

    @Autowired
    private Environment env;

    public CommonsRequestLoggingFilter requestLoggingFilter() {
        CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter();
        loggingFilter.setIncludeClientInfo(env.getProperty("logging.client"));
        loggingFilter.setIncludeQueryString(env.getProperty("logging.query"));
        loggingFilter.setIncludePayload(env.getProperty("logging.payload"));
        loggingFilter.setIncludeHeaders(env.getProperty("logging.headers"));
        return loggingFilter;
    }

    @Bean
    public CommonsRequestLoggingFilter springLogging() {
        Logger logger = (Logger) LoggerFactory.getLogger(CommonsRequestLoggingFilter.class);
                logger.setLevel(Level.DEBUG);
        return requestLoggingFilter();
    }
}

logging.properties

logging.client = true
logging.query = true
logging.payload = true
logging.headers = true

1 Comment

Thanks, i believe Interceptor can achieve the goal, but i'm looking for a SpringMVC built-in approach to do it, can u help me?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.