Servlet面试题

  • servlet的生命周期
  • servlet的线程安全问题
  • 如何解决?
  • get 与 post 区别


servlet的生命周期

  1. servlet初始化—init()方法
    ①第一次创建Servlet时调用,只会执行一次初始化
    ②默认是第一次处理请求时创建Servlet,也可以设置为服务器第一次启动时就创建Servlet
public void init() throws ServletException {
	// 初始化代码...
}
  1. servlet处理请求:service()方法
    ①处理来自浏览器的请求,将处理后的结果响应给浏览器
    ②servlet接收到请求后,调用service方法来进行处理,service中针对不同的请求进行匹配,选择调用doPost或doGet等方法
    ③在编写servlet时,需要实现doPost/doGet等方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    long lastModified;
    if (method.equals("GET")) {
		//处理get请求
        }
    } else if (method.equals("HEAD")) {
       
    } else if (method.equals("POST")) {
        this.doPost(req, resp);
    } else if (method.equals("PUT")) {
        this.doPut(req, resp);
    } else if (method.equals("DELETE")) {
        this.doDelete(req, resp);
    } else if (method.equals("OPTIONS")) {
        this.doOptions(req, resp);
    } else if (method.equals("TRACE")) {
        this.doTrace(req, resp);
    } else {
    	//其他
    }
}
  1. servlet长时间没有被调用或服务器关闭,会调用destroy()方法销毁servlet,由JVM垃圾回收器来回收servlet
    destroy方法只会执行一次
    执行后,该servlet被标记为垃圾,等待回收

servlet的线程安全问题

servlet不是线程安全的

servlet是单例的,初始化后,只有长时间不再接受请求或容器关闭时,这个servlet才会销毁,多个请求线程都访问的是这一个servlet

一个servlet在处理第一次请求前进行实例化,初始化。或在容器启动时初始化(需要设置)
后续调用这个servlet的请求,都是独立的线程来调用service方法,存在线程安全问题

如何解决?

  1. 不在servlet中使用成员变量,线程之间没有资源竞争,线程安全
  2. 使用ThreadLocal为每个线程提供一份独立的变量
  3. 给处理请求的方法加锁;造成阻塞
protected synchronized void doGet(HttpServletRequest req, HttpServletResponse resp) 
								throws ServletException, IOException {
}
  1. 实现SingleThreadModel接口;会为每个用户创建一个servlet实例,性能差(已弃用)
public class DormServlet extends HttpServlet implements SingleThreadModel

get 与 post 区别

HTTP请求默认使用get

get

post

参数在url中

参数在 resquest body 请求体中

有长度限制

没有长度限制

暴露在url中,不安全

隐藏在请求体中,安全

只能url编码

支持多种编码

产生一个TCP数据包

产生两个TCP数据包

获取服务器中的数据

修改服务器上的数据