Following Google's pagespeed advice I would like the minify the HTML responses of my Spring application. I don't mean GZip, I mean removing comments and whitespace from HTML before it is sent down the wire.
I would like to do this dynamically and not in my templates. My templates contain many comments that are useful but should not be part of the response.
Following is my controller;
@Controller
public class IndexController {
@GetMapping("/")
public ModelAndView index() {
Data data = ....
return new ModelAndView("index", data);
}
}
Spring Boot is a backend framework that has become a major player in the enterprise Java ecosystem. It lets Java developers start building web applications quickly, without fuss. Today we are spoilt for choice, with several different frontend frameworks out there that go well with a Java Spring Boot backend.
This article explores the different options that Spring Boot developers have for using Javascript and CSS on the client (browser) side of their application. Part of the plan is to explore some Javascript libraries that play well in the traditional server-side-rendered world of Spring web applications.
I managed to do this by adding a javax.servlet.Filter
component that is using com.googlecode.htmlcompressor
into Spring
First the Filter
;
@Component public class HtmlFilter implements Filter { protected FilterConfig config; public void init(FilterConfig config) throws ServletException { this.config = config; } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { ServletResponse newResponse = response; if (request instanceof HttpServletRequest) { newResponse = new CharResponseWrapper((HttpServletResponse) response); } chain.doFilter(request, newResponse); if (newResponse instanceof CharResponseWrapper) { String text = newResponse.toString(); if (text != null) { HtmlCompressor htmlCompressor = new HtmlCompressor(); response.getWriter().write(htmlCompressor.compress(text)); } } } }
and relevant CharResponseWrapper
;
class CharResponseWrapper extends HttpServletResponseWrapper { protected CharArrayWriter charWriter; protected PrintWriter writer; protected boolean getOutputStreamCalled; protected boolean getWriterCalled; public CharResponseWrapper(HttpServletResponse response) { super(response); charWriter = new CharArrayWriter(); } public ServletOutputStream getOutputStream() throws IOException { if (getWriterCalled) { throw new IllegalStateException("getWriter already called"); } getOutputStreamCalled = true; return super.getOutputStream(); } public PrintWriter getWriter() throws IOException { if (writer != null) { return writer; } if (getOutputStreamCalled) { throw new IllegalStateException("getOutputStream already called"); } getWriterCalled = true; writer = new PrintWriter(charWriter); return writer; } public String toString() { String s = null; if (writer != null) { s = charWriter.toString(); } return s; } }
Works fantastically. Converts an html this ugly;
<!DOCTYPE HTML> <html> <head> <title> A Simple <!-- Test--> HTML Document <!-- Test--> </title> </head> <body> <p>This is a very simple HTML document</p> <!-- Test--> <p>It only has two<!-- Test--> paragraphs</p> <!-- Test--> </body> </html>
into this;
<!DOCTYPE HTML> <html> <head> <title> A Simple HTML Document </title> </head> <body> <p>This is a very simple HTML document</p> <p>It only has two paragraphs</p> </body> </html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With