JavaWeb之filter&listener&文件上传

一、filter

1.1 过滤器的基本概述:

filter是Servlet规范中的一个接口(javax.servlet.Filter接口),要想实现过滤器功能,必须实现此接口。

JavaWeb中的过滤器:当用户访问服务器资源时,过滤器将请求拦截下来,完成一些特殊的功能(如登录验证、统一编码处理、敏感字符过滤),还可以对响应信息进行拦截过来(一般是用来做数据压缩的)。

接口中有三个方法:

  • init:用于初始化
  • doFilter:每次执行拦截过滤
  • destroy:用于销毁

1.2 过滤器快速使用

在这里插入图片描述

1.2.1 编码步骤

  1. 客户端向服务器发起访问资源的请求
  2. Filter将请求拦截住,开始处理访问资源之前的逻辑
  3. Filter决定是否要放行访问请求,如果放行,请求继续向后运行
  4. 请求访问到相关资源,然后服务器给出响应
  5. Filter将响应拦截住,开始处理访问资源之后的逻辑
  6. 服务器将响应返回给浏览器

1.2.2 Filter配置

xml:

<filter>
	<filter-name>别名</filter-name>
    <filter-class>配置过滤器的全路径
</filter>
<filter-mapping>映射配置
     <filter-name>别名</filter-name>
     <url-pattern>filter的拦截路径</url-pattern>
</filter-mapping>

注解:

@WebFilter(value="指定拦截规则")  //value属性和urlPatterns属性的作用是一样的

1.2.3 Filter执行过程

单个过滤器:

  • 请求访问资源之前,先到达过滤器
  • 过滤器放行之后,会访问资源
  • 访问资源之后,还会再次经过过滤器

多个过滤器

  • 请求访问资源之前,先到达过滤器
  • 过滤器放行之后,执行下一个过滤器,直到所有过滤器执行完之后,才会访问资源
  • 只要其中任何一个过滤器没有放行,就不会访问资源
  • 访问资源之后,还会按照倒序方式执行过滤器

过滤器的放行:

  • 调用FilterChain接口中的doFilter方法,如果有下一个过滤器,则执行下一个过滤器;如果当前过滤器处于调用的最后一个过滤器,就执行目标资源。

多个过滤器的执行顺序

XML方式:

  • <filter-mapping>的配置先后顺序

注解方式:

  • 看过滤器的类名的字符,按照ASCII码表的顺序,一个字母一个字母的比,字母排在前面的先执行

1.3 Filter的生命周期

创建:应用加载时,Filter对象创建

  • void init(FilterConfig config):初始化方法,在项目启动的时候就会执行,只执行一次

活着:只要应用提供服务,Filter对象就一直存在

  • void doFilter(request,response,FilterChain chain):执行过滤方法,当请求匹配上的时候就会执行

销毁:应用卸载或者服务器宕机,对象销毁

  • void destroy():销毁,在项目被移除的时候或者服务器关闭的时候就会执行,只执行一次

1.4 拦截方式配置

默认情况下,Fliter只拦截请求,请求到达服务器的时就开始拦截。

可以通过<filter-mapping>标签中dispatcher标签来配置过滤拦截方式:

  • <dispatcher>REQUEST</dispatcher> 默认值,只拦截从浏览器直接发送过来的请求
  • <dispatcher>FORWARD</dispatcher> 过滤拦截转发过来的请求
  • <dispatcher>INCLUDE</dispatcher> 过滤拦截包含,只有动态包含(与静态包含无关,因为静态包含是一个文件)
  • <dispatcher>ERROR</dispatcher> 过滤拦截全局错误页面,一般不用
  • <dispatcher>ASYNC</dispatcher> 过滤拦截异步请求,一般不用

1.5 Filter与servlet的区别

  • Servlet的功能过滤器全都有,而过滤器多了一个放行的功能
  • 过滤器它不是一个资源,不能通过地址栏输入访问
  • Servlet是一个资源,可以通过地址栏访问

二、监听器——Listener

2.1 Listener概述

在web程序中,Listener监视某些对象(域对象),一旦其发生相应的变化,就采取相应的操作,主要应用于 统计历史访问次数、统计在线人数、系统启动时初始化配置信息。

Listener主要概念:

  • 事件源:发生事件的对象
  • 事件:发生了什么事情
  • 监听器:是一个接口,这里面提供了一些方法需要我们自己编写

Listener是web核心中三大组件之一,

  • Servlet:服务器的小程序 , 程序的入口
  • Filter:过滤器
  • Listener:监听器

八个监听器接口:

监听对象创建和销毁的
ServletContextListener
ServletRequestListener
HttpSessionListener

监听域中属性发生变化的(变化有:存入域中,修改域中属性,从域中删除)
ServletContextAttributeListener
ServletRequestAttributeListener
HttpSessionAttributeListener

感知型监听器(都和会话域有关系)

HttpSessionBindingListener

感知有数据和会话域绑定
感知有数据和会话域解绑

HttpSessionActivtionListener

感知会话域中数据被钝化到磁盘上
感知磁盘上的数据被活化到会话域中

