Servlet 实例

从零写一个可运行的 Servlet:注解映射、响应输出、部署与访问。

Beginner
Key Points用 @WebServlet 声明 URL,重写 doGet 写响应,打成 war 放进容器的 webapps 目录即可访问。

完整代码

Java
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet(name = "hello", urlPatterns = {"/hello", "/hi"})
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        String name = req.getParameter("name");
        if (name == null || name.isBlank()) {
            name = "World";
        }
        try (PrintWriter out = resp.getWriter()) {
            out.println("<!DOCTYPE html>");
            out.println("<html><body>");
            out.println("<h1>Hello, " + escape(name) + "</h1>");
            out.println("</body></html>");
        }
    }

    private static String escape(String s) {
        return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
    }
}

urlPatterns is an array, so one servlet can serve several URLs. name is just an internal identifier and may be omitted.

等价于 web.xml

XML
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         version="6.0">
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.example.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

Annotation or web.xml — pick one. web.xml lets you change mappings without recompiling and overrides annotations when both exist.

访问与响应

Bash
curl -s "http://localhost:8080/myapp/hello?name=Ada"
Output
<!DOCTYPE html>
<html><body>
<h1>Hello, Ada</h1>
</body></html>

URL 映射的三种写法

PatternMatches
/hello只有 /hello
/api/*/api/users、/api/orders/1
*.do任意以 .do 结尾的路径
/ is the default servlet mapping and swallows everything unmatched, static assets included — get it wrong and every CSS and image 404s. Use /* to wrap static resources, / to handle only unmatched requests; the two are not the same.

Friends & Partners