文章目录
什么是Servlet?
- Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
- 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
Servlet及其子类
其中GenericServlet同时也继承了ServletConfig和Serializable。
Servlet中常用方法
- void init(ServletConfig var1) throws ServletException;
- void service(ServletRequest request, ServletResponse response) throws ServletException, IOException;
- void destroy();
- ServletConfig getServletConfig();
- String getServletInfo();
init
用来初始化由Servlet容器实例化的对象。在GenericServlet中实现了该方法。
上面是GenericServlet中的类级属性和init方法的实现,在Servlet容器初始化Servlet时,会根据配置信息创建一个ServletConfig对象,然后将该参数传给init方法完成初始化。
service
每当客户端向Servlet发送请求时,就会调用service方法,该方法会根据请求方式调用相应的方法。
该方法有两个参数:Request和Response,当客户端发送请求时,Servlet容器会创建这两个对象,并且传参给sevice。
distory
该方法用来销毁Servlet。当要卸载应用程序或者关闭Servlet容器时,就会调用该方法。
Servlet的生命周期
Servlet对象的创建到销毁
就是Servlet的生命周期。
下面是Servlet从创建到销毁的过程:
- 当Servlet
第一次
收到请求时,Servlet容器会首先通过反射机制
实例化一个Servlet对象
,然后调用init方法
初始化该对象,最后调用service方法
。 - 当Servlet
第二次
收到请求时只会调用service方法
,之后收到请求也同样如此。 - 终止程序,关闭Servlet容器,此时就会调用
distory
。
下面用代码演示一下该过程:
public class TestServlet01 extends HttpServlet { public TestServlet01(){ System.out.println("正在实例化......"); } @Override public void init() throws ServletException { System.out.println("正在初始化......"); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("正在服务......"); } @Override public void destroy() { System.out.println("正在销毁......"); } }
在服务器第一次收到请求时,首先进行了实例化
,在进行了init(初始化)
,最后就行了 service(服务)
。
在之后的每次请求时,只会调用service
。
最后终止程序,关闭Servlet容器,会调用destory
。
Servlet初始化时机
在上文提到了Servlet的初始化时机,即在第一次收到请求时会进行初始化,其实在配置Servlet时可以设置参数来改变这个时机。
可以在配置时添加如下代码:
<servlet> <servlet-name>TestServlet01</servlet-name> <servlet-class> servlets.TestServlet01</servlet-class> <load-on-startup>0</load-on-startup><!--添加这行代码--> </servlet>
加了该参数之后(参数大于0),一旦Web项目开始,就会加载该Servlet,实例化该Servlet对象并且调用init()初始化,在参数大于0的情况下,参数越小,加载的时机就越靠前,如果参数是负数,跟没有加是一样的效果。
当我们修改完配置后再次运行这段代码:
钝化和活化
钝化: 当服务器正常关闭时,还存活着的session(在设置时间内没有销毁) 会随着服务器的关闭被以文件(“SESSIONS.ser”)的形式存储在tomcat 的work 目录下,这个过程叫做Session 的钝化。
活化: 当服务器再次正常开启时,服务器会找到之前的“SESSIONS.ser” 文件,从中恢复之前保存起来的Session 对象,这个过程叫做Session的活化。
注意:
只有实现了Serializable接口的对象才能被钝化和活化。
Http协议
- 超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的
请求-响应协议
,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式
给出;而 消息内容则具有一个类似MIME的格式
。 - Http连接是一次性连接,当服务器和客户端进行完请求和响应后,连接就会断开,这样http就不会处于等待状态,及时地释放连接可以大大提高服务器的执行效率。
- Http是无状态协议,即服务器不保留与客户交易时的任何状态。这就大大减轻了服务器记忆负担,从而保持较快的响应速度。
- Http请求响应包含两个部分:请求和响应
----------请求
请求包含三个部分:请求行,请求消息头,请求主题
(1) 请求行:包含三个信息:请求的方式 ; 请求的url ; 请求的协议
(2) 请求消息头:包含了很多客户端要告诉服务器的信息(比如说浏览器的版本型号,能够接受响应的类型等)
(3)请求体:
get方式没有请求体,但是有queryString
post方式,有请求体,form data
json格式,有请求体,request payload
---------响应
响应包含三个部分:响应行; 响应头; 响应体
(1)响应行:协议;响应状态码
(2)响应头:包含了服务器的信息
(3)响应的实际内容(比如请求html页面时,响应就时该html文件中的具体内容)
Session
Http是无状态连接,并且是一次性连接,所以同一个Servlet无法判断两次请求是否来自同一个客户端,session就解决了该问题。
会话跟踪技术
- 客户端第一次发请求给服务器,服务器获取尝试session,获取不到,则创建新的,然后响应给客户端。
- 下次客户端发送请求时会将已有的session发送给服务器。
常用API
request.getSession() 获取当前会话,没有创建一个新的 request.getSession(true) 获取当前会话,没有获取一个新的,和无参的一样 request.getSession(false) 获取当前会话,没有返回null,不会创建新的 session.isNew(); 判断当前会话是否是新创建的 session.getMaxInactiveInterval();获取会话的最大非激活间隔时常(一定时间不发送请求,会话就会失效,进行一次请求和响应,该时间就会刷新),默认为1800s session.setMaxInactiveInterval(int interval);设置session的最大非激活间隔时常,interval为正数时表示以秒为单位的时长,负数表示永不失效 session.invalidate();强制让会话失效
演示
public class TestServlet03 extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //HttpSession session = req.getSession(); //Object o = session.getAttribute("123"); HttpSession session = req.getSession(); System.out.println("session id = " +session .getId()); System.out.println("isNew = " + session.isNew()); } }
Session保存作用域
每一个session都有自己的保存作用域,在作用域内以键值对的方式保存信息,拥有相同session的请求(同一个客户端)可以访问该作用域。
Session类中有以下常用API:
- void setAttribute(String key,Object value) ------- 以键值对的方式保存信息。
- Object getAttribute(String key) ------- 通过key来获取value
- void removeAttribute(String key) ----- 通过key来删除键值对
服务器端内部转发和客户端重定向
服务器内部转发
//var是要跳转的Servlet request.getRequestDispatcher(String var).forward(ServletRequest request,ServletResponse response);
客户端只知道自己向Servlet01发送了请求,并且收到了响应,服务器内部发生了什么,自己不知道,所以客户端从发送请求至收到响应自己的地址栏(url)并不会发生改变,页面不会发生跳转。
客户端重定向
//var是重定向的Servlet response.sendRedirect(String var);
此时客户端向test04发送请求,test04响应客户端,让其向test05发送请求。客户端的地址栏会发生改变,页面会跳转。
get()和post()区别
- 客户端直接请求servlet时默认请求方式为get。
- 提交html表单时,使用get方式会将参数数据放在url的后边发给服务器,不安全。
- 提交html表单时,使用post方式会将参数数据放在http的请求体里面发给服务器,较为安全。
- get传送的数据是添加在url后边的,浏览器对url都有自己的长度限制,所以通过get方式发送的数据量较小。
- post发送数据的是添加在http请求体里的,发送数据量较大,但是一般服务器会对post发送的数据量进行限制
ServletRequest和ServletResponse
对于每一个Http请求,Servlet容器都会创建一个ServletRequest,和一个ServletResponse请求,并且传给service方法。
常用API
ServletRequest中:
//获取指定参数的值,常用来获取HTML表单指定参数的值 public String getParameter(String name)
ServletResponse中:
//通过getWriter方法获取PrintWriter对象,然后通过调用print/println向客户端发送数据。 PrintWriter writer = response.getWriter(); writer.print("发送内容");
在向客户端发送数据前需要告诉服务器编码类型,如果发送的是HTML标签,同样也需要告诉客户端,如下:
resp.setHeader("Content-Type","text/html;charset=utf-8");
Request保存作用域
类似于session的保存作用域,每一个请求和响应的过程中都有一个保存作用域,在响应完成前可以访问该保存作用域。响应前,在servlet中采用服务器内部转发,在另外一个servlet中同样可以访问该作用域。
Request中常用API
- void setAttribute(String key,Object value) ------- 以键值对的方式保存信息。
- Object getAttribute(String key) ------- 通过key来获取value
- void removeAttribute(String key) ----- 通过key来删除键值对
ServletContext
ServletContext表示Servlet应用程序,通过ServletContext可以访问应用范围的初始化参数和属性,即在一个应用程序范围内可以访问application保存作用域里的内容。
应用程序范围:服务器开启到服务器关闭。
application作用域:在应用程序范围内,所有请求都可以访问该作用域。
ServletContextd对象的获取: 调用ServletConfig中的getServletContext()方法,GenericServlet抽象类中实现了该方法。
ServletContext对象中常用API
- void setAttribute(String key,Object value) ------- 以键值对的方式保存信息。
- Object getAttribute(String key) ------- 通过key来获取value
- void removeAttribute(String key) ----- 通过key来删除键值对