上篇通过课本上的实例学习了Servelt怎么使用,从这篇开始详细的学习其中的细节。

实现Servlet

实现一个自己的Servlet类,可以通过直接去实现Servlet接口,也可以去继承实现了Servlet接口的GenericServlet类,也可以去继承间接实现了Servlet接口的HttpServlet类,它们的关系如下:
这里写图片描述

Servlet的核心方法

建立一个继承了Servlet接口的类可以直观地看到Servlet中要求被覆写的一些重要方法:

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class MyServlet implements Servlet {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void init(ServletConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
        // TODO Auto-generated method stub

    }

}

init()方法将在第一次创建Servlet时被调用,且后面不会再调用它。用来创建和加载一些初始化数据。

destroy()方法是在Servlet生命周期结束时被调用,且之前不会去调用它。用来关闭和数据库的连接,终止服务线程,将Cookie写回磁盘等操作。

service()方法是Servlet中最核心的方法,用来处理来自客户端的请求。如果是去继承实现了Servlet接口的GenericServlet类,那么只要求重写这个serivce()方法:

import java.io.IOException;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class MyServlet extends GenericServlet {

    @Override
    public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
        // TODO Auto-generated method stub

    }

}

更简便和常用的方式是去继承HttpServlet类,这时并不要求覆写任何方法:

import javax.servlet.http.HttpServlet;

public class MyServlet extends HttpServlet {

}

但这样显然就没有可用价值,在网上找了HttpServlet类的源码,其中有两个service()方法,一个是覆写了父类抽象的service()方法:

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

    HttpServletRequestrequest;
    HttpServletResponse response;

    try {
        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;
    } catch (ClassCastException e) {
        throw new ServletException("non-HTTP request or response");
    }
    service(request, response);
}

在该方法中仅是对传进来的ServletRequest类的参数做了检查,然后调用了另一个service()方法:

protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

    String method = req.getMethod();

    if (method.equals(METHOD_GET)) {
    long lastModified = getLastModified(req);
    if (lastModified == -1) {
        // servlet doesn't support if-modified-since, no reason
        // to go through further expensive logic
        doGet(req, resp);
    } else {
        long ifModifiedSince;
        try {
        ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
        } catch (IllegalArgumentException iae) {
        // Invalid date header - proceed as if none was set
        ifModifiedSince = -1;
        }
        if (ifModifiedSince < (lastModified / 1000 * 1000)) {
        // If the servlet mod time is later, call doGet()
        // Round down to the nearest second for a proper compare
        // A ifModifiedSince of -1 will always be less
        maybeSetLastModified(resp, lastModified);
        doGet(req, resp);
        } else {
        resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        }
    }

    } else if (method.equals(METHOD_HEAD)) {
    long lastModified = getLastModified(req);
    maybeSetLastModified(resp, lastModified);
    doHead(req, resp);

    } else if (method.equals(METHOD_POST)) {
    doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {
    doPut(req, resp);

    } else if (method.equals(METHOD_DELETE)) {
    doDelete(req, resp);

    } else if (method.equals(METHOD_OPTIONS)) {
    doOptions(req,resp);

    } else if (method.equals(METHOD_TRACE)) {
    doTrace(req,resp);

    } else {
    //
    // Note that this means NO servlet supports whatever
    // method was requested, anywhere on this server.
    //

    String errMsg = lStrings.getString("http.method_not_implemented");
    Object[] errArgs = new Object[1];
    errArgs[0] = method;
    errMsg = MessageFormat.format(errMsg, errArgs);

    resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
    }
}

暂不去关注其细节,但仍能看到该方法中的分支语句调用了不同的do*()方法,这就是根据状态的不同以及客户端的请求不同调用的不同处理方法。一般只需要**覆盖**HttpServlet中的doGet()doPost()方法,并使其实现一样的功能(一个调用另一个)即可。

实际上前者是处理那些未指定method参数或指定其值为”get”的HTML表单提交,后者是处理指定了参数为”post”的HTML表单提交,很多时候目的是一样的。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