七的博客

Servlet知识点总结

Java

Servlet知识点总结

最近在接触使用 Java 开发 WEB 页面的技术,接触到了 Servlet 这技术。

Servlet 是 Java 的服务端的技术,可以处理客户端发送的请求,然后生成动态的 HTML 内容给客户端。

可以先看下一个 HelloWorld 例子:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorldServlet extends HttpServlet {
  
  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
      
      // 设置响应内容类型是 html
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      
      // 输出 html 页面内容给客户端
      out.println("<html>");
      out.println("<head><title>Hello World</title></head>");
      out.println("<body>");
      out.println("<h1>Hello World!</h1>");
      out.println("</body></html>");
      
      out.close();
  }
  
}

上面的例子就是大部分 Servlet 代码的典型,看起来还是稍微有点麻烦的 。当浏览器访问这个 Servlet 时,浏览器的界面上就会显示 Hello World!。

如果是使用 PHP 的话,直接这么写就可以:

<?php

// 设置响应内容类型
header("Content-Type: text/html");

// 直接输出 html 页面内容
echo "<html>";
echo "<head><title>Hello World</title></head>";
echo "<body>";
echo "<h1>Hello World!</h1>";
echo "</body></html>";
?>

Servlet 的简单工作流程

  • 当用户在浏览器中点击一个链接或者提交一个表单,浏览器会给服务器发送一个HTTP请求。
  • 服务端收到请求,根据请求地址跟 Servlet 的映射关系,再调用对应的 Servlet 程序。
  • 如果是第一次访问,那么服务端会创建一个 Servlet 的实例。 后续访问就会直接拿缓存中的实例去处理。
  • Servlet 代码做对应的业务逻辑处理,然后拼接 HTML 页面返回给浏览器。

怎么实现一个 Servlet 接口

所有的 Servlet 接口都必须去实现 javax.servlet.Servlet 接口或继承 GenericServlet / HttpServlet。

区别在于:

  • GenericServlet 需要自行判断是 get 还是 post 请求,然后进行分发处理。
  • HttpServlet 则直接提供 doGet、doPost 方法,直接实现这两个方法进行处理即可。 不用手动去判断当前请求是 get 还是 post 请求。

比如下面这个例子:

public class MyServlet extends HttpServlet {

    public void init(ServletConfig config) throws ServletException {
        // 初始化操作
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 处理 GET 方式的请求
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 处理 POST 的请求请求
    }

    public void destroy() {
        // 销毁操作
    }
}

Servlet 请求跟响应对象

Servlet 的请求跟响应对象是非常重要的,整个 Servlet 中使用的最频繁。

  • HttpServletRequest

HttpServletRequest 用于获取浏览器请求的信息,比如请求参数、请求头、请求方法等。

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      // 获取请求参数
      String param = request.getParameter("paramName");
      // 获取请求头参数
      String header = request.getHeader("headerName");
  }
  • HttpServletResponse

HttpServletResponse 用于设置响应信息,如状态码、响应头、响应体等。

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      // 设置返回值状态为 200
      response.setStatus(HttpServletResponse.SC_OK);
      // 设置为 html 页面
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      
      // 输出页面内容
      out.println("<html><body><h1>Hello, World!</h1></body></html>");
  }

配置 Servlet 接口

每一个 Servlet 接口都需要在 web.xml 中进行配置,否则请求的时候会找不到对应的 Servlet 接口,就会报 404 错误。

比如:

<servlet>
    <servlet-name>myServlet</servlet-name>
    <servlet-class>com.suny.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>myServlet</servlet-name>
    <url-pattern>/myServlet</url-pattern>
</servlet-mapping>

上面就是配置了一个 Servlet 接口,解释如下:

  • Servlet 接口类位于 com.suny.MyServlet 。
  • Servlet 的名称为 myServlet。
  • Servlet 的访问路径为 /myServlet ,比如 http://localhost:8080/myServlet

如果有多个 Servlet 接口,只需要依次配置即可。

写一个登录的 Servlet 程序

新建一个 LoginServlet.java 文件,然后写入下面的内容:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 显示登录表单
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head><title>登录界面</title></head>");
        out.println("<body>");
        out.println("<h2>填写登录信息</h2>");
        out.println("<form action='LoginServlet' method='post'>");
        out.println("Username: <input type='text' name='username'><br>");
        out.println("Password: <input type='password' name='password'><br>");
        out.println("<input type='submit' value='Login'>");
        out.println("</form>");
        out.println("</body></html>");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 处理登录请求
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        out.println("<html><body>");
        if ("admin".equals(username) && "password".equals(password)) {
            HttpSession session = request.getSession();
            session.setAttribute("username", username);
            out.println("<h2>欢迎登录, " + username + "!</h2>");
            out.println("<p>登录成功.</p>");
        } else {
            out.println("<h2>登录失败</h2>");
            out.println("<p>用户名或者密码验证失败.</p>");
            out.println("<a href='LoginServlet'>再次尝试登录</a>");
        }
        out.println("</body></html>");
    }
}

上面这个程序, doGet 方法将会向浏览器返回一个登录的 HTML 界面。

doPost 方法处理业务逻辑,验证用户名和密码,然后输出验证结果。

所有的 HTML 页面都通过 Java 代码去生成的,不需要写额外的 HTML 文件。

缺点

从上面这个例子看,HTML 和 Java 代码混在一起 , 不好维护。

而且对于更复杂的页面,没有提示真的很难写的出来。写起来特别的费劲,如果是 HTML 文件中还会有自动提示。