大数据正式22

大数据正式22

监听器

  • 概述
    • Listener--监听器
    • Servlet技术中的三大组件之一【Servlet、Filter、Listener】
    • 简单、应用少
    • 监听器可以用来监听web应用执行过程中的相关的事件,来进行对应的处理
  • 应用
    1. 写一个类实现监听器接口
    2. web中配置
  • 监听三大作用域创建和监听器

    1. ServletContextListener

      • 生命周期:web部署到下线
      • 作用范围:整个web应用
      • 主要功能:整个web应用中共享数据
      • 例子

        package com.peng.listener;
        
        import javax.servlet.ServletContextEvent;
        import javax.servlet.ServletContextListener;
        
        public class MyServletContextListener implements ServletContextListener {
        
            public void contextDestroyed(ServletContextEvent arg0) {
                System.out.println("context Destory");
            }
        
            public void contextInitialized(ServletContextEvent arg0) {
                System.out.println("context Init");
        
            }
        
        }
        

        <!-- 监听器的配置 -->
        <listener>
            <listener-class>com.peng.listener.MyServletContextListener</listener-class>
        </listener>
        
    2. HttpSessionListener

      • 生命周期:第一次调用request.getSession()
      • 作用范围:整个web应用的额会话周期
      • 主要功能:整个会话的生命周期共享数据

        package com.peng.listener;
        
        import javax.servlet.http.HttpSessionEvent;
        import javax.servlet.http.HttpSessionListener;
        
        public class MySessionListener implements HttpSessionListener {
        
            public void sessionCreated(HttpSessionEvent arg0) {
                System.out.println("session create!!!");
            }
        
            public void sessionDestroyed(HttpSessionEvent arg0) {
                System.out.println("session destory!!!");
        
            }
        
        }
        

        <!-- 监听器的配置 -->
        <listener>
            <listener-class>com.peng.listener.MySessionListener</listener-class>
        </listener>
        
    3. ServletRequestListener

      • 生命周期:一次请求和一次响应的过程中
      • 作用范围:一次请求和一次响应的过程中
      • 主要功能:一次请求和一次响应的过程中共享数据

        package com.peng.listener;
        
        import javax.servlet.ServletRequestEvent;
        import javax.servlet.ServletRequestListener;
        
        public class MyRequestListener implements ServletRequestListener {
        
            public void requestDestroyed(ServletRequestEvent arg0) {
                System.out.println("destory ServletRequestListener");
            }
        
            public void requestInitialized(ServletRequestEvent arg0) {
                System.out.println("init ServletRequestListener");
            }
        
        }
        

        <!-- 监听器的配置 -->
        <listener>
            <listener-class>com.peng.listener.MyRequestListener</listener-class>
        </listener>
        
    4. ServletContextAttributeListener

      package com.peng.listener;
      
      import javax.servlet.ServletContextAttributeEvent;
      import javax.servlet.ServletContextAttributeListener;
      
      public class MyServletContextListener implements
              ServletContextAttributeListener {
      
          public void attributeAdded(ServletContextAttributeEvent arg0) {
      
          }
      
          public void attributeRemoved(ServletContextAttributeEvent arg0) {
      
          }
      
          public void attributeReplaced(ServletContextAttributeEvent arg0) {
              // getValue为旧值
              // 获取新值 arg0.getServletContext().getAttribute(arg0.getName());
          }
      }
      
    5. HttpSessionAttributeListener

      package com.peng.listener;
      
      import javax.servlet.http.HttpSessionAttributeListener;
      import javax.servlet.http.HttpSessionBindingEvent;
      import javax.servlet.http.HttpSessionEvent;
      import javax.servlet.http.HttpSessionListener;
      
      public class MySessionAttributeListener implements HttpSessionAttributeListener {
      
          public void attributeAdded(HttpSessionBindingEvent arg0) {
      
          }
      
          public void attributeRemoved(HttpSessionBindingEvent arg0) {
      
          }
      
          public void attributeReplaced(HttpSessionBindingEvent arg0) {
              // TODO Auto-generated method stub
      
          }
      }
      
    6. ServletRequestAttributeListener

      package com.peng.listener;
      
      import javax.servlet.ServletRequestAttributeEvent;
      import javax.servlet.ServletRequestAttributeListener;
      
      public class MyRequestSAttributeListener implements
              ServletRequestAttributeListener {
      
          public void attributeAdded(ServletRequestAttributeEvent arg0) {
      
          }
      
          public void attributeRemoved(ServletRequestAttributeEvent arg0) {
      
          }
      
          public void attributeReplaced(ServletRequestAttributeEvent arg0) {
              // TODO Auto-generated method stub
      
          }
      }
      
    7. 使javabean自己感知在session域中的变化HttpSessionBindingListener(加入,移除)

      • 注:javabean实现这个接口,重写方法;web.xml中无须配置

        package compeng.javabean;
        
        import java.io.Serializable;
        
        import javax.servlet.http.HttpSessionBindingEvent;
        import javax.servlet.http.HttpSessionBindingListener;
        
        public class PersonBinding implements Serializable, HttpSessionBindingListener {
            private String name;
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public void valueBound(HttpSessionBindingEvent arg0) {
                // 加入
            }
        
            public void valueUnbound(HttpSessionBindingEvent arg0) {
                // 移出
            }
        
        }
        
    8. 使javabean自己感知在session域中的变化HttpSessionActivationListener(钝化,活化)

      • 注:javabean实现这个接口,重写方法;web.xml中无须配置
      • 注:javabean记得实现序列化接口
      • 活化回来时,对象不是同一个,只是携带的信息一样而已

        package compeng.javabean;
        
        import java.io.Serializable;
        
        import javax.servlet.http.HttpSessionActivationListener;
        import javax.servlet.http.HttpSessionBindingEvent;
        import javax.servlet.http.HttpSessionBindingListener;
        import javax.servlet.http.HttpSessionEvent;
        
        class PersonBinding implements Serializable, HttpSessionActivationListener {
            private String name;
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public void sessionDidActivate(HttpSessionEvent arg0) {
                // 序列化
        
            }
        
            public void sessionWillPassivate(HttpSessionEvent arg0) {
                // 反序列化
        
            }
        
        }
        

