Javaweb之Servlet

Servlet的作用:获取请求数据、处理请求、完成响应。

通常继承HttpServlet抽象类来写Servlet类,一个Servlet类只创建一个对象,默认在客户端第一次访问Servlet类时创建对象。Servlet是单例的,线程不安全。

	<servlet>
		<servlet-name>hello1</servlet-name>
		<servlet-class>cn.itcast.servlet.Hello1Servlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>hello1</servlet-name>
		<url-pattern>/hello1</url-pattern>
	</servlet-mapping>
	<servlet>
		<servlet-name>hello2</servlet-name>
		<servlet-class>cn.itcast.servlet.Hello2Servlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>hello2</servlet-name>
		<url-pattern>/hello2</url-pattern>
	</servlet-mapping>
	<servlet>
		<servlet-name>hello3</servlet-name>
		<servlet-class>cn.itcast.servlet.Hello3Servlet</servlet-class>
		<load-on-startup>2</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>hello3</servlet-name>
		<url-pattern>/hello3</url-pattern>
	</servlet-mapping>

<servlet>元素中配置<load-on-startup>元素可以让服务器在启动时就创建该Servlet,其中<load-on-startup>元素的值必须是大于等于0的整数,值越小就越先在服务器启动时创建。上例中,服务器启动时,创建Servlet的顺序为Hello1ServletHello2ServletHello3Servlet

Servlet类由我们来写,但对象由服务器来创建,并且由服务器调用相应的方法。

1.Servlet接口

3个生命周期方法:

init(ServletConfig config):Servlet实例对象创建后,调用此方法。服务器会在Servlet第一次被访问时创建Servlet对象,或者服务器在启动时创建Servlet对象。

service(ServletRequest request, ServletResponse response):每访问一次Servlet,执行一次此方法

destroy():服务器销毁Servlet前,调用此方法

2.GenericServlet抽象类

GenericServlet继承了Servlet接口和ServletConfig接口,ServletConfig接口方法如下:


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

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只有service(ServletRequest request, ServletResponse response)一个抽象方法。

【注意】GenericServlet添加了init()方法,并且在生命周期方法init(ServletConfig)内部调用init()方法。如果子类覆盖了GenericServletinit(ServletConfig)方法,那么this.config=config这一条语句就会被覆盖了,也就是说GenericServlet的实例变量config的值为null,那么所有依赖config的方法都不能使用了。如果真的希望完成一些初始化操作,应该重写init()方法,而不是生命周期方法init(ServletConfig)。

3.HttpServlet抽象类

HttpServlet是GenericServlet的子类,实现了GenericServlet中的抽象方法。

public abstract class HttpServlet extends GenericServlet {
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        ……
    }
    @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);
    }
    ……
}

HttpServletservice(ServletRequest, ServletResponse):内部会把ServletRequest强转成HttpServletRequest,把ServletResponse强转成HttpServletResponse,然后调用service(HttpServletRequest,HttpServletResponse)方法。

service(HttpServletRequest,HttpServletResponse):内部通过HttpRequest的getMethod()获取请求方式,然后根据请求方式调用相应的处理方法。例如:请求方式为get时,调用doGet()方法;请求方式是post时,调用doPost()方法。

因此,创建HttpServlet类时,应该重写doGet()或doPost()方法。

4.Servlet在web.xml中的配置

  <servlet>
	<servlet-name>servletName</servlet-name>
	<servlet-class>servlet的全类名</servlet-class>
  </servlet>
  <servlet-mapping>
	<servlet-name>servletName</servlet-name>
	<url-pattern>servletPath<url-pattern>
  </servlet-mapping>

【注意】:

(1)一个<servlet-mapping>中给出多个<url-pattern>

(2)可以在<url-pattern>中使用通配符*
  <url-pattern>/*<url-pattern>:表示匹配任何路径
  <url-pattern>/do/*<url-pattern>:表示匹配以/do开头的任何路径
  <url-pattern>*.do<url-pattern>:表示匹配任何以“.do”结尾的路径

通配符要么在开头,要么在结尾,不能在中间,例如:/*.do就是错误的。

如果不使用通配符,那么必须以“/”开头,例如:<url-pattern>abc</url-pattern>就是错误的

通配符是一种模糊匹配URL方式,如果存在更具体的<url-pattern>,那么访问路径优先匹配具体的<url-pattern>。例如:

	<servlet>
		<servlet-name>hello1</servlet-name>
		<servlet-class>cn.itcast.servlet.Hello1Servlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>hello1</servlet-name>
		<url-pattern>/servlet/hello1</url-pattern>
	</servlet-mapping>
	<servlet>
		<servlet-name>hello2</servlet-name>
		<servlet-class>cn.itcast.servlet.Hello2Servlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>hello2</servlet-name>
		<url-pattern>/servlet/*</url-pattern>
	</servlet-mapping>

当访问路径为http://localhost:8080/JavaWeb/servlet/hello1时,优先匹配hello1的路径。

猜你喜欢

转载自blog.csdn.net/qq_41706150/article/details/80141215