1.Servlet的继承关系
1.Servlet的继承关系 1.继承关系 三者可以根据ctrl+鼠标左键进入 javax.servlet.Servlet接口:(下面有个抽象类) javax.servlet.GenericServlet抽象类(这个抽象类又包含了) javax.servlet.Http.HttpServlet抽象子类(也是个抽象子类) 2.相关方法 javax.servlet.Servlet接口: void init(config)--初始化方法 void service(request,respon) -服务方法 void destroy() --销毁方法 javax.servlet.GenericServlet抽象类中: void service(request,respon) -仍然是抽象的 javax.servlet.Http.HttpServlet抽象子类: void service(request,respon) -不是抽象的 1. String method=req.getMethod();获取请求的方式 2. 各种if判断,根据请求方式不同,决定去调用不同的do方法 (ctrl+F12快速找到) if (method.equals("GET")) { this.doGet(req, resp); } else if (method.equals("HEAD")) { this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); }else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } 3. 在HttpServlet这个抽象类中,do方法都差不多: protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String msg = lStrings.getString("http.method_get_not_supported"); this.sendMethodNotAllowed(req, resp, msg); } private void sendMethodNotAllowed(HttpServletRequest req, HttpServletResponse resp, String msg) throws IOException { String protocol = req.getProtocol(); if (protocol.length() != 0 && !protocol.endsWith("0.9") && !protocol.endsWith("1.0")) { resp.sendError(405, msg); } else { resp.sendError(400, msg); } } 3.小结 1) 继承关系:HttpServlet -> GenericServlet ->Servlet 2) Servlet中核心方法:init(),servlet(),destroy() 3) 服务方法:当有请求过来时,service方法会自动响应(其实都是tomcat容器调用的) 在HttpServlet中我们会去分析请求的方式:到底是get、post、head还是delete等 然后再决定调用的是哪个do开头的方法 那么在HttpServlet中这些do方法默认都是405的实现风格--要我们去子类实现对于的方法,否则默认会报405错误 4) 因此,我们在新建Servlet,我们才会去考虑请求方法,从而决定重写哪个do方法
2.Servlet的生命周期
1)生命周期:从出生到死亡的过程就是生命周期。对于Servlet中的三个方法:init()、service()、destory() 2)默认情况下: 第一次接受请求时:这个Servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service() 从第二次请求开始,每一次刷新都是一次服务 当容器关闭时,其中的所有servlet实例会被销毁,调用销毁方法 3)所以Servlet实例tomcat只会创建一个,所有的请求都是这个实例去响应 默认情况下,第一次请求时,tomcat才会去实例化,初始化然后再服务。这样的好处-->提高系统的启动速度 坏处-->第一次请求时耗时太长,对第一个人不公平 因此得出:如果要提高系统的启动速度,当前默认情况就是这样;如果要提高响应速度,我们应该设置Servlet的初始化时机 4)Servlet的初始化时机: 默认是第一次接受请求时,实例化、初始化 我们可以通过<load-on-startup>(在web.xml里面配置)来设置servlet启动的先后顺序,数字越小,越靠前 这样的话随着tomcat启动已经完成了初始化 <servlet> <servlet-name>Demo02Servlet</servlet-name> <servlet-class>com.atguigu.servlets.Demo02Servlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> 5)Servlet在容器中是:单例的(不管是谁访问创造一个实例)、线程不安全的(一个线程在正常访问资源1的时候,但突然另一个线程把资源1改变了,导致刚才的线程无法正常访问) -单例:所有的请求都是同一个实例去响应 -线程不安全:一个线程需要根据这个实例中的某个成员变量值取做逻辑判断,但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化 -我们已经知道了servlet是线程不安全的,所以尽量不要在servlet中定义成员变量。如果不得不去定义,那么(1)不要去修改成员变量的值 (2)不要去根据成员变量的值做一些逻辑判断