tomcat的容器等级分为四个等级,servlet的容器管理context容器,一个context对应一个web工程。Engine是个引擎容器,HOST是主机容器
servlet 是在服务器上运行的小程序,一个 servlet 就是一个 Java 类,并且可以通过 “请求 - 响应” 编程模式来访问这个驻留在服务器内存里面的 servlet 程序
在之前创建的JavaEE项目中的src目录下创建一个包:cn.zhukun.web.servlet 在包下新建一个Java class:ServletDemo1 在这个类中实现Servlet接口
package cn.zhukun.web.servlet; import javax.servlet.*; import java.io.IOException; public class ServletDemo1 implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } //提供服务的方法 @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("hello Servlet"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }**配置Servlet:**编辑 web.xml 文件
<!--配置Servlet --> <servlet> <servlet-name>demo1</servlet-name> <servlet-class>cn.zhukun.web.servlet.ServletDemo1</servlet-class> </servlet> <servlet-mapping> <servlet-name>demo1</servlet-name> <url-pattern>/demo1</url-pattern> </servlet-mapping>启动Tomcat: 浏览器输入: http://localhost:8080/day08_tomcat/demo1发现什么都没有 但是在控制台输出之前在ServletDemo1 中写的“hello Servlet”并且浏览器刷新一次出现一次
根据上面两张图总结Servlet工作机制: 在客户端浏览器上输入http://localhost:8080/day08_tomcat/demo1(通过localhost:8080找到Tomcat服务器,通过day08_tomcat找到Tomcat下部署的web项目,通过demo1找到对应的Servlet程序) 将HTTP请求发送给web服务器Tomcat,此时请求的Servlet并未被初始化,Tomcat服务器解析web.xml根据web.xml中servlet映射找到demo1对应的是ServletDemo1 程序,于是从磁盘项目文件中将ServletDemo1加载至Tomcat容器的Servlet容器中。Tomcat服务器将HTTP请求解析为request对象转至Servlet容器中的ServletDemo1程序处理,处理完后返回response,Tomcat再将response转换成HTTP响应返送给客户端
Tomcat解析web.xml文件的过程: Tomcat首先根据demo1遍历地去找到对应的 <url-pattern>/demo1</url-pattern>,通过<url-pattern>/demo1</url-pattern>找到<servlet-name>demo1</servlet-name>,通过<servlet-name>demo1</servlet-name> 找到<servlet-class>cn.zhukun.web.servlet.ServletDemo1</servlet-class> Tomcat将全类名对应的字节码文件加载进内存。Class.forName();创建对象.cls.newInstance();调用方法——service() (因为实现了Servlet方法所以一定会有service方法)
Servlet工作原理: Servlet接口定义了Servlet与servlet容器之间的契约。这个契约是:Servlet容器将Servlet类载入内存,并产生Servlet实例和调用它具体的方法。但是要注意的是,在一个应用程序中,每种Servlet类型只能有一个实例。
用户请求致使Servlet容器调用Servlet的Service()方法,并传入一个ServletRequest对象和一个ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如TomCat)封装好的,并不需要程序员去实现,程序员可以直接使用这两个对象。
ServletRequest中封装了当前的Http请求,因此,开发人员不必解析和操作原始的Http数据。ServletResponse表示当前用户的Http响应,程序员只需直接操作ServletResponse对象就能把响应轻松的发回给用户。
对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象
Servlet接口下的五个方法: 1、初始化方法,只在Servlet创建时执行(只会执行一次)
@Override public void init(ServletConfig servletConfig) throws ServletException { }2、提供服务的方法,每当Servlet被访问时就会执行(执行多次)
@Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { }3、销毁方法,在服务器正常关闭时执行(执行一次)
@Override public void destroy() { }4、获取ServletConfig对象(Servlet的配置对象)
@Override public ServletConfig getServletConfig() { return null; }5、获取Servlet的一些信息。比如版本,作者…等
@Override public String getServletInfo() { return null; }测试一下: 新建一个ServletDemo2
package cn.zhukun.web.servlet; import javax.servlet.*; import java.io.IOException; public class ServletDemo2 implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.printf("init........."); } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.printf("service......"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { System.out.printf("destroy......"); } }配置web.xml
<servlet> <servlet-name>demo2</servlet-name> <servlet-class>cn.zhukun.web.servlet.ServletDemo2</servlet-class> </servlet> <servlet-mapping> <servlet-name>demo2</servlet-name> <url-pattern>/demo2</url-pattern> </servlet-mapping>运行: 浏览器再刷新两次后: 关闭Tomcat服务器后:
1、被创建:执行init方法,只执行一次 Servlet什么时候被创建?(默认情况下,第一次被访问时Servlet被创建) 可以配置执行Servlet的创建时机。 在标签下配置
第一次被访问时创建 <load-on-startup>的值为负数在服务器启动时创建<load-on-startup>的值为0或正整数Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的,多个用户同时访问时,可能存在线程安全问题。 (解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值)
2、提供服务:执行service方法,执行多次 每次访问Servlet时,Service方法都会被调用一次。 3、被销毁:执行destroy方法,只执行一次 Servlet被销毁时执行,服务器关闭时,Servlet被销毁之前执行,一般用于释放资源(只有服务器正常关闭时,才会执行destroy方法)
支持注解配置。可以不需要web.xml配置文件 1、创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml 注意:Java EE version 必须选择 Java EE 5以上的(只有Java EE 5以上才满足3.0以上) 最下面的Create web.xml 不勾选 2、定义一个类,实现Servlet接口 3、复写方法 4、 在类上使用@WebServlet注解,进行Servlet配置
注意:
package cn.zhukun.web.servlet; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException; @WebServlet(urlPatterns = "/demo") public class ServletDemo implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.printf("servlet3.0 来了......"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
查看一下@WebServlet注解类
package javax.servlet.annotation; @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Documented public @interface WebServlet { java.lang.String name() default ""; java.lang.String[] value() default {}; java.lang.String[] urlPatterns() default {}; int loadOnStartup() default -1; javax.servlet.annotation.WebInitParam[] initParams() default {}; boolean asyncSupported() default false; java.lang.String smallIcon() default ""; java.lang.String largeIcon() default ""; java.lang.String description() default ""; java.lang.String displayName() default ""; }最重要的属性用value表示,而WebServlet里urlPatterns()是最重要的,所以 @WebServlet(urlPatterns = "/demo")可以写成@WebServlet(value = "/demo") value只有一个属性的话可以省略不写 所以最终可以直接写成@WebServlet("/demo")
其中demo是资源路径也就是urlPatterns()(浏览器网址中根据资源路径来确定访问哪个servlet)
1、 IDEA会为每一个tomcat部署的项目单独建立一份配置文件 查看控制台的log: Using CATALINA_BASE: “C:\Users\zhukun.IntelliJIdea2019.3\system\tomcat\Tomcat_8_0_0_day9_Servlet” 2、工作空间项目和tomcat部署的web项目 tomcat真正访问的是“tomcat部署的web项目”,“tomcat部署的web项目"对应着"工作空间项目” 的web目录下的所有资源 3、WEB-INF目录下的资源不能被浏览器直接访问。 4、断点调试:点击"绿色小虫子"启动 dubug 启动 按 执行下一步