简介
静态资源(客户端向服务端发出请求报文服务端直接生成响应报文发送给服务端)无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源
动态资源 (客户端向服务端发出请求报文服务端要先运行生成Java文件获得资源,再将该Java文件转化文响应报文发送给服务端)需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成
动态资源指的不是视图上的动画效果或者是简单的人机交互效果
Servlet是动态资源
是运行在服务端(tomcat)的Java小程序,从代码层面上来讲Servlet就是一个接口
用来接收、处理客户端请求、响应给浏览器的动态资源。在整个Web应用中,Servlet主要负责接收处理请求、协同调度功能以及响应数据。我们可以把Servlet称为Web应用中的“控制器”
不是所有的JAVA类都能用于处理客户端请求,能处理客户端请求并做出响应的一套技术标准就是Servlet
Servlet是运行在服务端的,所以 Servlet必须在WEB项目中开发且在Tomcat这样的服务容器中运行
web项目运行流程
Servlet 开发流程
* 1 创建javaWEB项目,同时将tomcat添加为当前项目的依赖
* 2 再src中创建一个类继承HttpServlet(web.xml是写指向地址的;index.html是页面的东西),
* 在此类中重写方法 service(HttpServletRequest req, HttpServletResponse resp)
* 3 在service方法中,定义业务处理代码
* ①从request对象中获取请求中的任何信息(username 参数)
* ②处理业务的代码
* ③将要响应的数据放入response(使用response创建一个打印流,用该打印流对象读取数据)
* 4 在web.xml中,配置Servlet对应的请求映射路径
Servlet生命周期
Servlet 生命周期分为四个阶段
* 1 实例化 构造器 第一次请求时执行/服务启动时执行(与loadOnStartup有关)
* 2 初始化 init 构造完毕执行
* 3 接收请求,处理请求 服务 service 每次请求都执行
* 4 销毁 destroy 关闭服务时执行一次
* 结论:
* Servlet在Tomcat中是单例的(一个Servlet类在Tomcat中只有一个对象)
Servlet的成员变量在多个线程栈之中是共享的
不建议在service方法中修改成员变量在并发请求时会引发多线程按安全问题
Servlet继承结构
三者之间的关系
GenericServlet抽象类实现Servlet 接口, HttpServlet 抽象类继承GenericServlet抽象类
Servlet 接口
接口及方法说明
Servlet 规范接口,所有的Servlet必须实现
public void init(ServletConfig config) throws ServletException;
初始化方法,容器在构造servlet对象后,自动调用的方法,容器负责实例化一个ServletConfig对象,并在调用该方法时传入
ServletConfig对象可以为Servlet 提供初始化参数
public ServletConfig getServletConfig();
获取ServletConfig对象的方法,后续可以通过该对象获取Servlet初始化参数
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
处理请求并做出响应的服务方法,每次请求产生时由容器调用
容器创建一个ServletRequest对象和ServletResponse对象,容器在调用service方法时,传入这两个对象
public String getServletInfo();
获取ServletInfo信息的方法
public void destroy();
Servlet实例在销毁之前调用的方法
GenericServlet抽象类
(侧重除了service方法以外的其他方法的处理)
GenericServlet 抽象类是对Servlet接口一些固定功能的粗糙实现,以及对service方法的再次抽象声明,并定义了一些其他相关功能方法
private transient ServletConfig config;
初始化配置对象作为属性
public GenericServlet() { }
构造器,为了满足继承而准备
public void destroy() { }
销毁方法的平庸实现-------将抽象方法重写为普通方法,在方法内部没有任何的实现代码
public String getInitParameter(String name)
获取初始参数的快捷方法
public Enumeration<String> getInitParameterNames()
返回所有初始化参数名的方法
public ServletConfig getServletConfig()
获取初始Servlet初始配置对象ServletConfig的方法
public ServletContext getServletContext()
获取上下文对象ServletContext的方法
public String getServletInfo()
获取Servlet信息的平庸实现
public void init(ServletConfig config) throws ServletException()
初始化方法的实现,并在此调用了init的重载方法
//tomcat在调用init方法时,会读取配置信息进入一个ServletConfig对象并将该对象传入init方法
this.config = config-----------------将config对象存储为当前的属性
public void init() throws ServletException
重载init方法,为了让我们自己定义初始化功能的方法
public void log(String msg)
public void log(String message, Throwable t)
打印日志的方法及重载
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
服务方法再次声明
public String getServletName()
获取ServletName的方法
HttpServlet 抽象类
(侧重处理service方法的处理)
abstract class HttpServlet extends GenericServlet HttpServlet抽象类,除了基本的实现以外,增加了更多的基础功能
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
上述属性用于定义常见请求方式名常量值
public HttpServlet() {}
构造器,用于处理继承
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
对服务方法的实现
在该方法中,将请求和响应对象转换成对应HTTP协议的HttpServletRequest HttpServletResponse对象
调用重载的service方法
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
重载的service方法,被重写的service方法所调用
在该方法中,通过请求方式判断,调用具体的do***方法完成请求的处理
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
对应不同请求方式的处理方法
除了doOptions和doTrace方法,其他的do*** 方法都在故意响应错误信息
为Servlet提供配置参数的函数
ServletConfig(多例)
ServletConfig是什么
+ 为Servlet提供初始配置参数的一种对象,每个Servlet都有自己独立唯一的ServletConfig对象
+ 容器会为每个Servlet实例化一个ServletConfig对象,并通过Servlet生命周期的init方法传入给Servlet作为属性
ServletConfig是一个接口,定义了如下API
| 方法名 | 作用 |
| ----------------------- | ------------------------------------------------------------ |
| getServletName() | 获取\<servlet-name>HelloServlet\</servlet-name>定义的Servlet名称 |
| getServletContext() | 获取ServletContext对象 |
| getInitParameter() | 获取配置Servlet时设置的『初始化参数』,根据名字获取值 |
| getInitParameterNames() | 获取所有初始化参数名组成的Enumeration对象 |
作用:将定义的初始值传入ServletConfig对象中,在将该对象传入init方法中,初始值设置成功
ServletContext(单例)
ServletContext是什么
+ ServletContext对象有称呼为上下文对象,或者叫应用域对象(后面统一讲解域对象)
+ 容器会为每个app创建一个独立的唯一的ServletContext对象
+ ServletContext对象为所有的Servlet所共享
+ ServletContext可以为所有的Servlet提供初始配置参数
> 获取资源的真实路径
String realPath = servletContext.getRealPath("资源在web目录中的路径")
无论项目的部署路径发生什么变化,都会动态获取项目运行时候的实际路径
> 获取项目的上下文路径
String contextPath = servletContext.getContextPath();
项目的部署名称,也叫项目的上下文路径,在部署进入tomcat时所使用的路径,该路径是可能发生变化的,通过该API动态获取项目真实的上下文路径
>域对象的相关API
域对象: 一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同---------------------在一定范围内能对数据库进行存储传输的对象
ServletContext代表应用,所以ServletContext域也叫作应用域,是webapp中最大的域,可以在本应用内实现数据的共享和传递
webapp中的三大域对象,分别是应用域,会话域,请求域
`后续我们会将三大域对象统一进行讲解和演示`,三大域对象都具有的API如下
| API | 功能解释 |
| ------------------------------------------- | ------------------- |
| void setAttribute(String key,Object value); | 向域中存储/修改数据 |
| Object getAttribute(String key); | 获得域中的数据 |
| void removeAttribute(String key); | 移除域中的数据 |
代码举例:
在servlet1中存入数据(向域对象中)(以及测试ServletConfig相关API,域对象API)
@WebServlet(urlPatterns = "/servlet1",initParams = {@WebInitParam(name="keya",value = "valueA"),@WebInitParam(name="keyb",value = "valueB")}
)public class Servlet1 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("--------------------ServletConfig获取参数-------------------------");ServletConfig servletConfig=this.getServletConfig();//获取初始配置信息//根据参数名获取参数值String keya = servletConfig.getInitParameter("keya");System.out.println(keya);//获取所有的初始参数名//hasMoreElements 1 判断有没有下一个参数 如果有放回true 如果没有返回false//nextElement 取出下一个元素 向下移动游标Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();while (initParameterNames.hasMoreElements()){String pname = initParameterNames.nextElement();System.out.println(pname+"="+getInitParameter(pname));}System.out.println("--------------------ServletContext获取参数-------------------------");//获取ServletContext//servletContext的唯一性ServletContext servletContext1 = this.getServletContext();ServletContext servletContext2 = req.getServletContext();System.out.println(servletContext1==servletContext2);//servletContext通过key名获取默认的value值String encoding = servletContext1.getInitParameter("encoding");System.out.println(encoding);//获取所有key的值Enumeration<String> parameterNames = servletContext1.getInitParameterNames();//利用循环获取所有的默认value值while (parameterNames.hasMoreElements()){String s = parameterNames.nextElement();System.out.println(s+"="+servletContext1.getInitParameter(s));}//作为域对象一定会有的API/*
| void setAttribute(String key,Object value); | 向域中存储/修改数据 |
| Object getAttribute(String key); | 获得域中的数据 |
| void removeAttribute(String key); | 移除域中的数据 |*///向域中增加/修改数据servletContext1.setAttribute("ka","va");servletContext1.setAttribute("ka","vaa");//获得域中的数据//Object ka = servletContext1.getAttribute("ka");(强转)String ka = (String)servletContext1.getAttribute("ka");//移除域中的数据servletContext1.removeAttribute("ka");}
}
在servlet3中读取数据(以及测试ServletContext的获取路径的API)
@WebServlet(urlPatterns = "/servlet3")
public class Servlet3 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext servletContext=getServletContext();//向upload目录中写入一个文件//获得一个指定项目部署位置下的某个文件/目录的磁盘真实路径的API-----------------动态获取某个文件目录的路径String path=servletContext.getRealPath("upload");FileOutputStream fos=new FileOutputStream(path+"/a.txt");System.out.println(path);//获得项目部署的上下文路径,项目的访问路径------------动态获取上下文路径//后续的学习在项目中使用相对和绝对路径找目标资源//例如:相对:servlet1 绝对:/demo03/servlet1(使用绝对路径时要带上项目的上下文路径)String contextPath = servletContext.getContextPath();System.out.println(contextPath);//从域对象中读取数据(在servlet1中添加的)String ka = (String)servletContext.getAttribute("ka");//强转System.out.println(ka);}
}