score:28
use an interceptor:
- extend
handlerinterceptoradapter
and overrideprehandle
- define it with
<mvc:interceptors>
indispatcher-servlet.xml
it will run for every request.
score:1
as any tech answer ... it depends .. on the tech stack you are using and what your requirements are.
for example the more generic you want to make your logging, the further upfront you would want to do it. in your case, you are logging only requests which are logging enabled and being handled in the spring context. so you could be "missing" other requests.
i would look at the container or the web server you are using to run your app. that will remove this dependency on spring. plus containers provide you the flexibility of plugging in a logging provider and then configuring the format of the log outside code. for example, if you are using apache web server, use apache web server logging to log all http requests in the access logging layer. but be careful, some of the logging options have performance penalties. log only what you seriously need for an access pattern monitoring perspective.
if you are using tomcat, then tomcat also will allow you to log stuff. search for access valve in the tomcat documentation for the tomcat you are using. that will open up a world of possibilities.
more extensive logging should be the domain of the exception strategy ie the kind of detail you want to see when a problem occurs in the system.
score:2
adding to what @b.ali has answered. if you are using this in a spring asynchronous request (serlvet 3.0 or greater) handling scenario, then the following code is what worked for me.
public class onceperrequestloggingfilter extends onceperrequestfilter {
@override
protected void dofilterinternal(httpservletrequest request, httpservletresponse response, filterchain filterchain) throws servletexception, ioexception {
boolean isfirstrequest = !isasyncdispatch(request);
httpservletrequest requesttouse = request;
httpservletresponse responsetouse = response;
// the below check is critical and if not there, then the request/response gets corrupted.
// probably because in async case the filter is invoked multiple times.
if (isfirstrequest && !(request instanceof contentcachingrequestwrapper)) {
requesttouse = new contentcachingrequestwrapper(request);
}
if (isfirstrequest && !(response instanceof contentcachingresponsewrapper)) {
responsetouse = new contentcachingresponsewrapper(response);
}
filterchain.dofilter(requesttouse, responsetouse);
if (!isasyncstarted(request)) {
contentcachingresponsewrapper responsewrapper =
webutils.getnativeresponse(response, contentcachingresponsewrapper.class);
responsewrapper.copybodytoresponse(); // important to copy it back to response
}
}
@override
protected boolean shouldnotfilterasyncdispatch() {
return false; // important this is true by default and wont work in async scenario.
}
}
score:6
here's a small library i wrote you can use: spring-mvc-logger
i made it available via maven central:
<dependency>
<groupid>com.github.isrsal</groupid>
<artifactid>spring-mvc-logger</artifactid>
<version>0.2</version>
</dependency>
score:8
the main issue with reading request is that as soon as the input stream is consumed its gone whoof... and cannot be read again. so the input stream has to be cached. instead of writing your own classes for caching (which can be found at several places on web), spring provides a couple of useful classes i.e. contentcachingrequestwrapper and contentcachingresponsewrapper. these classes can be utilized very effectively, for example, in filters for logging purposes.
define a filter in web.xml:
<filter>
<filter-name>loggingfilter</filter-name>
<filter-class>org.springframework.web.filter.delegatingfilterproxy</filter-class>
</filter>
<filter-mapping>
<filter-name>loggingfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
since the filter is declared as delegatingfilterproxy, it can be declared as a bean using @component or @bean annotations. in the loggingfilter's dofilter method, wrap the request and response with spring provided classes before passing it to the filter chain:
httpservletrequest requesttocache = new contentcachingrequestwrapper(request);
httpservletresponse responsetocache = new contentcachingresponsewrapper(response);
chain.dofilter(requesttocache, responsetocache);
string requestdata = getrequestdata(requesttocache);
string responsedata = getresponsedata(responsetocache);
the input stream will be cached in the wrapped request as soon as the input stream is consumed after chain.dofilter(). then it can be accessed as below:
public static string getrequestdata(final httpservletrequest request) throws unsupportedencodingexception {
string payload = null;
contentcachingrequestwrapper wrapper = webutils.getnativerequest(request, contentcachingrequestwrapper.class);
if (wrapper != null) {
byte[] buf = wrapper.getcontentasbytearray();
if (buf.length > 0) {
payload = new string(buf, 0, buf.length, wrapper.getcharacterencoding());
}
}
return payload;
}
however, things are a bit different for response. since the response was also wrapped before passing it to the filter chain, it will also be cached to the output stream as soon as it is written on its way back. but since the output stream will also be consumed so you have to copy the response back to the output stream using wrapper.copybodytoresponse(). see below:
public static string getresponsedata(final httpservletresponse response) throws ioexception {
string payload = null;
contentcachingresponsewrapper wrapper =
webutils.getnativeresponse(response, contentcachingresponsewrapper.class);
if (wrapper != null) {
byte[] buf = wrapper.getcontentasbytearray();
if (buf.length > 0) {
payload = new string(buf, 0, buf.length, wrapper.getcharacterencoding());
wrapper.copybodytoresponse();
}
}
return payload;
}
hope it helps!
score:46
edit: also, see @membersound's comment on this answer, which improves this answer.
spring supports this. see commonsrequestloggingfilter. if using spring boot, just register a bean of that type and boot will apply it to the filter chain. like:
@bean
public filter logfilter() {
commonsrequestloggingfilter filter = new commonsrequestloggingfilter();
filter.setincludequerystring(true);
filter.setincludepayload(true);
filter.setmaxpayloadlength(5120);
return filter;
}
also, this logging filter requires the log level be set to debug. e.g. do this in a logback.xml with:
<logger name="org.springframework.web.filter.commonsrequestloggingfilter" level="debug"/>
Source: stackoverflow.com
Related Query
- How to log properly http requests with Spring MVC
- How to respond with HTTP 400 error in a Spring MVC @ResponseBody method returning String?
- How to Implement HTTP byte-range requests in Spring MVC
- How to respond with HTTP status code in a Spring MVC @RestController @ResponseBody class returning an object?
- How to enable HTTP caching for the resource handler with Spring MVC and Spring Security
- Custom Spring MVC HTTP Patch requests with Spring Data Rest functionality
- How to get the basic HTTP authentication data with Spring MVC and Java
- how to handle both XmlHttpRequest(AJAX) and regular http requests in one spring mvc method?
- How can I properly validate checkboxes with Spring MVC and ThymeLeaf?
- how to configure the http head in jQuery post function with spring mvc
- Spring MVC - log every incoming http request call with payload into database
- How to get access to HTTP header information in Spring MVC REST controller?
- How to avoid the "Circular view path" exception with Spring MVC test
- Why does Spring MVC respond with a 404 and report "No mapping found for HTTP request with URI [...] in DispatcherServlet"?
- How to configure embedded Tomcat integrated with Spring to listen requests to IP address, besides localhost?
- Spring MVC "redirect:" prefix always redirects to http -- how do I make it stay on https?
- How to write a proper global error handler with Spring MVC / Spring Boot
- How can I have case insensitive URLS in Spring MVC with annotated mappings
- How to configure Spring MVC with pure Java-based configuration?
- Http Post with request content type form not working in Spring MVC 3
- How to handle HTTP OPTIONS requests in Spring Boot?
- How to handle exceptions in Spring MVC differently for HTML and JSON requests
- How to handle HTTP OPTIONS with Spring MVC?
- How to create Spring MVC application with Maven structure in Intellij IDEA 13.1?
- How to include js and CSS in JSP with spring MVC
- How to cope with x-forwarded-headers in Spring Boot 2.2.0? (Spring Web MVC behind reverse proxy)
- How do I map Spring MVC controller to a uri with and without trailing slash?
- How to login a user with spring 3.2 new mvc testing
- How to register handler interceptors with spring mvc 3.0?
- How to pass a session attribute as method argument (parameter) with Spring MVC
More Query from same tag
- Spring And EventSource
- How to keep request parameters after redirect?
- Spring MVC @RequestParam values not being extracted from URI as expected
- Restricting continous character occurence
- Java build path error- spring framework
- org.springframework.web.servlet.DispatcherServlet noHandlerFound (No mapping found)
- How to access a scope variable in inline javascript inside a html page in thymeleaf and use it to change a css attribute
- Requiring password even when logged in for certain resources in Spring Boot webapp
- How to hold filter parameters. Pagination
- springmvc using json response
- Parsley not using custom error container for radio button group
- Separate Spring context for DelegatingFilterProxy
- FileNotFoundException with properties file
- EmbeddedServletContainerAutoConfiguration and ServerPropertiesAutoConfiguration in Spring Boot 2.0
- Why we need to use annotations in Spring?
- Spring validate related request parameters
- Using Spring with App Engine
- Custom deserializer for requests with content-type application/x-www-form-urlencoded in Spring Boot
- Spring dojo request issue
- Thymeleaf page layout header properties overriden
- Pass parameter to Spring controller using @PathVariable
- Spring 3 - In CustomUserDetailsService class, i am getting resource null
- Spring DispatcherServlet: No mapping found for HTTP request
- How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration?
- How Spring MVC works with mybatis?
- how to move config xml files from WEB-INF to resources in java spring?
- Spring Web application displaying HTTP Status 404 -
- Spring Rest Template Http client error exception
- Spring 3.1.2 MVC @ExceptionHandler with @ResponseBody
- After logout back button should always direct to login page