How do I minify dynamic HTML responses in Spring?

JackMahoney :

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);
    }
}
buræquete :

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>

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=429352&siteId=1