1.当多个客户端(一定数量)同时请求同一个Servlet的时候,容器可以同时处理。 正确√
2.当存在多个监听器的时候,其初始化顺序是按照部署描述符中定义的顺序来初始化监听器的。 正确√
3.下面哪些方法是可以做到Servlet线程安全?(共4种)
-
A.注意Servlet中属性的线程安全 √
-
B.注意Servlet中声明的变量的线程安全,尽量不要使用实例变量 √
-
C.尽量避免在Servlet中创建线程√
-
D.多个Servlet访问的外部对象需要加锁处理 √
4.下面关于Web应用组件启动顺序的说法错误的是?
-
B.Web应用组件启动过程中,过滤器的优先级高于Servlet ×
-
C.Web应用组件启动过程中,监听器的优先级高于过滤器 ×
-
D.Web应用组件启动过程中,监听器的优先级高于Servlet ×
5.下面哪项说法是错误的?
-
A.过滤器和监听器都是Web服务端应用组件 √
-
B.ServletRequestAttributeListener是属于EventListeners √
-
C.在部署描述符中,如果过滤器定义在监听器前,则容器会先初始化过滤器 ×
-
D.客户端的请求可以交由多个过滤器处理 √
6.下面说法正确的是?
-
A.ServletContext的属性是线程安全的 ×
-
B.其它选项都是正确的
-
C.HttpSession的属性是理论上线程安全 √
-
D.ServletRequest的属性不是线程安全 ×
2. 关于filter过滤器的使用小记
(1)使用步骤
① 第一次输入Servlet的访问地址url
② 浏览器端地址栏变化状态如下:
a. 回车键后:
b. 查看filter代码:
PS:→_→
得出结论:此处重定向的参数location,为相对路径(相对于访问的那个servlet的url地址);否则:
③ 查看eclipse控制台:
输出次数共计20次,且每次调用次数都不太一样,猜想一:它是随服务器的响应速度决定的;
得出结论:当我们通过浏览器端访问ServletA时,a. 首先调用ServletA所对应的Filter的doFilter()方法(PS:filter的init方法在项目部署在服务器时就已经完成了);
b. 当程序执行doFilter方法过程中,会调用res.sendRedirect()方法,而此时,sendRedirect()方法中的参数“有误”(有误:它的url地址涉及到同一个Filter的访问路径,那么它就会不停地调用该Filter的doFilter方法,直到服务器放弃该重定向。所以:就出现所谓"不定次数循环"!);
同时,关于这里重定向url的相对路径注意事项:它是相对于ServletA路径。而不是相对于该项目的路径,此处应值得注意一下
c. 查看经过过滤器后的重定向地址页面,它竟不是error.html!!为什么?
猜想二:该访问url被放弃掉了。进一步得出:当出现“网页走丢了”时,往往都是程序走进“循环”了,即:在url重定向方面出错了
d. 当我们把重定向location地址由
更改为:→_→
跳转好使了;
在含有filter情况下,访问servletA过程:①调用访问的ServletA的init()方法;②执行对应的filter中的doFilter()方法(PS:filter中的init()方法在项目部署在服务器上时就已经被调用);
(2) filter的过程图解:https://www.cnblogs.com/zyaizz/p/3554289.html
案例:
3.监听器
注册:相当于把监听器安装在某个监听场所;
通知:监听场所传递出的信息给监听器;(监听器把相应的信息发送给终端)
4. listener,filter,servlet的比较:
(1)启动顺序:
排序如下:
listener -> filter -> servlet (PS:仅仅是listener的ListenerContext对象的 init()方法 调用是在filter之前;listener的其它对象的init()方法在filter之后,在servlet之前;详见下图:request对象的init 仅仅在servlet的init 的前一步)
其中listener和filter是随项目在服务器上的部署而启动的;
①第一次登录后(http://127.0.0.1:8080/cloudy/UserServlet?userName=123&userPassword=123)
得出结论:a. 当用户向服务端发送第一次请求时,servlet容器 首先调用了listenerRequest对象的 init() 方法;b. 紧接着调用相应的servlet对象的 init()方法(PS:filter的init方法在项目部署时就已经调用了,listenerContext更是在filter之前。);c.之后依次调用servlet中的方法,执行完servlet后,即:响应的开始;d. 进入filter的doFilter方法中的chain.doFilter方法后的code;e. 再然后,执行listenerRequest的destroy()方法,请求结束;
②第二次登录:
第二次登录,少了servlet的init方法,多了相应的servlet操作code。注意listenerRequest的方法没有变化。