【Java】Servlet原理

1.什么是Servlet

Servlet是JavaWeb三大组件之一(Listener / Filter),属于动态资源,服务器将收到的请求交给Servlet处理

Servlet需要做的事:

>>接收请求数据

>>处理请求

>>完成响应

编写一个Servlet需要两步:

**编写Servlet类

**在web.xml文件中配置Servlet(在Servlet3.0之后用注解实现)

编写Servlet需要我们实现javax.servlet.Servlet接口

public interface Servlet{
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}

接口中有3个生命周期方法:(在Servlet出生、服务、死亡的状态分别调用对应方法

void init(ServletConfig);//Servlet是在第一次被访问时由服务器创建的

void service(ServletRequest,ServletResponse); //接收到一次请求 就调用service()一次

void destroy();  //通常在服务器被关闭时,服务器会去销毁Servlet,在销毁Servlet之前服务器会先去调用Servlet的destroy()方法

剩下两个方法:

getSevletConfig:ServletConfig对象对应web.xml文件(Sevlet3.0之前所需的配置文件)中的<servlet>元素。

该对象用来返回初始化参数和 ServletContext

例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取

getServletInfo:该方法用于返回Servlet的描述信息,这些信息可以是Servlet的作者,版本、版权信息等。

默认情况下,这个方法返回空串。开发人员可以覆盖这个方法来返回有意义的信息

 

2.GenericServlet

GenericServlet.java

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private transient ServletConfig config;
    public GenericServlet() {}
    @Override
    public void destroy() {}
    @Override
    public String getInitParameter(String name) {
        return getServletConfig().getInitParameter(name);
    }
    @Override
    public Enumeration<String> getInitParameterNames() {
        return getServletConfig().getInitParameterNames();
    }
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }
    @Override
    public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }
    @Override
    public String getServletInfo() {
        return "";
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
    public void init() throws ServletException {}
    public void log(String msg) {
        getServletContext().log(getServletName() + ": " + msg);
    }
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
    @Override
    public abstract void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
    @Override
    public String getServletName() {
        return config.getServletName();
    }
}

**GenericServlet的init()方法

在GenericServlet中,定义了一个ServletConfig config实例变量,并在init(ServletConfig)方法中把参数ServletConfig赋给了实例变量。然后在该类的很多方法中使用了实例变量config。

如果子类覆盖了GenericServlet的init(StringConfig)方法,那么this.config=config这一条语句就会被覆盖了,也就是说GenericServlet的实例变量config的值为null,那么所有依赖config的方法都不能使用了。如果真的希望完成一些初始化操作,那么去覆盖GenericServlet提供的init()方法,它是没有参数的init()方法,它会在init(ServletConfig)方法中被调用。

 

**实现了ServletConfig接口

GenericServlet还实现了ServletConfig接口,所以可以直接调用getInitParameter()、getServletContext()等ServletConfig的方法。

3.HttpServlet

HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,

所以通常我们都会通过继承HttpServlet来完成自定义的Servlet

HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)方法,这个方法是HttpServlet自己的方法,不是从Servlet继承来的。

在继承得来的service(..)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,

然后调用service(HttpServletRequest,HttpServletResponse)方法,

这说明子类可以去覆盖service(HttpServletRequest,HttpServletResponse)方法即可,

这就不用自己去强转请求和响应对象了

其实子类也不用去覆盖service(HttpServletRequest,HttpServletResponse)方法,

因为HttpServlet还要做另一步简化操作(doGet() / doPost())

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

        HttpServletRequest  request;
        HttpServletResponse response;

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

在HttpServlet的service(HttpServletRequest,HttpServletResponse)方法会去判断当前请求是GET还是POST

(判断方法:request.getMethod()可以来获取当前请求的类型),

如果是GET请求,那么会去调用本类的doGet()方法,

如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法即可。

 

public class AServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       System.out.println("hello doGet()...");

    }

}

public class BServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response)

           throws ServletException, IOException {

       System.out.println("hello doPost()...");

    }

}

猜你喜欢

转载自blog.csdn.net/TypantK/article/details/82773978