Handling HTTP Requests and Responses in Java Web Applications

HTTP Response Object

Overview of the Response Object

In web applications, a response represants the server's processed result of a client request, delivered back to the client. In B/S architecture, this means returnign data to the browser. The response object in JavaWeb is used to implement this functionality.

The Servlet specification defines both protocol-independent (ServletResponse) and protocol-dependent (HttpServletResponse) interfaces. This discussion focuses on HTTP-related responses using HttpServletResponse. The servlet container (like Tomcat) provides the implementation; developers do not need to create custom implementations. The container instantiates the object and passes it to servlet methods like doGet and doPost.

Common HTTP Status Codes

Status Code Description
200 Success
302, 307 Redirection (307 is newer)
304 Resource not modified (cache used)
400 Bad request (often invalid parameters)
404 Resource not found
405 HTTP method not allowed
500 Internal server error

General categories:

  • 1xx: Informational
  • 2xx: Success
  • 3xx: Redirection
  • 4xx: Client error
  • 5xx: Server error

Practical Examples

1. Outputting Chinese Text with Byte Stream

When outputting non-ASCII text via a byte stream, character encoding mismatches between the server and browser can cause garbled text. The server's default encoding (e.g., UTF-8) may differ from the browser's default (e.g., GBK). Solutions include setting the response header Content-Type to specify the charset.

public class ByteStreamEncodingServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String message = "Byte stream output with Chinese characters";
        // Recommended approach: Set content type and charset
        resp.setContentType("text/html;charset=UTF-8");
        ServletOutputStream output = resp.getOutputStream();
        output.write(message.getBytes("UTF-8"));
    }
}

2. Outputting Chinese Text with Character Writer

Using PrintWriter also requires setting the correct charset before obtaining the writer to prevent internal encoding issues.

public class WriterEncodingServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String text = "Character writer output with Chinese";
        // Set encoding and content type before getting writer
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write(text);
    }
}

The method setContentType("text/html;charset=UTF-8") performs two actions: sets the response object's character set (affecting the PrintWriter) and informs the browser of the content type and charset.

3. Generating a CAPTCHA Image

Images can be generated dynamically using BufferedImage and Graphics2D, then written to the response output stream.

public class CaptchaServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int width = 180;
        int height = 40;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();

        graphics.setColor(Color.LIGHT_GRAY);
        graphics.fillRect(0, 0, width, height);
        graphics.setColor(Color.BLUE);
        graphics.drawRect(0, 0, width - 1, height - 1);

        Random rand = new Random();
        graphics.setColor(Color.DARK_GRAY);
        for (int i = 0; i < 8; i++) {
            graphics.drawLine(rand.nextInt(width), rand.nextInt(height),
                               rand.nextInt(width), rand.nextInt(height));
        }

        graphics.setFont(new Font("Arial", Font.BOLD, 28));
        graphics.setColor(Color.RED);
        String captcha = "";
        for (int i = 0; i < 4; i++) {
            captcha += rand.nextInt(10);
        }
        graphics.drawString(captcha, 30, 30);
        graphics.dispose();

        resp.setContentType("image/jpeg");
        ImageIO.write(image, "jpg", resp.getOutputStream());
    }
}

4. Controlling Cache with Response Headers

Static resources can be cached by clients. The Expires header defines a future time until which the resource is considered fresh.

public class CacheControlServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Cache for 1 hour
        long expiryTime = System.currentTimeMillis() + 3600_000;
        resp.setDateHeader("Expires", expiryTime);
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("Cached content");
    }
}

5. Refreshing the Page Automatically

The Refresh header instructs the browser to reload the page or navigate to a new URL after a specified delay.

public class AutoRefreshServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.write("Redirecting in 3 seconds...");
        // Refresh after 3 seconds to a login page
        resp.setHeader("Refresh", "3;URL=/login.html");
    }
}

6. Request Redirection

Redirection is a client-side action where the browser makes a new request to a different URL. The address bar changes.

public class RedirectionServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Redirect to another servlet
        resp.sendRedirect("DestinationServlet");
        // Internally, this sets status 302 and Location header
    }
}

7. File Download

To force a file download, set the Content-Type to application/octet-stream and the Content-Disposition header to attachment.

