Java Building Simple Web Server

Building Simple Web Servers in Java

Building a web server in Java is a great way to understand the basics of HTTP and server-client communication. Java provides several ways to create web servers, from basic implementations using sockets to more advanced frameworks like Jetty and Spring Boot. This guide will cover:

  1. Basic HTTP Server using HttpServer (Java SE)
  2. Creating a Simple Web Server using Sockets
  3. Using Jetty to Build a Web Server
  4. Building a Web Server with Spring Boot

1. Basic HTTP Server using HttpServer (Java SE)

Java SE provides a lightweight HTTP server API in the com.sun.net.httpserver package. This is ideal for creating simple web servers quickly.

Example: Simple HTTP Server

  • Setup: Add the necessary imports.
Java
  import com.sun.net.httpserver.HttpServer;
  import com.sun.net.httpserver.HttpHandler;
  import com.sun.net.httpserver.HttpExchange;

  import java.io.IOException;
  import java.io.OutputStream;
  import java.net.InetSocketAddress;
  • Creating the Server:
Java
  public class SimpleHttpServer {
      public static void main(String[] args) throws IOException {
          HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
          server.createContext("/test", new MyHandler());
          server.setExecutor(null); // creates a default executor
          server.start();
          System.out.println("Server started on port 8000");
      }

      static class MyHandler implements HttpHandler {
          @Override
          public void handle(HttpExchange exchange) throws IOException {
              String response = "Hello, World!";
              exchange.sendResponseHeaders(200, response.length());
              OutputStream os = exchange.getResponseBody();
              os.write(response.getBytes());
              os.close();
          }
      }
  }
  • Explanation:
  • HttpServer.create(): Creates an HTTP server bound to the specified port.
  • createContext(): Creates a new context that listens for requests on the specified path.
  • setExecutor(): Sets the executor used to handle requests. null creates a default executor.
  • start(): Starts the server.
  • handle(): Handles incoming HTTP requests.

2. Creating a Simple Web Server using Sockets

Using sockets gives you full control over the server’s behavior. This example demonstrates a basic HTTP server using raw sockets.

Example: Simple Socket-based HTTP Server

  • Setup: Add the necessary imports.
Java
  import java.io.BufferedReader;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.io.PrintWriter;
  import java.net.ServerSocket;
  import java.net.Socket;
  • Creating the Server:
Java
  public class SimpleSocketServer {
      public static void main(String[] args) {
          try (ServerSocket serverSocket = new ServerSocket(8080)) {
              System.out.println("Server started on port 8080");

              while (true) {
                  try (Socket clientSocket = serverSocket.accept()) {
                      handleClient(clientSocket);
                  }
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
      }

      private static void handleClient(Socket clientSocket) throws IOException {
          BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
          PrintWriter out = new PrintWriter(clientSocket.getOutputStream());

          // Read the request
          String line;
          while (!(line = in.readLine()).isEmpty()) {
              System.out.println(line);
          }

          // Send the response
          String response = "HTTP/1.1 200 OK\r\n"
                  + "Content-Length: 13\r\n"
                  + "Content-Type: text/plain\r\n"
                  + "\r\n"
                  + "Hello, World!";
          out.print(response);
          out.flush();

          in.close();
          out.close();
      }
  }
  • Explanation:
  • ServerSocket: Listens for incoming connections on the specified port.
  • accept(): Waits for a client to connect.
  • handleClient(): Handles the client’s request and sends a response.
  • Reads the HTTP request from the client and prints it to the console.
  • Sends a simple “Hello, World!” response to the client.

3. Using Jetty to Build a Web Server

Jetty is a lightweight, highly-scalable HTTP server and servlet container. It is ideal for embedding web servers into Java applications.

Example: Simple Jetty Server

  • Setup: Add the Jetty dependency to your project (Maven example):
Java
  <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-server</artifactId>
      <version>11.0.7</version>
  </dependency>
  <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-servlet</artifactId>
      <version>11.0.7</version>
  </dependency>
  • Creating the Server:
Java
  import org.eclipse.jetty.server.Server;
  import org.eclipse.jetty.servlet.ServletContextHandler;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import java.io.IOException;

  public class SimpleJettyServer {
      public static void main(String[] args) throws Exception {
          Server server = new Server(8080);

          ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
          context.setContextPath("/");
          server.setHandler(context);

          context.addServlet(HelloServlet.class, "/hello");

          server.start();
          server.join();
      }

      @SuppressWarnings("serial")
      public static class HelloServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
              resp.setContentType("text/plain");
              resp.setStatus(HttpServletResponse.SC_OK);
              resp.getWriter().println("Hello, World!");
          }
      }
  }
  • Explanation:
  • Server: Creates a new Jetty server instance.
  • ServletContextHandler: Configures the context path and session handling.
  • addServlet(): Maps a servlet to a specific URL pattern.
  • HelloServlet: Defines a simple servlet that handles GET requests and responds with “Hello, World!”.

4. Building a Web Server with Spring Boot

Spring Boot simplifies the process of creating stand-alone, production-grade Spring-based applications. It includes an embedded Tomcat server by default.

Example: Simple Spring Boot Application

  • Setup: Add the Spring Boot dependency to your project (Maven example):
Java
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.5.4</version>
  </dependency>
  • Creating the Application:
Java
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.RestController;

  @SpringBootApplication
  public class SimpleSpringBootApplication {
      public static void main(String[] args) {
          SpringApplication.run(SimpleSpringBootApplication.class, args);
      }

      @RestController
      class HelloController {
          @GetMapping("/hello")
          public String hello() {
              return "Hello, World!";
          }
      }
  }
  • Explanation:
  • @SpringBootApplication: Marks the main class of a Spring Boot application.
  • SpringApplication.run(): Launches the Spring Boot application.
  • @RestController: Marks the class as a REST controller.
  • @GetMapping: Maps HTTP GET requests to the hello() method, which returns “Hello, World!”.

Best Practices

  1. Resource Management: Always close resources like sockets and streams to avoid resource leaks.
  2. Error Handling: Implement proper error handling to ensure your server can handle unexpected situations gracefully.
  3. Security: Ensure your server is secure. Use HTTPS for secure communication, validate input to prevent injection attacks, and handle sensitive data appropriately.
  4. Scalability: Consider scalability when designing your server. Use thread pools, non-blocking I/O, and efficient resource management.
  5. Logging: Implement logging to monitor server activity and diagnose issues.
  6. Configuration: Externalize configuration settings to make your server easier to manage and deploy.

Summary

Building web servers in Java can range from simple implementations using sockets or HttpServer to more advanced solutions with Jetty or Spring Boot. Understanding the basics of HTTP, socket programming, and web frameworks helps you choose the right tool for your needs. By following best practices, you can create robust, secure, and scalable web servers in Java.

Scroll to Top