package com.hsj.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;
/**
* 自定义Servlet有三种方式:
* A:实现Servlet接口
* B:继承GenericServlet
* C:继承HttpServlet
*
*
* 自定义Servlet的编写步骤:
* A:自定义类实现Servlet接口并实现接口中所有的方法并打印输出日志方便观察效果
* B:在站点部署描述符文件(WEB-INF/web.xml)中注册自定义的Servlet
* <!-- 注册自定义的Servlet -->
<servlet>
<!-- servlet-name的值可以任意取,但为了方便使用一般写成自定义Servlet类的简单类名 -->
<servlet-name>ServletLifeCycler</servlet-name>
<!-- servlet-class的值为自定义Servlet的完整包名+类名,即完全限定名 -->
<servlet-class>com.hsj.servlet.ServletLifeCycler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletLifeCycler</servlet-name>
<!-- url-pattern的值是我们访问当前Servlet路径的一部分,内容随便写,但为了开发方便,大家都约定:
当前Servlet的简单类名并且把第一个字母小写 -->
<url-pattern>/servletLifeCycler</url-pattern>
</servlet-mapping>
访问Servlet的格式:http://localhost:8080/项目的站点名/url-pattern的值,如:
http://localhost:8080/ServletDemo01/servletLifeCycler
Servlet的工作原理:
String url=http://localhost:8080/ServletDemo01/servletLifeCycler
int startIndex=url.lastIndexOf("/")
url.substring(startIndex)的执行结果为:/servletLifeCycler
在站点部署描述符文件中查找所有的servlet-mapping的url-pattern的值,如果和/servletLifeCycler相等,说明
找到了要访问的Servlet的入口,然后查找和当前servlet-mapping是兄弟关系的servlet-name的值并且存储起来,
继续查找当前servlet-name的父元素servlet-mapping的兄弟节点servlet的子节点servlet-name的内容ServletLifeCycler
然后和之前servlet-mapping的子节点servlet-name的值进行比较看是否相等,如果不相等则继续查询其它的节点,如果相等
则找到了要访问servlet的类的完整包名+类名即servlet的字节点servlet-name的兄弟节点servlet-class的值,然后
通过反射技术就可以实例化自定义的Servlet类了,
Class clz=Class.forName("com.hsj.servlet.ServletLifeCycler");
Object obj=clz.newInstance(); <===> ServletLifeCycler slc=new ServletLifeCycler(); Object obj=slc;
自动调用构造函数,之后自动调用init(ServletConfig config),然后调用service(req,res)完成客户端的处理请求,
之后再次访问则只调用service(req,res);
面试题:请简述Servlet生命周期函数及其执行流程?
init():当用户第一次访问当前Servlet时自动调用,用来完成初始化工作,而且只调用一次。
service():用户每次当前当前Servlet都会自动调用当前方法,用来完成客户端发送过来的请求
destroy():当前Servlet销毁时自动调用的方法,用来做资源释放工作,而且只调用一次。
* @author h
*
*/
public class ServletLifeCycler implements Servlet {
/**
* 默认情况表,当用户第一次访问当前Servlet时自动调用
*/
public ServletLifeCycler(){
System.out.println("===ServletLifeCycler()==");
}
/**
* 当第一次访问当前Servlet时被调用,而且只调用一次,用来做初始化工作
*/
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("===ServletLifeCycler.init(ServletConfig config)====");
}
@Override
public ServletConfig getServletConfig() {
System.out.println("====ServletLifeCycler.getServletConfig()====");
return null;
}
/**
* 当前每次访问Servlet时都会被自动调用,用来处理客户端发送的请求,用户访问多少次当前Servlet就调用多少次当前方法
*/
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("====ServletLifeCycler.service(ServletRequest req, ServletResponse res)====");
}
@Override
public String getServletInfo() {
System.out.println("===ServletLifeCycler.getServletInfo()===");
return null;
}
/**
* 当Servlet销毁时自动调用的方法,用来做资源释放工作,这个方法也是只被调用一次,
* 注意:中断tomcat服务器不会调用当前方法,只有正常关闭tomcat服务器或者重新部署当前项目时才会自动调用当前方法
*/
@Override
public void destroy() {
System.out.println("===ServletLifeCycler.destroy()====");
}
}