tomcat服务器,通过Java的反射机制来自动调用servlet的init、service过程中,利用了反射机制,在创建servlet对象之前,先在以map为数据结构的cache缓存池中,判断是否已经存在servlet对象: Show
-------存在直接使用缓存池的servlet对象,不存在才创建一个servlet对象,然后添加进servlet的缓存池【单例的原理】 --------然后判断是利用map的key 是否相同,其中key就是servlet 的全限定名称的别名(String),value是servlet的全限定名称。 二、servlet的请求流程:★ 流程:①发送请求 -》②域名解析 -》③tomcat 服务器解析请求【上下文、资源名】 -》④上下文的匹配【server.xml文件的上下文元素的path,匹配上之后,读取该元素的docBase属性值(当前访问的Web项目的根路径)】 -》⑤资源名的匹配【Context的属性docBase值--->找到当前项目的根路径,读取项目根路径下的web.xml文件,在web.xml文件中匹配规则元素】,找不到(404)找到了就获取到Servlet类的全限定名 -》⑥使用servlet对象【判断Servlet缓存池是否已经存在(全限定名为**)servlet对象】,不存在(第一次请求),创建(全限定名为**) servlet对象并存储到缓存池,存在,直接使用该servlet对象 Servlet没有main方法,无法独立运行,他的运行完全由Servlet引擎来控制和调度,所谓生命周期就是servlet容器何时创建servlet实例,何时调用其方法进行请求的处理,何时并销毁其实例的整个过程。
三个servlet生命周期方法1.init方法,在Servlet实例创建之后执行(证明该Servlet有实例创建了)
2.service方法,每次有请求到达某个Servlet方法时执行,用来处理请求(证明该Servlet进行服务了)
3.destory方法,Servlet实施销毁时执行(证明该Servlet的实例被销毁了)
Servlet的生命周期,简单描述分为四步,servlet类加载->实例化->服务->销毁
四.HttpServletRequest对象 HttpServletRequest对象:主要作用是用来接收客户端发送的请求信息,例如:请求的参数,发送的头消息等都属于客户端发送的消息,service()方法中形参接收的是HttpServiceReques接口的实例化对象,表示该对象主要应用在HTTP协议上,该对象是由Tomcat封装好传递过来的。 HttpServletRequest是ServletRequest的子接口,ServletRequest只有一个子接口,就是HttpServletRequest,既然只有一个子接口那么为什么不合并在一起呢? 从长远来讲,现在主要使用的是HTTP协议,但是以后可能会出现更多的协议,如果以后想要支持这种新的协议,只需要继承ServletRequest接口就行了。 在HttpServletRequest接口中,定义的方法有很多,但是都是围绕客户端参数的。但是怎么拿到对象呢?不需要,直接在Servlet方法中由容器传入进来,而我们需要做的就是取出对象中的数据,进行分析处理。 4.1 接收方法方法实现:
获取请求参数的两种方法:一种是获取请求参数,一种是获取对应参数的所有值,遍历进行输出
最后输出想要得到的对应参数 4.2 请求乱码问题 由于现在的request属于接收客户端的参数,所以必然有其默认的语言编码,主要是由于在解析过程中默认使用的编码方式为ISO-8859-1(此编码不支持中文)所以解析时一定会出现乱码,要想解决这种乱码问题,需要设置request中的编码方式,告诉服务器以何种方式进行解析数据,或者在接收到乱码数据之后,再通过相应的编码格式还原。 4.3 请求转发 请求转发是一种服务器行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保存,地址栏中的URL地址不会改变,得到响应后,服务器端将再次响应发送给客户端,从始至终都只有一个请求发出,实现方式如下,达到多个资源协同响应的效果。
通俗易懂来说就是请求转发是可以做跳转的,跳转之后还可以将原来的对象赋给你 查看代码可知图片中写了两个请求跳转的命令,一个跳转到servlet04,一个跳转到login.jsp,在浏览器中访问servlet03文件,浏览器会首先访问servlet03文件,之后运行到请求转发命令时,再次跳转页面到servlet04或login.jsp页面,**但是浏览器显示的url并没有改变,并且后台会将servlet03的参数同样传给跳转之后的页面,**显示效果如下 1.跳转到servlet04界面访问的url为servlet03 但是后台返回了03与04页面的响应,所以存在了请求转发 2.跳转到login.jsp界面servlet03响应结果 url显示是servlet03文件路径但是页面跳转到login.jsp 所以即实现了请求跳转 4.4 request 域对象通过该对象可以在一个请求中传递数据,作用范围;在一次请求中有效,即服务器跳转有效。 即在Java中我们不能传输对象及数据,但是利用域对象可以实现参数,对象及其数据的传输,但是只在请求转发中实现。 在servlet05中,定义对象及其数据 访问servlet05显示Servlet05 表示访问成功: 之后创建一个servlet06实现servlet05跳转及其对象带入: 最后实现输出. 注:当访问一串文件使用请求转发时,例如访问servlet04,05,06,07,08只要一直使用请求转发功能,里面所有的数据都会共享,即作用域,但是一旦直接访问路径,则作用域就会失效。 五.HttpServletResponse对象 Web服务器收到客户端的http请求时,会针对每一次请求,分别创建一个用于代表请求的resquest对象和代表响应的response对象。 resquest和response对象分别代表请求和响应,获取客户端数据,通过resquest对象,向客户端输出数据,需要通过response对象。 HttpServletResponse的主要功能用于服务器对于客户端的请求进行响应,将web服务器处理后的结果返回给客户端,service()方法中形参接收的是HttpServletResponse接口的实例化对象,这个对象中封禁了向客户端发送数据,发送响应头,发送响应状态码的方法。 5.1 响应数据 接收到客户端请求后,可以通过HttpServletResponse对象直接进行响应,响应时需要获取输出流。 有两种形式: getWrite()获取字符流(只能响应字符) getOutStream()获取字节流(能响应一切数据) 注意:两者不能同时使用 注:两种输出流方法同时使用,会优先由前一个方法调用reponse对象,因为前面的方法已经调用了response对象,所以会报错,后面的方法无调用对象。 5.2响应乱码问题 在响应中,如果我们响应的内容中含有中文,则有可能出现乱码,这时因为服务器响应的数据也会经过网络传输,服务器端有一种编码方式,但是客户端也存在一种编码方式,当两端使用的编码方式不同时则会出现乱码。 getWrite()的字符乱码 对于getWrite()获取到的字符流,响应中文必定出乱码,由于服务器端在进行编码是默认会使用ISO-8859-1格式的编码,该编码格式不支持中文。 要解决该种乱码问题只能在服务器端告知服务器使用一种能够支持中文的编码格式,比如我们常用的"UTF-8"。 response.setCharacterEncoding("UTF-8") 此时还只完成了一半的工作,要保证数据正确显示,还需要指定客户端的解码方式。 response.setHeader("content-type" , "test/html ; charset = UTF-8"); 两端指定编码后,乱码就解决了,一句话:保证发送端和接收端的编码一致 实验: 一.字符流响应数据: 显示乱码 二.字节流响应数据 显示乱码 解决方法: 1.设置服务端编码格式: 再次查看界面显示 显示Servlet02显示界面与03一致但还是乱码 原因:由于客户端与服务端解码方式不一致会导致,乱码,所以只设置了服务端但是没有设置客户端编码格式,所以依然会导致乱码。 再次设施客户端编码格式: 首先在客户端将我们输入的字体转换为html类型,使客户端可以查看,之后再该变其编码格式,使客户端与服务端一致,再次运行显示成功。 同时设置客户端与服务端的编码: getOutStream()字节乱码 对于getOutStream()方式获取到的字节流,响应中文时,由于本身就是传输的字节,所以此时可能出现乱码,也可能正确显示。当服务器端给的字节恰好和客户端使用的编码方式一致时则文本正确显示,否则出现乱码。无论如何我们都应该准确掌握服务器和客户端使用的是哪种编码格式,以确保数据正确显示。 制定客户端和服务端使用的编码方式一致。 解决方法同字符流乱码解决方式一致 代码中同时设置服务端与客户端编码格式 成功显示文本 总结
5.3 重定向 重定向是一种由服务端引导,客户端的行为,客户端发送一个请求,被服务端接收处理之后,服务端会进行响应,在响应的同时,服务端会给客户端一个新的地址(下次请求的地址 response.sendRedirect(url);)当客户端接收到响应后,会立刻马上,自动根据服务器给的新地址发送第二个请求,服务器接收到请求并作出响应,重定向完成。 从描述中可以看出重定向当中有两个请求存在,并且属于客户端行为。
实现重定向通过观察浏览器我们发现第一次请求获取的响应码为302,并且含有一个location头信息,并且地址栏最终看到的地址是和第一次不同的,地址栏已经发生了变化。 如图所示,首先访问Servlet04之后服务端会对客户端发送一个重定向的url,客户端收到之后会立刻再次向服务端发送请求,之后定向到Servlet05,而此时就存在两个请求,上图所示,即302重定向到了05 重定向时传参如果给04传一个参数,查看05是否能够收到参数 首先在04,05分别创建一个对象接收参数: 之后向04传递一个参数,查看重定向之后05是否也会接收到这个参数 如图显示,05并没有接收到这个参数的数据,但是如果我们单独给05传参时就可以接收到参数的数据,这是因为我们实现了两次请求,创建了两个resquest对象,所以是无法实现请求转发的,而跳转过后的页面也就无法收到前一个请求的数据了。 5.4请求转发与重定向的区别两者都可以进行跳转,根据需求选取即可。
六.Cookie对象 Cookie是浏览器提供的一种技术,通过服务器的程序能将一些只须保存在客户端,或者在客户端进行处理的数据,放在本地的计算机上,不需要网络连接,因而提高网页处理的效率,并且能够减少服务器的负载,但是由于Cookie是服务器端保存在客户端的信息,所以其安全性也是很差的。例如常见的记住密码就可以通过Cookie来实现。 有一个专门操作Cookie的类javax.servlet.http.Cookie,随着服务器的响应发送给客户端,保存在浏览器,当下次访问时再将Cookie带回服务器。 Cookie格式:键值对用"="链接,多个键值对利用":"隔开 6.1Cookie对象的创建和发送 通过new Cookie("key","value");来创建一个Cookie对象,要想Cookie随响应发送到客户端。需要先添加到response对象中,response.addCookie(cookie);此时该cookie对象随着响应发送到了客户端上,在浏览器上也可以看见
F12查看 Cookie对象的发送: f12进行查看 6.2 Cookie的获取 在服务器端只提供了一个getCookie()的方法用来获取客户端回传的所有Cookie组成的一个数组,如果需要获取单个cookie则需要通过遍历,getName()获取Cookie的名称,getValue()获取Cookie的值。 通俗易懂就是,首先查看cookie文件是否为空,不为空之后创建一个数组来遍历cookie的name与value。的到cookie文件内容。 首先查看到之前的cookie还在,说明cookie是浏览器存放的一个文件,不会随着浏览器哦或者网页的关闭或重启而改变或消失,是本地的文件,其次查看到这次访问的cookie数据 服务端也通过遍历查看到cookie文件的内容。 即获取cookie文件内容。 6.3 设置Cookie到期时间 除了Cookie的名称和内容外,我们还需要关心一个信息,到期时间,到期时间用来指定该cookie何时失效,默认当前浏览器关闭即失效,我们也可以手动设定cookie到期时间(通过到期时间计算),通过setMaxAge(int time)方法设定cookie最大有效时间,以秒为单位。 到期时间的取值负整数 若为负数,表示不存储该cookie. cookie的maxAge属性的默认值为-1,表示只在浏览器内存中存活,一 旦关闭浏览器窗口,那么cookie就会消失。 正整数 若大于0的整数,表示存储的秒数 表示cookie对象可存活指定的秒数,当生命大于0时,浏览器会把Cookie保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie也会存活响应的时间。 零 若为零,则删除此cookie cookie生命等于0是一个特殊的值,它表示cookie被作废!也就是说,如果原来浏览器已经保存了这个Cookie,那么可以通过Cookie的setMaxAge(0)来删除这个Cookie。无论是在浏览器内存中,还是在客户端硬盘上都会删除这个Cookie. 注:到期时间是指当前时间加有效时间,当到期时间为-1时,即关闭时,到期时间为当前时间-1,所以当到期时间为-1时,浏览器关闭时就会删除此cookie。 设置cookie到期时间: 显示如下:zahngsan与lisi显示成功,但是wangwu已经被删除,关闭浏览器之后显示张三也被删除 6.4 Cookie注意点1.Cookie保存在当前浏览器中 在一般的站点中常常有记住用户名这样的操作,该操作只是将信息保存在本机上,换电脑之后这些信息就无效了,而且cookie还不能跨浏览器。 2.Cookie存中文问题 Cookie中不能中文,如果有中文则通过URLEncoder.encode()来进行编码,获取时则通过URLDecoder.decoder()来进行编码。 不能存放中文 浏览器显示报错 1上面进行加密,后面进行解密 将中文加密之后存入浏览器,使其可以存储,之后返回服务器时解密得到cookie解密之后的中文。 访问之后得到加密后的cookie 再次访问,查看服务器端 得到中文的cookie 3.同名Cookie问题 如果服务器端发送重复的Cookie那么会覆盖掉原来的Cookie。 之后访问域名发现,value已被覆盖成zhangsan 4.浏览器存放Cookie的数量 不同的浏览器对Cookie也是有限定的,Cookie的存储是有上限的,Cookie是存储在客户端(浏览器)的,而且一般是由服务器端创建和设定的,后期结合Session来实现会话跟踪。 6.5 Cookie的路径
实现 当访问cook05时只能得到cookie1和2,因为1的cookie任意文件访问都可以得到,而2是因为只要是ser04项目中的文件都可以访问到,而4指定了sc04/cook02目录,所以只有访问此目录时才能得到cookie,而只有访问sc03项目时可以得到3 七.HttpSession对象(会话对象) HttpSession对象是javax.servlet.http.HttpSession的实例,该接口不像HttpServletRequest或HttpServletResponse还存在一个父接口,该接口只是一个纯粹的接口。这因为session本身就属于HTTP协议的范畴。 对于服务而言,每一个连接到它的客户端都是一个session,servlet容器使用此接口创建HTTP客户端的HTTP服务器之间的会话,会话将保留指定的时间段,跨多个连接或者来自用户的页面请求,一个会话通常对应于一个用户,该用户可能多次访问一个站点。可以通过此接口查看和操作有关某个会话的信息,比如会话标识符,创建时间和最后一次访问时间,在整个session中,最重要的就是属性的操作。 session无论客户端还是服务器端都可以感知到,若重新打开一个新的浏览器,则无法取得之前设置的session,因为每一个session只保存在当前的浏览器中,并在响应的页面取得。 Session的作用就是为了标识一次会话,或者说确认一个用户;并且在一次会话(一个用户的多次请求)期间共享数据。我们可以通过request.getSession()的方法,来获取当前会话的session对象。 7.1 Session常用方法如图session对象的常用方法:
运行时服务器端显示: 第一个箭头指向第一次访问,从上向下分别为
说明:session在你访问此界面时创建,即会话开始,在你关闭浏览器之前session会一直存在,会话也一样,会话中有很多请求,但是请求只能存在一次,但是其中会话会一直存在,类似于,你与老师谈话,会话是你与老师谈话这一段时间,但是请求只是老师与你之间的一个问题。 7.2 标识符 JSESSIONIDSession既然是为了标识一次会话,那么此次会话就应该有一个唯一的标识,这个标志就是sessionid。 每当一次请求到达服务器,如果开启了会话(访问了session),服务器第一步会查看是否从客户端回传一个名为JSESSIONID的cookie,如果没有则认为这是一次新的会话,会创建一个新的session对象,并用唯一的sessionid为此次会话做一个标识,如果有JESSIONID这个cookie回传,服务器则会根据JESSIONID这个值去查看是否含有id为JESSION值的session对象,如果没有则认为是一个新的会话,返回该session对象,数据达到共享。 这里提到一个叫做JESSIONID的cookie,这是一个比较特使的cookie,当用户请求到达服务器时,如果访问了sesion,则服务器会创建一个名为JESSIONID,值为获取到的session(无论时获取到的还是新创建的)sessionid的cookie对象,并添加到response对象中,响应给客户端,有效时间为关闭浏览器。 所以Session的底层依赖Cookie来实现。 JSESSIONID的cookie 7.3 Session域对象 Session用来表示一次会话中,在一次会话中数据是可以共享的,这时session作为域对象存在,可以通过setAttribute(name,value);方法向域对象中添加数据,通过getAttribute(name)从域对象中获取数据,通过removeAttribute(name)从域对象中移除数据。 如图所示,session域对象常见用法 数据存储在session域对象中,当session对象不存在了,或者时两个不同的session对象时,数据也就不能共享了,这就不得不谈到session的生命周期了。 而session域对象与request域对象的不同之处在于: session域对象存在于整个会话存在期间,但是request域对象只存在于一次请求之间 所以对于重定向与请求转发,session都会存在,但是request只在请求转发中存在,在重定向中因为客户端进行了两次访问,所以不会存在第二次中。 如图上方为请求转发,此时客户端访问jsp界面,即uname,upwd与name都会显示 但是如果此时将请求类型转为重定向,此时name对象就无法显示,因为nae对象为request域对象。 此时request对象由于只存在于一次请求中所以无法取到它的值。 5.4 Session域对象的销毁1.默认到期时间 当客户端第一次请求servlet并且操作session时,session对象生成,Tomcat中session默认的存活时间为30min,即你不操作界面的时间,一旦有操作,session会重新计时。 那么session的默认时间可以修改吗?答案是肯定的 可以在 Tomcat中的conf目录下的web.xml文件中进行修改 例如:当你上个厕所回来网站依旧连接session,但是当你睡了个午觉回来,网站显示需要重新登录,即代表此时session失效了,需要重新登录。 2..自己设定到期时间 当然除了以上的修改方式外,我们也可以在程序中自己设定session的生命周期,通过session.setMaxinactiveInterval(int)来设定session的最大不活动时间,单位为秒 当然我们也可以通过getMaxinactiveIntervcal()的方法来查看当前的session对象的最大不活动时间。 3.立刻失效即每次查看JSESSIUONID对象时显示的数值都不一样 4.关闭浏览器 从前面的JESSIONID可以知道,session底层依赖于cookie实现,并且该cookie的有效时间为关闭浏览器,从而session在浏览器关闭时相当于失效了(因为没有相应的JSESSION再与之对应) |