Servlet是JavaWeb的三大组件之一,它属于动态资源,Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:接收请求数据、处理请求和完成响应。
Servlet类由我们来写,但对象由服务器来创建,并由服务器来调用相应的方法。
实现Servlet的方式
- 实现javax.servlet.Servlet接口。
- 继承javax.servlet.GenericServlet类。
- 继承javax.servlet.http.httpServlet类。
1、实现javax.servlet.Servlet接口:
public class HelloServlet implements Servlet {
@Override
public void destroy() {
// 这是生命周期方法,会在Servlet销毁之前调用,只调用一次。
}
@Override
public ServletConfig getServletConfig() {
// 获取Servlet的配置信息。也就是web.xml中的信息。
return null;
}
@Override
public String getServletInfo() {
// 获取Servlet的信息
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException {
// 这是生命周期方法,在Servlet对象创建后马上执行,只执行一次
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
//生命周期方法,用来处理请求的方法,每次处理请求都会调用该方法。
}
在web.xml中配置的目的就是把访问路径与一个Servlet绑定在一起。
<servlet> 指定HelloServlet这个Servlet的名称为helloworld。
<servlet-name>helloworld</servlet-name>
<servlet-class>cn.yzgarden.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping> 指定/helloworld访问路径访问的Servlet名为helloworld。
<servlet-name>helloworld</servlet-name>
<url-pattern>/helloworld</url-pattern>
</servlet-mapping>
①服务器创建Servlet
当Servlet第一次被请求时,或服务器启动时,服务器会创建Servlet实例,服务器默认是在Servlet第一次被请求时,创建Servlet实例,如果希望服务器启动时就会创建Servlet实现需要在web.xml中配置,服务器只为一个类型的Servlet创建一个实例对象,所以Servlet是单例的。
②服务器初始化Servlet
当服务器创建Servlet实例后会马上调用Servlet的init(ServletConfig)方法,完成对Servlet的初始化,init(ServletConfig)方法只会被调用一次,服务器会在调用init()方法时传递ServletConfig参数。
③服务器使用Servlet处理请求
当Servlet被请求时,服务器会调用Servlet的service(ServletRequest,ServletResponse)方法,service(ServletRequest,ServletResponse)方法每处理一次请求,就会被调用一次,所以它可以被调用N次。
④服务器销毁Servlet
服务器通常不会销毁Servlet,通常只有在服务器关闭时才会销毁Servlet,服务器会在销毁Servlet之前调用Servlet的destory()方法,通常Servlet是没什么可要释放的,所以该方法一般都是空的。
- ServletRequest:service()方法的参数,它表示请求对象,它封装了所有与请求相关的数据,它是由服务器创建的。
- ServletRespon:service()方法的参数,它表示响应对象,在service()方法中完成对客户端的响应需要使用这个对象。
- ServletConfig:init()方法的参数,它表示Servlet配置对象,它对应Servlet的配置信息,对应web.xml文件中的<servlet>元素。
ServletConfig接口
ServletConfig是Servlet中的init()方法的参数类型,服务器会在调用init()方法时传递ServletConfig对象给init()方法。它对应Servlet的配置信息,对应web.xml文件中的<servlet>元素。
ServletConfig对象是由服务器创建,然后传递给Servlet的init()方法,可以在init()方法使用,ServletConfig对象封装了Servlet在web.xml中的配置信息,它对应<servlet>元素。
- String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值。
- Enumeration getInitParameterNames():用来获取在web.xml中配置的所有初始化参数名称。
- ServletContext getServletContext():用来获取ServletContext对象。
- String getServletName():用来获取Servlet在web.xml文件中的配置名称,即<servlet-name>指定的名称。
<servlet>
<servlet-name>helloworld</servlet-name>
<servlet-class>cn.yzgarden.servlet.HelloServlet</servlet-class>
<init-param> 初始化信息。
<param-name>param-name1</param-name>
<param-value>param-value1</param-value>
</init-param>
</servlet>
可以使用String value1=servletConfig.getInitParameter("param-name1");获取值。
获取所有初始化参数的名称:
Enumeration e=servletConfig.getInitParameterNames();
while(e.hasMoreElements()){
System.out.println(e.nextElement());
}
2、GenericServlet类
GenericServlet是Servlet接口的实现类,它是一个抽象类,它唯一的抽象方法是service()方法。
GenericServlet类实现了Servlet类的方法
- 实现了String getServletInfo()
- 实现了void destroy()
- 实现了void init(ServletConfig config),该方法由Tomcat调用,只调用一次,是这些方法中第一个调用的,会在构造器之后马上被调用。
- 实现了ServletConfig getServletConfig()
GenericServlet类实现了ServletConfig接口
- 实现了ServletContext getServletContext()
- 实现了String getInitParameter(String name)
- 实现了String getServletName()
- 实现了Enumeration getInitParameterNames()
GenericServlet添加了init()方法,该方法会被init(ServletConfig)方法调用,如果要对Servlet进行初始化,那么应该覆盖init()方法,而不是init(ServletConfig)方法。
GenericServlet的init()方法
在GenericServlet中,定义了一个ServletConfig config实例变量,并在init(ServletConfig)方法中把参数ServletConfig赋给了实例变量,然后在该类的很多方法中使用了实例变量config。
GenericServlet还实现了ServletConfig接口,所以可以直接调用getInitParameter()、getServletContext()等ServletConfig的方法。
3、HttpServlet类
HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊请求,通常都会通过继承HttpServlet来完成自定义的Servlet。
HttpServlet类提供了service(HttpServletRequest,HttpServletResponse)方法。
在HttpServlet的service(HttpServletRequest,HttpServletResponse)方法会判断当前请求是GET还是POST,如果是GET请求,那么会调用本类的doGet()方法,如果是POST请求会去调用doPost()方法。
Servlet不是线程安全的,所有不应该在Servlet中随便创建成员变量,可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作,所以不要在Servlet中创建成员,创建局部变量即可,可以创建无状态成员,也可以创建在状态的成员,但状态必须为只读的。
让服务器在启动时就创建Servlet
默认情况下,服务器会在某个Servlet第一次收到请求时创建它,也可以在web.xml中对Servlet进行配置,使服务器启动时就创建Servlet。
<servlet>
<servlet-name>AServlet</servlet-name>
<servlet-class>cn.yzgarden.AServlet</servlet-class>
<load-on-startup>0</load-on-startup> 数字的大小就是创建Servlet的顺序。
</servlet>
<url-pattern>是<servlet-mapping>的子元素,用来指定Servlet的访问路径,即URL,它必须是以"/"开头。可以在<servlet-mapping>中给出多个<url-pattern>,也就是一个Servlet可以有多个访问路径。
<servlet-mapping>
<servlet-name>AServlet</servlet-name>
<url-pattern>/AServlet</url-pattern>
<url-pattern>/BServlet</url-pattern>
</servlet-mapping>
可以在<url-pattern>中使用通配符,星号"*",星号可以匹配任何URL前缀或后缀,使用通配符可以命名一个Servlet绑定一组URL。
<url-pattern>/servlet/*</url-pattern> /servlet/a、/servlet/b,都匹配/servlet/* 路径匹配
<url-pattern>*.do</url-pattern> /abc/def/ghi.do、/a.do,都匹配*.do。 扩展名匹配
<url-pattern>/*</url-pattern> 匹配所有URL,啥都匹配。
通配符要么为前缀,要么为后缀,不能出现在URL中间位置,也不能只有通配符。通配符是一种模糊匹配URL方式,如果存在更具体的<url-pattern>,那么访问路径会去匹配具体的<url-pattern>。