• Servlet属性、监听者和会话


     没有servlet能单独存在。在当前的现代Web应用中,许多组件都是在一起协作共同完成一个目标。怎么让这些组件共享信息?如何隐藏信息?怎样让信息做到线程安全?

    1 属性和监听者

    1.1 初始化

    容器初始化一个servlet时,会为这个servlet建一个唯一的ServletConfig。容器从web.xml 配置文件中“读出”servlet初始化参数,并把这些参数交给ServletConfig。然后把ServletConfig传递给servlet的init()方法。

    一旦参数置于ServletConfig中,就不会再读了,除非重写部署了servlet。

    1.1.1 上下文初始化参数

    上下文初始化参数与servlet初始化参数很类似,只不过上下文参数对整个Web应用可用,而不只针对一个servlet。

    1. public class InitServlet extends HttpServlet {
    2. @Override
    3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    4. ServletConfig servletConfig = getServletConfig();
    5. String servletName = servletConfig.getInitParameter("servletName");
    6. ServletContext servletContext = getServletContext();
    7. String contextName = servletContext.getInitParameter("contextName");
    8. resp.setCharacterEncoding("gbk");
    9. PrintWriter writer = resp.getWriter();
    10. writer.println("servlet初始化参数:" + servletName);
    11. writer.println("上下文初始化参数:" + contextName);
    12. writer.close();
    13. }
    14. }
    1. <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    4. version="2.4">
    5. <servlet>
    6. <servlet-name>initServlet</servlet-name>
    7. <servlet-class>servlet.InitServlet</servlet-class>
    8. <init-param>
    9. <param-name>servletName</param-name>
    10. <param-value>initServlet</param-value>
    11. </init-param>
    12. </servlet>
    13. <context-param>
    14. <param-name>contextName</param-name>
    15. <param-value>day01</param-value>
    16. </context-param>
    17. <servlet-mapping>
    18. <servlet-name>initServlet</servlet-name>
    19. <url-pattern>/init</url-pattern>
    20. </servlet-mapping>
    21. </web-app>

    web.xml 

    1.2 监听者

    接口

    使用场景

    ServletContextAttributeListener

    监听Web应用上下文中是否增加、删除或替换了一个属性。

    HttpSessionListener

    监听会话的创建。

    ServletRequestListener

    用户请求监听。

    ServletRequestAttributeListener

    监听请求增加、删除或替换属性。

    HttpSessionBindingListener

    属性类对象在绑定到一个会话或从会话删除时触发给属性类对象。

    HttpSessionAttributeListener

    监听会话增加、删除或替换属性。

    ServletContextListener

    监听Web应用上下文创建或销毁。

    HttpSessionActivationListener

    监听会话迁移到另一个JVM。

    表 servlet常见的8种监听者

    1. public class MyAtt implements HttpSessionBindingListener {
    2. @Override
    3. public void valueBound(HttpSessionBindingEvent event) {
    4. System.out.println("myAtt 添加到:" + event.getSession());
    5. }
    6. @Override
    7. public void valueUnbound(HttpSessionBindingEvent event) {
    8. System.out.println("myAtt 移除");
    9. }
    10. }
    11. public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    12. @Override
    13. public void attributeAdded(HttpSessionBindingEvent event) {
    14. System.out.println("添加session属性:" + event.getName() + ",其值为:" + event.getValue());
    15. }
    16. @Override
    17. public void attributeRemoved(HttpSessionBindingEvent event) {
    18. System.out.println("删除session属性:" + event.getName() + ",其值为:" + event.getValue());
    19. }
    20. @Override
    21. public void attributeReplaced(HttpSessionBindingEvent event) {
    22. System.out.println("替换属性:" + event.getName() + ",其值为:" + event.getValue());
    23. }
    24. }
    25. public class MyHttpSessionListener implements HttpSessionListener {
    26. @Override
    27. public void sessionCreated(HttpSessionEvent event) {
    28. System.out.println("有个会话被创建了:" + event.getSession());
    29. }
    30. @Override
    31. public void sessionDestroyed(HttpSessionEvent event) {
    32. System.out.println("有个会话被销毁了:" + event.getSession());
    33. }
    34. }
    35. public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    36. @Override
    37. public void attributeAdded(ServletContextAttributeEvent event) {
    38. System.out.println("添加上下文属性:" + event.getName() + ",其值为:" + event.getValue());
    39. }
    40. @Override
    41. public void attributeRemoved(ServletContextAttributeEvent event) {
    42. System.out.println("删除上下文属性:" + event.getName() + ",其值为:" + event.getValue());
    43. }
    44. @Override
    45. public void attributeReplaced(ServletContextAttributeEvent event) {
    46. System.out.println("替换上下文属性:" + event.getName() + ",其值为:" + event.getValue());
    47. }
    48. }
    49. public class MyServletContextListener implements ServletContextListener {
    50. @Override
    51. public void contextInitialized(ServletContextEvent event) {
    52. System.out.println("上下文创建:" + event.getServletContext());
    53. }
    54. @Override
    55. public void contextDestroyed(ServletContextEvent event) {
    56. System.out.println("上下文销毁:" + event.getServletContext());
    57. }
    58. }
    59. public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
    60. @Override
    61. public void attributeAdded(ServletRequestAttributeEvent event) {
    62. System.out.println("添加请求属性:" + event.getName() + ",其值为:" + event.getValue());
    63. }
    64. @Override
    65. public void attributeRemoved(ServletRequestAttributeEvent event) {
    66. System.out.println("删除请求属性:" + event.getName() + ",其值为:" + event.getValue());
    67. }
    68. @Override
    69. public void attributeReplaced(ServletRequestAttributeEvent event) {
    70. System.out.println("替换请求属性:" + event.getName() + ",其值为:" + event.getValue());
    71. }
    72. }
    73. public class MyServletRequestListener implements ServletRequestListener {
    74. @Override
    75. public void requestDestroyed(ServletRequestEvent event) {
    76. System.out.println("请求被销毁:" + event.getServletRequest());
    77. }
    78. @Override
    79. public void requestInitialized(ServletRequestEvent event) {
    80. System.out.println("请求初始化:" + event.getServletRequest());
    81. }
    82. }

    监听者 

    1. public class ListenerServlet extends HttpServlet {
    2. @Override
    3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    4. req.setAttribute("reqAtt","hello req");
    5. req.getSession().setAttribute("sessionAtt", "hello session");
    6. req.getSession().setAttribute("binding",new MyAtt());
    7. getServletContext().setAttribute("contextAtt", "hello context");
    8. }
    9. }

     

    1. <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    4. version="2.4">
    5. <servlet>
    6. <servlet-name>listenerServlet</servlet-name>
    7. <servlet-class>servlet.ListenerServlet</servlet-class>
    8. </servlet>
    9. <servlet-mapping>
    10. <servlet-name>listenerServlet</servlet-name>
    11. <url-pattern>/listener</url-pattern>
    12. </servlet-mapping>
    13. <listener>
    14. <listener-class>listener.MyHttpSessionAttributeListener</listener-class>
    15. </listener>
    16. <listener>
    17. <listener-class>listener.MyHttpSessionListener</listener-class>
    18. </listener>
    19. <listener>
    20. <listener-class>listener.MyServletContextAttributeListener</listener-class>
    21. </listener>
    22. <listener>
    23. <listener-class>listener.MyServletContextListener</listener-class>
    24. </listener>
    25. <listener>
    26. <listener-class>listener.MyServletRequestAttributeListener</listener-class>
    27. </listener>
    28. <listener>
    29. <listener-class>listener.MyServletRequestListener</listener-class>
    30. </listener>
    31. </web-app>

    web.xml 

    2 会话管理

    Web服务器没有短期记忆。

    HttpSession对象可以保存跨同一个客户多个请求的会话状态,即与一个特定客户的整个会话期间,HttpSession会持久存储。对于会话期间客户做的所有请求,都可以用HttpSession存取。

    2.1 容器几乎做cookie的所有工作

    除了必须告诉容器创建或使用一个会话,其他工作,比如生成会话ID、创建新的cookie对象、把会话ID放到cookie中、把cookie设置为响应的一部分以及从请求中的cookie得到会话ID,将这个会话ID与一个现有会话匹配等工作都是由容器完成。

    HttpSession session = request.getSession(); // 在响应中发送一个会话cookie

    执行完上面后,容器会负责余下的事情,你什么也不用做。

    HttpSession session = request.getSession(); // 从请求得到会话id。

    执行完上面后,容器会负责余下的事情(找到与该ID匹配的会话,没有则创建一个新会话)。

    图 执行request.getSession()后的响应与请求

    当cookie被禁时,URL重写是一条后路:如果客户端不接受cookie,可以把URL重写作为一条后路。当然,在实际开发中,这种方法很少使用。

    2.2 删除会话

    删除会话有两种方式(不包括结束应用):

    1)设置超时时间,setMaxInactiveInterval() 指定对于这个会话客户请求的最大间隔时间(秒)。

    也可以在web.xml中配置,单位是分钟

          15

    2)结束会话,invalidate()

    2.3 会话迁移

    在部署分布式Web应用时,容器可能会负载均衡,取得客户的请求,把请求发送到多个JVM上。例如,每次客户请求时,有可能到达同一个servlet到不同实例。

    只有HttpSession对象(及其属性)会从一个VM移到另一个VM。

    每个VM中有一个ServletContext,每个VM上的每个servlet有一个ServletConfig。但是对于每个Web应用的一个给定会话ID,只有一个HttpSession对象,而无论应用分布在多少个VM上。

  • 相关阅读:
    凭什么软件测试入门就有一万+工资,为什么?我不相信。
    Vim实用技巧_0.vim - introduction
    [架构之路-246]:目标系统 - 设计方法 - 软件工程 - 需求工程- 需求开发:获取、分析、定义、验证
    【OpenCV-Python-课程学习(贾)】OpenCV3.3课程学习笔记:图像色彩空间的转换(cvtColor、)
    重构家用电器产业价值,S2B2C供应链系统模式助力企业拓展市场新空间
    AI数字人虚拟主播,跟传统主播相比有哪些优势,究竟谁更胜一筹?
    扫地机器人地图与用户终端的同步
    PHP 代码 清理 redis 消息问题
    关于TRPO推导中的一个疑问
    今天面了个腾讯拿38K出来的,让我见识到了基础的天花板
  • 原文地址:https://blog.csdn.net/qq_25308331/article/details/132679419