public class FileDownloadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String filePath = getServletContext().getRealPath("/uploads/image.png");
        File file = new File(filePath);

        resp.setHeader("Content-Type", "application/octet-stream");
        resp.setHeader("Content-Disposition", "attachment;filename=" + file.getName());

        try (InputStream in = new FileInputStream(file);
             OutputStream out = resp.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
    }
}

8. Important Notes on Response Objects

  • The byte stream (getOutputStream()) and character writer (getWriter()) are mutually exclusive; only one can be used per response.
  • Streams obtained from the response object do not need to be closed manually; the container handles cleanup.
public class ResponseNotesServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Using OutputStream
        ServletOutputStream outStream = resp.getOutputStream();
        outStream.write("Data".getBytes());
        // Attempting to also use Writer here would cause an IllegalStateException
    }
}

HTTP Request Object

Overview of the Request Object

A request represents a client's inquiry to the server for resources. In JavaEE, ServletRequest and HttpServletRequest objects encapsulate this, with the latter being HTTP-specific.

Common Methods and Examples

1. Retrieving Path and Address Information

public class RequestInfoServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Server IP: " + req.getLocalAddr());
        System.out.println("Server Port: " + req.getLocalPort());
        System.out.println("Client IP: " + req.getRemoteAddr());
        System.out.println("Request URI: " + req.getRequestURI());
        System.out.println("Request URL: " + req.getRequestURL());
        System.out.println("Query String: " + req.getQueryString());
        System.out.println("Servlet Path: " + req.getServletPath());
    }
}

2. Reading Request Headers

public class HeaderReaderServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Get a single header value
        String encoding = req.getHeader("Accept-Encoding");
        // Get all values for a header (if multiple)
        Enumeration<String> acceptValues = req.getHeaders("Accept");
        // Iterate through all header names
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            System.out.println(name + ": " + req.getHeader(name));
        }
    }
}

3. Obtaining Request Parameters

Form data can be retrieved via getParameter, getParameterValues, getParameterNames, and getParameterMap.

public class ParameterProcessingServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Single value parameter
        String username = req.getParameter("username");
        // Multiple values for same parameter name (e.g., checkboxes)
        String[] hobbies = req.getParameterValues("hobby");
        // All parameter names
        Enumeration<String> paramNames = req.getParameterNames();
        // Direct map of parameters
        Map<String, String[]> paramMap = req.getParameterMap();
    }
}

4. Populating a JavaBean with Request Parameters

Using Apache Commons BeanUtils simplifies mapping parameters to object properties, assuming form field names match bean property names.

import org.apache.commons.beanutils.BeanUtils;

public class BeanPopulationServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = new User();
        try {
            BeanUtils.populate(user, req.getParameterMap());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(user);
    }
}

5. Reading Request Body as a Stream

For non-form data (e.g., raw POST data), the input stream can be read directly.

public class StreamReaderServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletInputStream input = req.getInputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = input.read(buffer)) != -1) {
            System.out.write(buffer, 0, length);
        }
    }
}

6. Handling Chinese Character Encoding in Requests

  • POST requests: Use request.setCharacterEncoding("UTF-8") before accessing parameters.
  • GET requests: In Tomcat 8.5+, URI encoding is handled automatically. For older versions, manual decoding might be required.
public class EncodingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String name = req.getParameter("name");
        // Process name...
    }
}

7. Request Forwarding

Forwarding is a server-side mechanism to pass a request to another resource within the same context. The browser's address bar does not change, and request attributes are preserved.

public class ForwardingServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("dataKey", "sampleValue");
        RequestDispatcher dispatcher = req.getRequestDispatcher("/DestinationServlet");
        dispatcher.forward(req, resp);
    }
}

8. Request Inclusion

Inclusion merges the output of multiple servlets into a single response. The included servlet's response headers are typically ignored.

public class IncludingServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Content from main servlet. ");
        RequestDispatcher dispatcher = req.getRequestDispatcher("/IncludedServlet");
        dispatcher.include(req, resp);
    }
}

Key Points

  • Forwarding vs. Redirection: Forwarding (forward) is server-side, one request, address unchanged. Redirection (sendRedirect) is client-side, two requests, address changes.
  • Request Scope: Attributes set via setAttribute are available during the current request chain (forward/includes).
  • Inclusion Headers: Response headers from an included servlet are generally lost; only the including servlet's headers are sent.

Tags: java servlet HTTP web development Request Handling

Posted on Sun, 24 May 2026 16:47:57 +0000 by stuffradio