三、文件上传

3.1 文件上传概述

文件上传:要将客户端(浏览器)文件传递到服务器端存储,不是直接存储到数据库中,而是要将文件存储到服务器所在的磁盘上,这就要使用文件上传。

使用文件上传方式的好处:通过文件上传,可以将浏览器端的大数据直接保存到服务器端。不将数据保存到数据库中,而是保存到服务器磁盘上,这样减少了数据库服务器的压力,对数据的操作更加灵活。

3.2 常见的文件上传技术

  • 使用apache提供的工具:commons-fileupload.jar (代码写起来比较复杂)
  • 使用servlet3.0开始提供的文件上传方式
  • 使用springmvc框架(非常简单,底层封装了commons-fileupload)

3.3 文件上传浏览器前提

  1. 表单的提交方式必须是post
  2. 表单的enctype属性值必须是multipart/form-data(多部分表单数据)
  3. 在表单中提交文件选择框<input type='file'>,且需要提供name属性

3.4 使用commons-fileupload方式上传

  1. 导入jar包
  2. 创建磁盘文件项工厂,用来设置临时文件的大小和目录.
  3. 创建核心上传对象
  4. 使用核心上传对象解析请求,返回一个list<文件项>
  5. 遍历list,获取每个文件项
    • 判断是否为普通表单项(文件上传项之外)
      • 若是:获取name属性的值及用户输入的内容
      • 若不是:
        • 获取name属性的值
        • 获取文件的名称
        • 获取文件的内容
        • 保存文件
        • 删除临时文件
@WebServlet(name = "UploadServlet" , urlPatterns = "/uploadServlet")
public class UploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //借助第三方帮我们解析这个流(apache 提供fileUpload.jar包)
            //步骤如下:
            //步骤1: 创建磁盘文件项工厂,操作本地磁盘使用(例如创建临时文件...)
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //步骤2: 创建解析流的对象
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
            //步骤3: 开始解析-> 获得集合对象 List<FileItem>
            List<FileItem> list = fileUpload.parseRequest(request);

            //步骤4: 循环遍历
            for (FileItem fileItem : list) {
                //步骤5: 获得普通表单数据 和 文件上传数据
                //判断是普通的数据 还是文件上传数据   isFormField()是否为普通表单字段
                boolean formField = fileItem.isFormField();
                if(formField){
                    //普通表单数据  username=jack  nickname = rose
                    String name = fileItem.getName(); // null
                    String fieldName = fileItem.getFieldName();//表单提交key
                    String string = fileItem.getString("utf-8");// 表单提交的value
//
                    System.out.println(name);
                    System.out.println(fieldName);
                    System.out.println(string);
                }else{
                    //文件上传数据
                    String name = fileItem.getName(); // 文件的名称
                    String fieldName = fileItem.getFieldName();//表单提交key
                    //String string = fileItem.getString("utf-8");// 表单提交的value  文件的内容

                    //输入流
                    InputStream is = fileItem.getInputStream();

                    //截取后缀名
                    name = name.substring(name.lastIndexOf("."));

                    //保证文件名称不重复
                    String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
                    String filePath = "D:/"+date+name;//name是有后缀名 .jpg
                    //输出流
                    FileOutputStream os = new FileOutputStream(filePath);

                    //快速IO流操作
                    IOUtils.copy(is, os);
                    is.close();
                    os.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.5 Servlet3.0文件上传

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--
        文件上传有表单三要素:
            1.method必须是post提交(上传没有限制)
            2.表单中必须有一个组件 type="file"
            3.表单必须是多部分表单上传( 在表单上加入这个属性: enctype="multipart/form-data" )
            注意加入属性后 request对象获得数据的api 失效
    --%>
    <form action="/upload2Servlet" method="post" enctype="multipart/form-data">
        <input type="text" name="username"><br/>
        <input type="text" name="nickname"><br/>
        <input type="file" name="pic"><br/>
        <input type="submit">
    </form>
</body>
</html>

准备Servlet,加一个注解 @MultipartConfig 文件上传解析数据

@WebServlet(name = "Upload2Servlet" , urlPatterns = "/upload2Servlet")
@MultipartConfig //servlet 3.0提供的注解 目的 解析request对象 ,恢复原来的这些api
public class Upload2Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String nickname = request.getParameter("nickname");
        System.out.println(username);
        System.out.println(nickname);



        //处理文件 servlet 3.0提供api     request.getPart("key")  等效  request.getParameter("key");
        Part pic = request.getPart("pic");
        //判断文件是否存在
        if(pic!=null && pic.getSize() > 0){
            //解析文件
            String fileName = pic.getSubmittedFileName();//文件名称
            fileName = fileName.substring(fileName.lastIndexOf("."));
            String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
            String filePath = "D:/" + date + fileName ;

            //输入流
            InputStream is = pic.getInputStream();
            //输出流
            FileOutputStream os = new FileOutputStream(filePath);
            //快速IO流操作
            IOUtils.copy(is, os);
            is.close();
            os.close();
        }
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值