Servlet基础之过滤器、监听器、文件上传下载


考虑到这些东西已经不被常用了,就把以前的笔记翻上来应付下好了,暂不炒冷饭。

Filter(过滤器)

过滤器

过滤器的生命周期

在服务器启动的时候构造过滤器对象并且调用初始化方法。
在访问到映射路径时调用过滤器的过滤方法(doFilter)。
销毁的时候或者Reloading的时候调用过滤器的销毁方法.

登录过滤器

  1. 先强转request和response的对象类型
  2. 获取uri的路径
  3. 判断uri路径是否符合条件--符合条件则放行
  4. 不符合条件则判断session中是否有用户登录凭证--有则放行
  5. 没有则重定向

编码过滤器

  1. 把处理编码的代码抽取到过滤器中
    • req.setCharacterEncoding("utf-8");
    • 只针对post请求的编码处理
  2. 针对get的请求有2种
    1. 修改服务器的编码格式
    2. 编写包装类
  3. 多个过滤器的过滤顺序
    • 过滤器的过滤顺序跟web.xml的配置有关。
    • 放行后的代码则是服务器响应给客户端的时候执行,执行顺序与过滤顺序相反。

其他

过滤器是"链"在容器的处理过程中的。

这就意味着它们会在servlet处理器之前访问一个进入的请求,并且在外发响应信息返回到客户前访问这些响应信息。
这种访问使得过滤器可以检查并修改请求和响应的内容。

关于web.xml

Fiter的注册映射路径一般是/* 代表通配所有的路径。
用中间抽象类时要注意web.xml不能有该抽象类的注册,否则会默认实例该类,但抽象类不能实例化。


Listener(监听器)

监听器就是监听某个域对象的的状态变化的组件

监听器的相关概念

  • 事件源:被监听的对象(三个域对象)
    • request
    • session
    • servletContext
  • 监听器:监听事件源对象事件源对象的状态的变化都会触发监听器(6+2)。
  • 注册监听器:将监听器与事件源进行绑定。
  • 响应行为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)。

监听器有哪些

  • 第一维度按照被监听的对象划分:
    • ServletRequest域
    • HttpSession域
    • ServletContext域
  • 第二维度按照监听的内容分:
    • 监听域对象的创建与销毁的
    • 监听域对象的属性变化的

监听三大域对象的创建与销毁

监听三大域对象的监听器分别是:

  • ServletContextListener
  • HttpSessionListener
  • ServletRequestListener
监听器的编写步骤(重点):
  1. 编写一个监听器类去实现监听器接口。
  2. 覆盖监听器的方法。
  3. 需要在web.xml中进行配置—注册。
监听ServletContext域的创建与销毁的监听器ServletContextListener
  • Servlet域的生命周期

    • 何时创建:服务器启动创建
    • 何时销毁:服务器关闭销毁
  • ServletContextListener监听器的主要作用

    • 初始化的工作:初始化对象、初始化数据(加载数据库驱动、连接池的初始化)
    • 加载一些初始化的配置文件(spring的配置文件)
    • 任务调度(定时器—Timer/TimerTask)
监听Httpsession域的创建于销毁的监听器HttpSessionListener
  • HttpSession对象的生命周期
    • 何时创建:第一次调用request.getSession时创建
    • 何时销毁:服务器关闭销毁、session过期(默认30分钟,修改默认的30分钟是在Tomcat的web.xml,修改当前项目的过期时间是在自己项目的web.xml中)、手动销毁。
  • HttpSessionListener监听器的主要作用
    • 由于每次访问网站都会默认创建session对象(jsp页面中page指令中的session属性默认为true,即被访问时创建session),可以用于计数网站访问过的人
监听ServletRequest域创建与销毁的监听器ServletRequestListener
  • ServletRequest的生命周期
    • 创建:每一次请求都会创建request
    • 销毁:请求结束
  • 用法同上

其他

剩余四分之三的知识点没写 (我也不知道几年前的我为什么没写,虽然现在我也不想写,后面写过Spring后再讲)


文件上传下载

其实都是旧代码了,没什么实际用处,辣鸡代码不看也罢

上传

  1. 修改项目设置
    • 修改图片上传的目录位置
  2. 修改form表单属性
    • 提交方式为:Post
    • 添加属性为:enctype="multipart/form-data"
    • 上传文件的type为:file
    • 上传文件要设置name才能在后台获得
  3. 导包
    • 对于文件上传,浏览器是以流的形式提交到服务器端的
    • 如果直接用输入流解析请求参数会比较麻烦,一般采用apache提供的jar包组件:
      • commons-fileupload-1.2.2.jar
      • commons-io-2.2.jar
  4. Servlet
    1. 通过jar包实例化 磁盘工厂 对象
    2. 实例化一个 文件上传解析器,在构造方法中传递工厂对象
    3. 解决上传文件名的中文乱码问题
    4. 创建一个map/对象,用于存放表单数据
    5. 通过解析器解析前端发送的复合表单数据,返回一个集合
    6. 遍历这个集合,判断是否为非文本数据
    7. 使用工具包——存储在服务器路径下(注意解决重名问题)
      • 提示用户修改名字
      • 通过时间生成目录
      • 通过UUID生成唯一文件名
    8. 处理表单信息
    9. 关流

假设有一个表单提交要上传图片

    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    upload.setHeaderEncoding("UTF-8");
    
    HashMap<String, String> map = new HashMap<>();
    List<FileItem> list = upload.parseRequest(request);
    for(FileItem item :list){
        //判断是否为非文本数据
        if (!item.isFormField()) {
            ...
        }
    }
    
    //1.通过全局对象获取绝对路径
    String path = getServletContext().getRealPath("Upload");
    File file = new File(path);
    //判断路径是否存在
    if(!file.exists()){
        file.mkdirs();
    }
    //绝对路径
    UUID uuid = UUID.randomUUID();
    File newfile = new File(filePath,uuid.toString()+"_"+fItem.getName());
    is = fItem.getInputStream();
    fos = new FileOutputStream(file);
    //传递输入输出流拷贝文件
    IOUtils.copy(is , fos);
 	stu.setImgUrl("Upload/"+uuid.toString()+"_"+fItem.getName());
 	
 	//根据Key(input标签的name属性值)获取value值
 	String value = map.get(fItem.getFieldName());
 	if(value== null){
  	    //代表第一次存储
 	    map.put(fItem.getFieldName(),fItem.getString());
 	}else{
 	    //不是第一次存储,复选框
            map.put(fItem.getFieldName(),value+","+fItem.getString());
 	}
 	
 	//把map中的数据存放到stu对象中,这里用到BeanUtils的jar包
    BeanUtils.populate(stu,map);
    
    //注意后面关流
    ....

下载

  1. 前端页面
    • 下载链接传递到Servlet,并带上path=图片相对路径的属性
  2. Servlet
//    获取前端传递的path属性
    String path = request.getParameter("path");
//    截取出文件名
    String fileName = path.substring(path.lastIndexOf("/")+1);
//    解决文件名的中文乱码问题
    fileName = URLEncoder.encode(fileName,"utf-8");
//    获取图片完整路径
    path = getServletContext().getRealPath(path);
//    设置响应头
    response.setHeader("Content-disposition","attachment;fileName="+fileName);
//    创建输入输出流,用工具类复制
    fis = new FileInputStream(path); 
    os = response.getOutputStream();
    IOUtils.copy(fis,os);
//    关流
    ....

已经淘汰的内容,只是把多年前的学习笔记翻上来,不供参考

原文地址:https://www.cnblogs.com/zohnn/p/13857454.html