6、过滤器、监听器、文件上传和下载
过滤器、监听器、文件上传和下载
过滤器(Filter)
过滤器又可以称之为拦截器。
Filter
java中的Filter并不是一个标准的servlet,它不能处理用户请求,对客户端 生成响应。主要用于对HttpServletRequest进行预处理,以对HttpServletResponse进行后处理。是一个典型的处理链。
通常用于实现诸如日志记录、字符集设置、访问拦截等功能。
过滤器是Javaweb的三大组件之一。其他两个为Servlet和Listener!
过滤器主要是请求目标资源(servlet,jsp,html,图片等一些web组件)之前进行拦截。
实现方式
写一个过滤器就是写一个Java类,然后实现Filter接口。然后在web.xml中配置,过滤的映射路径。与Servlet类似....
<!-- 配置过滤器 --> <filter> <filter-name>myFilter</filter-name> <filter-class>com.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/index.jsp</url-pattern>//需要拦截的路径 </filter-mapping> <!-- 配置第二个过滤器 --> <filter> <filter-name>myFilter2</filter-name> <filter-class>com.filter.MyFilter2</filter-class> </filter> <filter-mapping> <filter-name>myFilter2</filter-name> <url-pattern>/index.jsp</url-pattern> </filter-mapping>
多个过滤器执行顺序
web.xml中从 上往下执行,先执行到哪个那个优先过滤。
过滤器的生命周期
生命周期与servlet的类似。
\1. init(FilterConfig):
在服务器启动时会创建Filter实例,并且每个类型的Filter只创建一个实例,从此不再创建!在创建完Filter实例后,会马上调用init()方法完成初始化工作,这个方法只会被执行一次;
\2. doFilter(ServletRequest req,ServletResponse res,FilterChain chain):
这个方法会在用户每次访问“目标资源(
\3. destroy():
服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。
FilterChain chain.doFilter(req,resp);
对请求进行放行。
四种拦截方式
-
request 默认的。对过滤的路径直接访问的时候会进入到过滤器。比如:地址栏中直接访问、表单提交、超链接、重定向。
-
forword 转发访问执行的过滤器。如果访问的路径被过滤,我们还是可以通过间接的访问。比如:转发requestDispatcher#forword()方法、jsp:forword标签都是转发访问。
-
include 包含访问执行的过滤。
-
error 当目标资源在web.xml中配置
中时,并且出现了异常,转发到目标资源时会执行过滤器。 -
在
里面配置 <dispatcher>FORWARD</dispatcher> 过滤器应用场景
执行目标资源之前做预处理工资,比如设置编码,这种通常会放行。再比如对页面的权限访问。
在请求前对编码的设置
<!-- 设置编码的过滤器 --> <filter> <filter-name>encodeFilter</filter-name> <filter-class>com.filter.EncodeFilter</filter-class> </filter> <filter-mapping> <filter-name>encodeFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { /** * 对所有请求的编码进行设置 */ request.setCharacterEncoding("utf-8"); HttpServletRequest rq = (HttpServletRequest) request; if(rq.getMethod().equalsIgnoreCase("post")) { response.setContentType("text/html;charset=utf-8"); } //放行 chain.doFilter(request,response); }
监听器
监听器的概念:Listener是Servlet的监听器,是由容器管理的。servlet规范中定义的一套对范围对象(page,request,session,servletContext)的生命周期过程进行监听一种机制。使得发开人员更大程度地对PageContext,ServletContext,HttpSession和ServletRequest对象得生命周期进行控制。
监听器得作用:
利用listener接口见通风在容器中某个执行流程,比如监听Java对象得方法电泳或属性改变,当被监听得对象发生上述事件后,监听器某个方法将立即被执行。并且根据其与应用程序得需求做出适当得响应。
被监听的对象:
三个域对象:request session servletContext
需要在web.xml中注册监听器,比如:
<!-- 配置监听在线人数监听器 --> <listener> <!-- 监听器类的路径--> <listener-class>com.listener.CountListener</listener-class> </listener>
监听ServletContext:
ServletContextListener接口:生命周期的方法
ServletContextAttributeListener接口:对属性的生命周期进行监听。
其他三大域以此类推。
package com.listener; import java.util.HashSet; import java.util.Set; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; /** * 通过监听器,监听登录在线的人数。 */ public class CountListener implements HttpSessionAttributeListener{ Set<Object> set = new HashSet<Object>(); private int count = 0; @Override public void attributeAdded(HttpSessionBindingEvent event) { if("aname".equalsIgnoreCase(event.getName())||"username".equalsIgnoreCase(event.getName())) { set.add(event.getName()+":"+event.getValue()); System.out.println("wojin入了=="+event.getValue()); event.getSession().getServletContext().setAttribute("count", set.size()); event.getSession().getServletContext().setAttribute("set",set); } } @Override public void attributeRemoved(HttpSessionBindingEvent event) { if("aname".equalsIgnoreCase(event.getName())||"username".equalsIgnoreCase(event.getName())) { set.remove(event.getName()+":"+event.getValue()); System.out.println("我出去了=="+event.getValue()); event.getSession().getServletContext().setAttribute("count", set.size()); event.getSession().getServletContext().setAttribute("set",set); } } @Override public void attributeReplaced(HttpSessionBindingEvent event) { if("aname".equalsIgnoreCase(event.getName())||"username".equalsIgnoreCase(event.getName())) { Object obj = event.getSession().getAttribute(event.getName()); System.out.println(obj); set.add(obj); System.out.println("我替换了=="+event.getValue()); event.getSession().getServletContext().setAttribute("count", set.size()); event.getSession().getServletContext().setAttribute("set",set); } } }
文件的上传和下载(fastupload)
在项目中使用SmartUpload组件可以进行文件的上传和下载操作。
详细见文档。
文件上传:
@Override protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { //编码:SmartUpload获取的文件用的是GBK; //创建一个上传对象 SmartUpload upload=new SmartUpload(); //初始化对象 upload.initialize(getServletConfig(),arg0,arg1); //设置上传的基本设置 //设置允许的上传文件列表 upload.setAllowedFilesList("jpg,png,gif,txt"); //设置允许上传的单一文件的最大值,单位是字节; upload.setMaxFileSize(2*1024*1024); //设置一次性允许上传的多个文件的总共大小 upload.setTotalMaxFileSize(10*1024*1024); try { //设置禁止上传的文件的列表 upload.setDeniedFilesList("exe,com,bat"); //执行上传文件 upload.upload(); //获取上传的所有文件 Files files=upload.getFiles(); //通过getCount()获取总数;进行遍历; for(int i=0;i<files.getCount();i++){ //遍历判断获取客户端上传的文件 File file =files.getFile(i); if (file.isMissing()) {//如果文件不存在 continue;//不存在就不用处理 } //获取上传的文件夹的位置;(项目的发布路径) String path=arg0.getRealPath("upload"); //输出控制台查看项目的发布路径 System.out.println(path); //获取上传的文件的文件名.同时修改编码方式; String filename=new String(file.getFilePathName().getBytes(),"utf-8"); System.out.println("文件名:"+filename); //使用原文件名保存文件; file.saveAs(path+"/"+filename); } //使用smartupload的request对象去获取字符内容; //因为form表单传过来的是字节流,不是字符流了; Request request=upload.getRequest(); String username=new String(request.getParameter("username"). getBytes(),"utf-8"); System.out.println(username+"****"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
文件下载:
@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String img=req.getParameter("img"); //String img=req.getParameter("file"); //创建一个上传下载对象; SmartUpload upload=new SmartUpload(); //初始对象; upload.initialize(getServletConfig(),req,resp); //取消浏览器默认程序打开相对应文件的操作; upload.setContentDisposition(null); //下载相应的文件名 try { //实现下载文件 upload.downloadFile("/image/"+img); } catch (SmartUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!