博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaWeb之filter&listener&文件上传
阅读量:4249 次
发布时间:2019-05-26

本文共 7265 字,大约阅读时间需要 24 分钟。

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的拦截路径

注解:

@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
List
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" %>    Title    <%--        文件上传有表单三要素:            1.method必须是post提交(上传没有限制)            2.表单中必须有一个组件 type="file"            3.表单必须是多部分表单上传( 在表单上加入这个属性: enctype="multipart/form-data" )            注意加入属性后 request对象获得数据的api 失效    --%>    

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

@WebServlet(name = "Upload2Servlet" , urlPatterns = "/upload2Servlet")@MultipartConfig //servlet 3.0提供的注解 目的 解析request对象 ,恢复原来的这些apipublic 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(); } }}

转载地址:http://ncwei.baihongyu.com/

你可能感兴趣的文章
TCP/IP详解笔记(一)
查看>>
501. Find Mode in Binary Search Tree
查看>>
504. Base 7
查看>>
593. Valid Square
查看>>
494. Target Sum
查看>>
463. Island Perimeter
查看>>
TCP协议粗析
查看>>
653. Two Sum IV - Input is a BST
查看>>
spark rdd 和 DF 转换
查看>>
RDD 基础操作
查看>>
RDD基本操作(下)
查看>>
##########(python 解析参数方法 可用) Python optionParser模块的使用方法 #######
查看>>
org.apache.hadoop.io.compress系列1-认识解码器/编码器
查看>>
pyspark-combineByKey详解
查看>>
从原理到代码:大牛教你如何用 TensorFlow 亲手搭建一套图像识别模块 | AI 研习社
查看>>
FM算法详解
查看>>
FM算法能够学习到原始特征的embedding表示
查看>>
Factorization Machines 学习笔记
查看>>
Spark入门实战系列--9.Spark GraphX介绍及实例
查看>>
倾情大奉送--Spark入门实战系列
查看>>