钝化和活化

  • 钝化
    • 在服务器正常关闭时,仍然存活的session会被钝化到work目录下
  • 活化
    • 在服务器正常开启时,将work目录下session.ser文件重写加载到服务器

EasyMall监听器的使用

  • EasyMall应用开启时设置项目路径到“app”变量中
  • EasyMall应用关闭时销毁“app”变量
  • 例子

    package com.easymall.listener;
    
    import javax.servlet.ServletContextEvent;
    
    public class ServletContextListener implements
            javax.servlet.ServletContextListener {
    
        public void contextDestroyed(ServletContextEvent arg0) {
            // 将项目路径移除
            arg0.getServletContext().removeAttribute("app");
    
        }
    
        public void contextInitialized(ServletContextEvent arg0) {
            // 将项目的路径存到app这个变量中
            arg0.getServletContext().setAttribute("app",
                    arg0.getServletContext().getContextPath());
        }
    
    }
    

文件上传

  • 步骤
    1. 带有文件上传的表单
      1. 必须有name
      2. 必须为post方式
      3. enctype的参数配置:multipart/form-data
    2. 在servlet写相应的逻辑【麻烦的逻辑】
      1. 获取流
      2. 变成字符串
      3. 切分字符串根据头信息
      4. 获取想要的文件
      5. enctype的参数配置:multipart/form-data
    3. 在servlet写相应的逻辑【简单的方式】
      1. Commaons-fileupload.jar包;commans-io.jar包
      2. 过程
        1. 创建文件上传工厂DiskFileItemFactory【内存缓冲区大小;文件临时存放目录】【文件全部传入才能做处理:放内存中--速度快但是占资源;放文件--速度慢,但是文件大小可以基本不受限制】【超过内存缓冲区,就执行文件临时存放目录】
        2. 创建文件上传的核心类ServletFileUpload
          1. isMultipartCotent(HttpServletRequest req)//判断当前上传的表单是否是multipart/form-data
          2. List parseRequest(HttpServletRequest req)//将请求头解析成文件的列表
          3. setFileSizeMax(long size)//控制文件上传的大小(Byte)
          4. setSizeMax(long size)//控制总的文件上传的最大值
        3. FileItem:文件上传项目--遍历item分别做处理
          1. isFormFiled判断当前FileItem是不是一个普通字段项----返回false为文件上传项
            1. 普通字段项
              1. getFieldName//获取字段项的名称
              2. getString//字段项的值
            2. 文件上传项
              1. getName//获取文件的名称
              2. getInputStream//获取文件的输入流
        4. 如果是文件,将获取到FileItem的输入流写入到文件的输出流中
      3. 遇到的问题
        • 文件名乱码(文件名称是中文名时)
          • 上传文件核心类的设置编码:setHeaderEncoding(encode)
        • 文件内容的乱码
          • response.setHeaderEncoding("utf-8")解决不了乱码
          • FileItem.getString(encode)
        • 临时文件未删除
          • FileItem.delete(记得该关的流关掉,要不删不了文件)
        • IE浏览器上传
          • Item.getName获取到的文件是全路径名(例如:C://a/b/c.txt)
          • 问题解决--只获取文件名
        • 文件上传保存的位置问题
          • 为了安全--文件保存的位置一定不能让外界直接访问
            1. Web-Inf下
            2. 本地文件的位置外界无法访问到
        • 文件重复--同名文件的覆盖
          • 尽量让文件名不要重复UUID(参考:时间+CPU时钟+。。。)
          • UUID.randomUUID().toString
        • 上传目录下文件过多:访问缓慢、甚至无法访问
          • 分目录存放
          • Integer.toHexString(int)+ 不够八位补0【HashCode不一定是唯一的】
          • 哈希特点:散列(相同二进制得到的数据相同)
          • 例:a/1/b/3/1/1/4/b/1bacbaaa.png
          • 总共产生的文件夹168
      4. 文件上传进度
        • ServletFileUpload.setProgressListener(ProgressListener pro);

简单例子

  • index.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    </head>
    <body bgcolor="#00ff00" text="#ffffff">${requestScope.message}
    </body>
    </html>
    
  • fileUp.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <title>文件上传</title>
    </head>
    <body bgcolor="#ff00ff" text="#00ffff">
        <center>
            <h1>name:</h1>
            <input type="text" name="name" />
            <h1>请选择文件:</h1>
            <form action="FileUpServlet" method="post"
                enctype="multipart/form-data">
                <input type="file" name="file" /> <input type="submit" value="上传文件" />
            </form>
        </center>
    </body>
    </html>
    
  • FileUpServlet

    package com.peng.ser;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    
    public class FileUpServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            this.doPost(request, response);
        }
    
        /* 上传文件逻辑 */
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
            String savePath = this.getServletContext().getRealPath(
                    "/WEB-INF/upload");
            File file = new File(savePath);
            // 判断上传文件的保存目录是否存在
            if (!file.exists() && !file.isDirectory()) {
                System.out.println(savePath + "目录不存在,需要创建");
                // 创建目录
                file.mkdir();
            }
            // 消息提示
            String message = "";
            try {
                // 使用Apache文件上传组件处理文件上传步骤:
                // 1、创建一个DiskFileItemFactory工厂
                DiskFileItemFactory factory = new DiskFileItemFactory();
                // 2、创建一个文件上传解析器
                ServletFileUpload upload = new ServletFileUpload(factory);
                // 解决上传文件名的中文乱码
                upload.setHeaderEncoding("UTF-8");
                // 设置文件的大小
                upload.setFileSizeMax(2 * 1024 * 102);// 设置单个文件的最大值
                upload.setSizeMax(50 * 1024 * 1024);// 设置总的文件的总的大小
                // 3、判断提交上来的数据是否是上传表单的数据
                if (!ServletFileUpload.isMultipartContent(request)) {
                    // 按照传统方式获取数据
                    return;
                }
                // 4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
                List<FileItem> list = upload.parseRequest(request);
                for (FileItem item : list) {
                    // 如果fileitem中封装的是普通输入项的数据
                    if (item.isFormField()) {
                        String name = item.getFieldName();
                        // 解决普通输入项的数据的中文乱码问题
                        String value = item.getString("UTF-8");
                        // value = new String(value.getBytes("iso8859-1"),"UTF-8");
                        System.out.println(name + "=" + value);
                    } else {// 如果fileitem中封装的是上传文件
                            // 得到上传的文件名称,
                        String filename = item.getName();
                        System.out.println(filename);
                        if (filename == null || filename.trim().equals("")) {
                            continue;
                        }
                        // 注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:
                        // c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
                        // 处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                        filename = filename
                                .substring(filename.lastIndexOf("\\") + 1);
                        // 获取文件名的UUID
                        String uuid_fileName = UUID.randomUUID().toString() + "_"
                                + filename;
                        // 哈希目录--利用文件的名称生成8层文件夹
                        String hashCod_8 = Integer.toHexString(uuid_fileName
                                .hashCode());
                        while (hashCod_8.length() < 8) {
                            hashCod_8 = "0" + hashCod_8;
                        }
                        for (int i = 0; i < hashCod_8.length(); i++) {
                            savePath += "\\" + hashCod_8.charAt(i);
                        }
                        File dir = new File(savePath);
                        dir.mkdirs();
                        // 获取item中的上传文件的输入流
                        InputStream in = item.getInputStream();
                        // 创建一个文件输出流
                        FileOutputStream out = new FileOutputStream(savePath + "\\"
                                + uuid_fileName);
                        // 创建一个缓冲区
                        byte buffer[] = new byte[1024];
                        // 判断输入流中的数据是否已经读完的标识
                        int len = 0;
                        // 循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                        while ((len = in.read(buffer)) != -1) {
                            // 使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\"
                            // + filename)当中
                            out.write(buffer, 0, len);
                        }
                        // 关闭输入流
                        in.close();
                        // 关闭输出流
                        out.close();
                        // 删除处理文件上传时生成的临时文件
                        item.delete();
                        message = "文件上传成功!";
                    }
                }
            } catch (Exception e) {
                message = "文件上传失败!";
                e.printStackTrace();
    
            }
            request.setAttribute("message", message);
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    }
    

加入进度显示的文件上传

  • 原生js+原生ajax
    • http://www.jb51.net/article/70521.htm
  • 超级棒的一篇文章
    • http://m.blog.csdn.net/liuzuochen/article/details/1516522
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘风御浪云帆之上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值