How do I create a hit counter servlet?

Here we have a simple example of creating a hit counter using servlet. The servlet updates the hits counter every time a page is visited and display the number of hits as an image. The image is generated at runtime using Java’s Graphic2D and ImageIO class.

To store the hits data create a table hits with a single field called counter and set the initial value of the counter to zero. Below is the HitCounterServlet servlet code.

package org.kodejava.example.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.*;

public class HitCounterServlet extends HttpServlet {
    public HitCounterServlet() {
        super();
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        updateHitCounter();
        getHitCounterImage(req, res);
    }

    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException {
        updateHitCounter();
        getHitCounterImage(request, response);
    }

    private void updateHitCounter() {
        Connection connection = getConnection();
        try {
            // Update the hits counter table by incrementing the
            // counter every time a user hits our page.
            String sql = "UPDATE hits SET counter = counter + 1";
            PreparedStatement stmt = connection.prepareStatement(sql);
            stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(connection);
        }
    }

    private void getHitCounterImage(HttpServletRequest req,
                                    HttpServletResponse res)
            throws IOException {
        Connection connection = getConnection();
        String hits = "";
        try {
            // Get the current hits counter from database.
            String sql = "SELECT counter FROM hits";
            PreparedStatement stmt = connection.prepareStatement(sql);
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                hits = rs.getString("counter");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(connection);
        }

        // Create an image of our counter to be sent to the browser.
        BufferedImage buffer = new BufferedImage(50, 20, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = buffer.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setFont(new Font("Monospaced", Font.PLAIN, 14));
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 50, 20);
        g.setColor(Color.BLACK);
        g.drawString(hits, 0, 20);

        res.setContentType("image/png");
        OutputStream os = res.getOutputStream();
        ImageIO.write(buffer, "png", os);
        os.close();
    }

    private Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost/kodejava", "kodejava", "kodejava123");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    private void closeConnection(Connection connection) {
        try {
            if (connection != null && !connection.isClosed()) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

To configure the servlet you’ll need to update the web.xml file as follow:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>kodejava-example</display-name>
    <servlet>
        <display-name>HitCounter</display-name>
        <servlet-name>HitCounter</servlet-name>
        <servlet-class>
            org.kodejava.example.servlet.HitCounterServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HitCounter</servlet-name>
        <url-pattern>/HitCounter</url-pattern>
    </servlet-mapping>
</web-app>

To display the hits counter image on the JSP page, create an image tag with the source point to our HitCoutnerServlet servlet.

Visited for: <img src="http://localhost:8080/app-name/HitCounter" alt="Hit Counter"/> times.

How do I count number of online users?

When you have a web application you might want to know how many users are currently online or connected to your website. If you have visited some of web online forums you can see; usually on the first page; the list of their online users or maybe just the number of currently online users.

How do we know / count how many sessions or users are currently connected to our website. Do you care to know? Let’s see what Java Servlet API offers us on this matter.

Servlet API has an interface javax.servlet.http.HttpSessionListener, an implementation of this interface will have the ability to be notified by the servlet engine at anytime when a new session was created or destroyed.

This interface has two methods to be implemented; these methods are sessionCreated(HttpSessionEvent se) and sessionDestroyed(HttpSessionEvent se). These method will be called as a notification that a new session was created and the session was about to be destroyed respectively.

Now let’s create our session listener. The code below is what our class is going to be implemented.

package org.kodejava.example.servlet;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.ArrayList;

public class SessionCounter implements HttpSessionListener {
    private List<String> sessions = new ArrayList<>();
    public static final String COUNTER = "session-counter";

    public void sessionCreated(HttpSessionEvent event) {
        System.out.println("SessionCounter.sessionCreated");
        HttpSession session = event.getSession();
        sessions.add(session.getId());
        session.setAttribute(SessionCounter.COUNTER, this);
    }

    public void sessionDestroyed(HttpSessionEvent event) {
        System.out.println("SessionCounter.sessionDestroyed");
        HttpSession session = event.getSession();
        sessions.remove(session.getId());
        session.setAttribute(SessionCounter.COUNTER, this);
    }

    public int getActiveSessionNumber() {
        return sessions.size();
    }
}

To display information of current online users we need to create a simple JSP page. This JSP file will get the number of online user from HttpSession attribute named counter that we set in our listener above.

<%@ page import="org.kodejava.example.servlet.SessionCounter" %>
<html>
<head>
    <title>Session Counter</title>
</head>
<body>
<% 
    SessionCounter counter = (SessionCounter) session.getAttribute(
            SessionCounter.COUNTER); 
%>

Number of online user(s): <%= counter.getActiveSessionNumber() %>
</body>
</html>

The final step to make the listener working is to register it in the web.xml file. Below is the example how to register the listener in web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
        PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <display-name>Servlet Examples</display-name>

    <listener>
        <listener-class>
            org.kodejava.example.servlet.SessionCounter
        </listener-class>
    </listener>

    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
</web-app>

Here a screen capture of the session counter in action:

Servlet Session Counter

Servlet Session Counter Example