循序渐进写一个Servlet(3) - 分别处理GET和POST

Servlet(Server Applet),全称Java Servlet,是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。本系列将一步步地写出一个Servlet程序。

这篇博文将演示如何分别处理GET和POST请求,以及处理请求中的参数。

编写doGet()和doPost()方法

首先把要实现的功能写好,后面才好调用不是。

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 设定返回内容的MIME类型
    response.setContentType("text/html");

    // 设定内容以UTF-8编码
    response.setCharacterEncoding("utf-8");

    try (PrintWriter writer = response.getWriter()) {
        // 开始输出HTML文本
        writer.print("<html lang=\"en\">");
        writer.print("<body>");
        writer.print("<b>Response from DemoServlet</b>");
        writer.print("<b>Handled by <code>doGet()</code></b>");
        writer.print("</body>");
        writer.print("</html>");
    }
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 设定返回内容的MIME类型
    response.setContentType("text/html");

    // 设定内容以UTF-8编码
    response.setCharacterEncoding("utf-8");

    try (PrintWriter writer = response.getWriter()) {
        // 开始输出HTML文本
        writer.print("<html lang=\"en\">");
        writer.print("<body>");
        writer.print("<b>Response from DemoServlet</b>");
        writer.print("<b>Handled by <code>doPost()</code></b>");
        writer.print("</body>");
        writer.print("</html>");
    }
}

区分HTTP方法

因为servlet是调用service()方法来处理请求的,所以对请求做区分也需要在service()方法中进行。

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

    HttpServletRequest httpServletRequest = (HttpServletRequest) req;
    HttpServletResponse httpServletResponse = (HttpServletResponse) res;

    if ("GET".equalsIgnoreCase(httpServletRequest.getMethod())) {
        doGet(httpServletRequest, httpServletResponse);
    } else if ("POST".equalsIgnoreCase(httpServletRequest.getMethod())) {
        doPost(httpServletRequest, httpServletResponse);
    } else {
        // 如果请求既不是GET也不是POST
        // 那么就返回HTTP 501 NOT IMPLEMENTED状态码
        // 毕竟不能把请求直接扔了,总是要有个返回的
        httpServletResponse.sendError(501);
    }
}

运行起来看看效果

首先发个GET请求

Handling GET request

再发个POST请求

Handling POST request

为什么不用HttpServlet类呢

没错,上面做的,就是自己实现了一个简陋的HttpServlet类,因为是循序渐进嘛,没头没脑的直接砸上来一个,算什么循序渐进。

那么现在就让DemoServlet继承HttpServlet。同时,因为HttpServlet已经在service()方法中实现了判断请求类型,所以DemoServlet中不要覆盖service()方法,只覆盖doGet()和doPost()方法。

public class DemoServlet extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 设定返回内容的MIME类型
        response.setContentType("text/html");

        // 设定内容以UTF-8编码
        response.setCharacterEncoding("utf-8");

        try (PrintWriter writer = response.getWriter()) {
            // 开始输出HTML文本
            writer.print("<html lang=\"en\">");
            writer.print("<body>");
            writer.print("<b>Response from DemoServlet</b>");
            writer.print("<b>Handled by <code>doGet()</code></b>");
            writer.print("</body>");
            writer.print("</html>");
        }
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 设定返回内容的MIME类型
        response.setContentType("text/html");

        // 设定内容以UTF-8编码
        response.setCharacterEncoding("utf-8");

        try (PrintWriter writer = response.getWriter()) {
            // 开始输出HTML文本
            writer.print("<html lang=\"en\">");
            writer.print("<body>");
            writer.print("<b>Response from DemoServlet</b>");
            writer.print("<b>Handled by <code>doPost()</code></b>");
            writer.print("</body>");
            writer.print("</html>");
        }
    }
}

处理请求中的参数

HTTP请求是可以带参数的,有了参数,那就得处理。

处理GET请求的参数

GET请求里带的参数,名字叫查询字符串(query string),是一组或多组key=value格式的键值对。

Query string写在URL后面,以一个问号起头,用&分隔各个键值对,即类似http://localhost:8080/appname/servlet?arg1=value1&arg2=value2&...&argN=valueN。

在代码里使用HttpServletRequest#getQueryString()方法,就可以获取到问号后面的query string,分别用&和=分割字符串,就可以取到每个参数的key和value。

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 设定返回内容的MIME类型
    response.setContentType("text/html");

    // 设定内容以UTF-8编码
    response.setCharacterEncoding("utf-8");

    /*

    String queryString = request.getQueryString();
    String[] queryStrings;

    if (queryString != null) {
        queryStrings = queryString.split("&");
    } else {
        queryStrings = new String[]{};
    }

    */

    // 使用Optional类简化null判断
    Optional<String> optionalQueryString = Optional.ofNullable(request.getQueryString());

    // 如果有query string则取出每个参数
    // 如果没有则返回一个空的String数组
    String[] queryStrings = optionalQueryString.isPresent() ? optionalQueryString.get().split("&") : new String[]{};

    try (PrintWriter writer = response.getWriter()) {
        // 开始输出HTML文本
        writer.print("<html lang=\"en\">");
        writer.print("<body>");
        writer.print("<b>Response from DemoServlet</b>");
        writer.print("<b>Handled by <code>doGet()</code></b>");

        writer.print("<br>");

        // 遍历每个参数
        for (String query : queryStrings) {
            // 取出参数的key和value
            String[] q = query.split("=");

            writer.print(q[0] + " = " + q[1] + "<br>");
        }

        writer.print("<br>");

        writer.print("</body>");
        writer.print("</html>");
    }
}

运行一下,结果是这样子的:

Handling query string

处理POST请求的参数

POST请求的参数就叫参数(parameter),位于请求体(body)里,格式由Content-Type请求头决定。详细介绍可以参考这篇MDN文档。

HttpServletRequest#getParameterMap()方法可以取出请求中的所有参数,并放到一个Map中。

@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 设定返回内容的MIME类型
    response.setContentType("text/html");

    // 设定内容以UTF-8编码
    response.setCharacterEncoding("utf-8");

    // 取出所有参数,得到一个Map
    Map parameterMap = request.getParameterMap();

    try (PrintWriter writer = response.getWriter()) {
        // 开始输出HTML文本
        writer.print("<html lang=\"en\">");
        writer.print("<body>");
        writer.print("<b>Response from DemoServlet</b>");
        writer.print("<b>Handled by <code>doPost()</code></b>");

        writer.print("<br>");

        // 遍历parameterMap
        parameterMap.forEach((k, v) -> writer.print(k + " = " + ((String[]) v)[0] + "<br>"));

        writer.print("</body>");
        writer.print("</html>");
    }
}

本文中将使用application/x-www-form-urlencoded格式做示例。

Handling parameter

系列博文

posted @ 2026-10-06 22:41  boris1993  阅读(2)  评论(0)    收藏  举报