描述:
专门用于处理http请求的标准组件(JavaEE标准),并且它必须依赖于web容器来运行,因为它的整个生命周期都是由web容器来管理的。
Servlet是以单实例,多线程的方式来处理请求
运行流程:
当客户端的一个请求到来时,这个请求最先经过的就是web容器,因为容器决定将这个请求交由给哪一个Servlet组件处理。这是因为容器在启动的时候它会去初始化每一个web应用,并解析其中的web.xml文件,找到所有注册的servlet信息以及过滤器、监听器信息等等,通过url-pattern匹配原则,将客户端请求匹配到具体的servlet时,这时,容器会根据配置的class-name来创建一个servlet实例并初始化,容器还会创建相应的请求对象和响应对象(request,response),容器在调用service方法处理请求的时候,会将这两个参数传递进来,我们就可以直接拿来使用,因为请求对象中已经封装好了客户端提交的一切信息,所以,我们就可以从这个对象中获取客户端提交的内容。
Servlet的分类
1.DefualtServlet,它是专门用于处理静态资源(如:html,css,js,jpg...),当请求无法交给我们的servlet处理的时候,就会将这个请求交给DefaultServlet来处理,如果DefaultServlet也无法处理这个请求,那么就会抛出404异常。
2.JspServlet,它是专门用于处理动态JSP页面的,它也就是传说中的JSP引擎,它的职责就是负责将jsp文件转译成java源文件,再通过javac命令编译成字节码文件加载到jvm中执行。
生命周期
Servlet的创建到销毁整个过程都是由容器负责的。
核心的生命周期方法:
1) init方法,在Servlet创建的时候会去调用,用于初始化Servlet,只会执行一次
Servlet创建的时机有两种情况:
1.当第一次请求的时候,容器会负责创建一个实例(延迟创建)
2.在容器启动的时候,会创建一个Servlet的实例,需要在web.xml中配<load-on-startup>1</load-on-startup>,数值1代表初始化的优先顺序,数值越小,创建的优先级别就越高(预先创建)
2)service方法,它是专门用于处理核心请求的业务方法,也就是在这个方法中来处理客户端提交的信息,这个方法会被调用多次,这个方法有两个参数,HttpServletRequest和HttpServletResponse对象,表示请求对象和响应对象,这个两个参数都是由容器创建的
3)destroy方法,这个方法会在servlet准备销毁前执行,也是由容器来调用的,那么可以在这个方法中执行一些资源释放之类的操作,这个方法是在关闭容器,或者重启容器的时候会执行
处理请求所谓处理请求,就是将客户端提交的信息进行后台处理,来完成某一个功能需求,完成之后把结果再响应回客户端的一个过程。
由于请求信息都封装到HttpServletRequest对象当中,所以,只要从这个对象中就可以获取客户端提交的一切信息资源
request对象提供的丰富的API让我们来获取客户端提交的内容
当请求处理完之后,就可以反馈一些信息回客户端,那么这时就需要response对象来完成
response也提供了很多API方法来完成响应的操作
Servlet之间的通信
1.转发
在Servlet和Servlet之间通信,我们经常会用到转发,目的是将同一个请求对象和响应对象转发给下一个Servlet或者JSP组件,这种转发的操作是可以持续操作的,只要转发一直存在,那么这个请求对象和响应对象就会一直保留,直到某一个Servlet组件响应了客户端,这个两个对象就会消失。
在转发的过程当中,url的地址是不会发生改变的
请求作用域:在这个请求的过程当中,请求对象会保持一个数据空间,这个空间就是请求作用域,这个作用域的目的就是可以在同一个请求范围之内让多个Servlet组件共享的一块内存区域,直到这个请求消失,那么作用域也就随之消失
2.重定向
重定向和转发最大的区别在于,重定向首先会向客户端进行一个302的响应,然后让客户端重新请求服务器资源,由于发起了新的请求,所以它们不是之前的同一个请求对象和响应对象,这时请求作用域是无效的
在重定向的时候,url地址栏会发生改变,重新请求新的资源
Servlet的线程安全
在开发中尽量避免在servlet中定义实例变量,因为servlet是单实例多线程运行的,因此实例变量会被多个线程锁共享,容易产生线程安全问题。
JSP执行的原理、
当客户端请求某一个JSP页面的时候,web容器会将这个请求交给JspServlet来处理,JspServlet会通过JSP引擎(jsper.jar)将这个JSP页面转译成一个Servlet组件,同时会在这个Servlet组件中定义好9个内置对象。最后通过编译命令(javac)来编译成字节码文件,并加载到JVM中来执行
我们在JSP中编写的Java小脚本(<% %>),通过转译,就会被定义为service方法中的代码片段
在JSP中声明的变量(<%! %>),通过转译,最终会被定义为servlet的实例变量
注意:当第一次请求的时候,容器会先检查之前有没有转译过这个JSP,如果没有就执行转译和编译,否则就直接使用之前转译好的Servlet组件来运行,提高效率
会话跟踪、
HTTP本身是“无状态”协议,它不保存连接交互信息,一次响应完成之后即连接断开,下一次请求需要重新建立连接,服务器不记录上次连接的内容.因此如果判断两次连接是否是同一用户, 就需要使用会话跟踪技术来解决.常见的会话跟踪技术有如下几种:
1.Cookie
cookie是通过客户端浏览器的方式缓存来自服务端发送的一些信息数据,那么这种会话跟踪的方式是由客户端来维护的。
cookie的有效时间(单位:秒):
1)如果设置的过期时间为正数,浏览器就会把cookie保存到浏览器的对应的cookie文件中,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。
2)如果设置的过期时间为负数,浏览器就会把cookie保存到浏览器的内存中,关闭后cookie就会销毁。
3)如果设置的过期时间为0,表示让浏览器立即删除cookie。
4)如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就销毁
2.Session
Session是一种以服务端来维护会话的跟踪技术,也就是说,用户的状态是保存在服务器端,这一点和cookie是有区别的。当用户发起一个请求到达服务器的时候,服务器会为当前用户创建一个唯一的session对象。同时为这个session对象维护一个唯一的sessionID,这个sessionID是会发送回客户端保存的,这个sesisonID就是以cookie的机制写回客户端浏览器,而且只会保存在浏览器的内存当中,不会写入cookie文件
(注意:session的创建是在Servlet中当调用了request.getSession()的方法时候才会创建,getSession方法被调用的时候,首先会检查当前客户端之前有没有创建过session,如果有就直接拿来使用,如果没有,则创建一个新的session对象)
会话作用域:
在使用Session做会话跟踪的时候,我们通常都会iuyongdao会话作用域,这个作用域表示着session对象的一块内存空间,相当于服务端为每一个客户端都维护了一块内存空间,这个内存空间是每一个客户端独享的。会话作用域是在正哥浏览器范围内是有效的,意思就是,只要不关闭浏览器,sessionid会一直保存在cookie的内存中,每次请求都会将这个sessionid带回服务器端,保持着session对象的存在。
关于session对象的销毁,关闭浏览器,销毁的只是sessionid,但session对象是保存在服务器端的,当session对象没有了sessionid对应的时候,服务器就认为session对象是无效的,那么在一定时间内会去销毁这个session,销毁的操作是有服务器端决定的
session的默认的生存时间是30分钟,也就是在30分钟之内,客户端没有请求,没有将sessionid带回服务器,那么服务器就会在这个时间之后销毁session对象。
session的超时设置可以有两种方式
1)可任意通过web.xml设置全局的session超时时间<session-config>,所谓全局就是对所有的session对象统一进行超时设置
2)可以在servlet中通过session.setMaxInactiveInterval()方法来设置超时,这个方法是针对当前的session来设置,并不会影响其他的session对象
3.URL重写
由于sessionid是以cookie的机制保存在客户端,但是客户端是可以禁用cookie选项的,这就意味着,服务无法将sessionid保存在客户端的cookie中,那么这时我们就需要进行URL的重写
URL重写是通过response对象来完成的
response对象提供了两个方法进行URL的重写
1) encodeRediredctURL(),标识在重定向之前完成URL的重写
2)encodeURL(),当servlet写回HTML文本时,文本中有需要请求新的资源的URL,这时就是使用encodeURL方法进行重写
会话跟踪:
HTTP本身是“无状态”协议,它不保存连接交互信息,一次响应完成之后即连接断开,下一次请求需要重新建立连接,服务器不记录上次连接的内容.因此如果判断两次连接是否是同一用户, 就需要使用会话跟踪技术来解决.常见的会话跟踪技术有如下几种:
Servlet:
Servlet上下文,是web容器为每一个web应用维护的一个内存共享空间,也就是每一个web应用都有一个唯一的ServletContext对象,那么这个上下文对象就被当前web应用中的所有Servlet和JSP组件所共享,这个空间也叫做上下文作用域。
跟request和session一样,这个对象都提供了相应的setAttribute()方法和getAttribute()方法来操作这个作用域。这个作用域是在整个web应用范围之内有效的,任何一个Servlet和JSP都可以从这个作用域中取值和赋值,它会随着容器的启动而创建,随着容器的关闭或重启而销毁。
在JSP中Application,也就是ServletContext对象
获取ServletContext的几种方式:
1)可以通过ServletConfig对象中获取
2)可以通过request对象中获取
3)可以通过session对象中获取
监听器:
Servlet中的监听器主要是用于监听一些重要的事情发生,它可以在时间发生的前后做出一些相应的处理操作。
在servelt中,监听器主要分为请求监听、会话监听、上下文监听
请求监听器
1) ServletRequestListener,用于监听请求对象的创建和销毁
2) ServletRequestAttributeListener,用于监听请求作用域的操作,例如setAttribute操作,removeAttribut操作等
会话监听器
1) HttpSessionListener,用于监听会话对象的创建和销毁
2) HttpSessionAttrbuteListener,用于监听会话作用域的操作
上下文监听器
1) ServeltContextListener,用于监听上下文对象的创建和销毁(容器在启动的时候会为为一个web应用创建一个唯一的上下文对象ServletContext,那么这个上下文对象是可以被当前项目中的所有Servlet所共享)
2) ServeletContextAttributeListener,用于监听上下文作用域的操作