Filters

Filters are another good technology of Java EE. It is an implementation of the Chain of Responsibility design pattern. It is useful when you want to perform filtering tasks to HTTP requests before they reach servlets.

Let's create an AuditingFilter to audit requests. For demonstration purposes, we will simply write the request information to log for now.

To create a filter, we need to implement the javax.servlet.Filter interface. Or, we can extend Spring's org.springframework.web.filter.GenericFilterBeanwhich provides a number of handy features. Let's go with GenericFilterBean.

Here is how AuditingFilter appears:

package app.messages;
...
public class AuditingFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
long start = new Date().getTime();
chain.doFilter(req, res);
long elapsed = new Date().getTime() - start;
HttpServletRequest request = (HttpServletRequest) req;
logger.debug("Request[uri=" + request.getRequestURI() + ", method="
+
request.getMethod() + "] completed in " + elapsed + " ms");
}
}

As you can see, we extend GenericFilterBean and overwrite the doFilter() method, which is the place that we perform the filtering tasks. At the beginning of this method, we mark the time before we invoke chain.doFilter()which allows the chain to invoke further filters behind it if there are any. If you forgot to call chain.doFilter(), no response will be sent back to the client. And you can still perform some tasks after invoking the chain.doFilter() method. In our filter, we calculate the elapsed time and log it as debug information.

By now, we have created AuditingFilter. However, if you restarted the application and refreshed the page, nothing would be showing up in the output. This is because we haven't registered it yet.

There are two ways to register a filter in a Spring Boot application. You can register it by adding <filter> and <filter-mapping> to the web.xml file, or you can create FilterRegistrationBean to register it in the configuration class, AppConfig. The use of web.xml is for web applications as a .war file that is deployed to an application server. Since we are running Tomcat in embedded mode, and there is no web.xml, we will use FilterRegistrationBean.

Here is what the updated AppConfig.java looks like:

..
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
...
public class AppConfig {
@Bean
public FilterRegistrationBean<AuditingFilter>
auditingFilterRegistrationBean()
{
FilterRegistrationBean<AuditingFilter> registration = new
FilterRegistrationBean<>();
AuditingFilter filter = new AuditingFilter();
registration.setFilter(filter);
registration.setOrder(Integer.MAX_VALUE);
registration.setUrlPatterns(Arrays.asList("/messages/*"));
return registration;
}
}

We apply the @Bean annotation to the auditingFilterRegistrationBean() method to generate FilterRegistrationBean for AuditingFilter. As you can see from this method, to register Filter, we need to create a Filter instance and use the setFilter() method to set Filter. And we use the setOrder() method to position this Filter in the chain. The one with the smaller order value will be put to the front. In our case, AuditingFilter will be put at the end of the chain. The setUrlPatterns() method is for specifying the path that Filter will be registered against. In our case, AuditingFilter will only process requests whose paths begin with /messages/.

And in order to show the debug log in the output, we need to turn on the debug level log for AuditingFilter. To do that, let's create the .properties file, application.properties, under the /src/main/resources/ directory. In this file, we will overwrite the default logging level of AuditingFilter. By now, we only have one custom property.

Here is what application.properties look like:

logging.level.app.messages.AuditingFilter=DEBUG

logging.level. is the property's prefix. And app.messages.AuditingFilter is the path of the class where we want to enable the debug level logging. You can use the path of a package that will enable the debug level logging for all of the classes inside that package.

Now, if you restart the application and refresh the page, you will see debug information similar to the following in the log:

Request[uri=/messages/welcome,method=GET] completed in 337 ms
Don't worry about the elapsed time showing in the preceding log. It took 337 ms  because it is the first request after the server has started and Spring needs to initialize DispatcherServlet. If you refresh the page again, you will see a much shorter duration. This is sometimes called Server Warming Up.

Spring Framework 5 introduces a new web stack, Spring WebFlux. It is a non-blocking web framework built to handle massive numbers of concurrent connections. In this book, we are going to use the traditional Spring MVC.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.208.97