7.过滤器
7.1介绍
能够目标资源的请求和响应进行截取.
7.2使用
-
创建过滤器
-
新建一个类,实现Filter接口(Jakarta.servlet.Filter)
-
重写init,doFilter,destroy方法
- init:初始化过滤器
- doFilter:编写Filter代码
- destroy:销毁过滤器
-
package Filter; import jakarta.servlet.*; import java.io.IOException; public class FilterText implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("-----FilterText"); //运行继续执行浏览器请求的目标资源 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { Filter.super.destroy(); } }
-
-
配置filter信息
-
配置xml信息
-
<!--法1--> <filter> <filter-name>FilterText</filter-name> <!--过滤器类路径--> <filter-class>Filter.FilterText</filter-class> </filter> <filter-mapping> <!--过滤器名字--> <filter-name>FilterText</filter-name> <!--拦截的请求--> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
-
//法2 在过滤器的类上编写注解 @WebFilter("/*)
-
-
-
使用过滤器
-
即使用servlet
-
package FilterServlet; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/FirstFilter") public class FirstFilter extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("FirstFilter"); } }
-
7.3过滤规则
-
精确过滤:配置过滤器拦截指定的请求url
- 如:FirstServlet,index.html
-
后缀过滤:配置过滤器拦截指定的后缀的请求url
- 如:.jpg,.html
-
通配符过滤:
/*拦截所有请求
/aaa/bbb/*,拦截项目中带有/aaa/bbb的请求url
7.4执行时机
-
分类
- 前置过滤器:过滤器在目标资源之前执行
- 后置过滤器:过滤器在目标资源之后执行
- 环绕过滤器:执行目标资源之前会执行过滤器,目标资源执行之后还会执行过滤器
-
设置
-
通过放行的时机来设置过滤器业务的执行
-
在过滤器的doFilter方法中
- 写在放行代码前面业务会在目标资源执行之前执行,
- 写在放行代码后面的业务则会在目标资源执行之后执行
- 放行代码(filterChain.doFilter())
-
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("-----before"); //运行继续执行浏览器请求的目标资源 filterChain.doFilter(servletRequest,servletResponse); System.out.println("-----after"); }
-
7.5过滤器链
7.5.1介绍
-
在同一个服务器资源(servlet类)上可用添加多个过滤器,当用户请求资源时,会依次执行每一个过滤器,然后再执行目标资源再依次通过过滤器响应客户端请求.
7.5.2优先级
- 过滤器优先级,在一个web项目中如果配置多个过滤器,多个过滤器的先后执行顺序
- 如果多个过滤器都是使用注解配置的,则按照过滤器类名的字符串字典顺序执行.
- 如果多个过滤器都是使用xml配置的,则按照配置的先后顺序执行.
- 如果多个过滤器使用的配置方式不同.xml的优先级高于注解的优先级
- 如果同一个过滤器即通过xml配置又通过注解配置,则会被执行两次
8.servlet应用
8.1文件上传
-
客户端提交文件到servlet类,servlet类接收文件并保存
-
准备工作
-
新建一个html类,编写提交代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>提交信息</title> </head> <body> <h3>图书添加页面</h3> <form action="" method=""> <p>图书编号: <input type="text" name="bookId"></p> <p>图书名称: <input type="text" name="bookName"></p> <p>图书封面: <input type="file" name="bookImg"></p> <p><input type="submit" value="提交"></p> </form> </body> </html>
-
新建一个servlet类,接收提交信息
-
//接收图书信息 @WebServlet("/BookSaveServlet") public class BookSaveServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
-
-
新建一个实体类,将接收到的信息保存到数据库
-
package FilterPractise.dto; //将接收到的信息保存到数据库 public class Book { private String bookId; private String bookName; //保存的是图片的路径,而不是保存图片本身 private String bookPath; //getset和有参无参方法 }
-
-
-
前端提交上传文件
-
当form表单数据提交时,浏览器会对表单数据进行编码,然后提交;
-
当表单中存在文件的时候,要设置不编码传输
-
通过form表单的enctype属性设置表单数据的压缩方式:
- application/x-www- form-urlencoded 在发送前编码所有字符(默认)
- text/plain 将表单数据空格转换成+,不对特殊字符进行编码
- multipart/form-data不对表单数据进行编码
<!--在form中设置如下代码--> <form action="BookSaveServlet" method="post" enctype="multipart/form-data">
-
-
servlet类接收文件
-
当网页提交数据的表单设置了entype="multipart/form-data"之后
-
不能直接使用getParameter接收文本数据,需要在当前servlet类添加注解
-
用于处理非压缩提交的数据(@MultipartConfig)
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.设置utf-8编码 request.setCharacterEncoding("utf-8"); //2.接收普通文本 //当网页提交数据的表单设置了 enctype="multipart/form-data"之后不能直接使用getParameter接收文本数据 //需要在当前serlvet类添加 @MultipartConfig 用于处理非压缩提交的数据 String id = request.getParameter("bookId"); String name = request.getParameter("bookName"); //3. 接收表单提交的图片 // getPart("输入框name属性"): 接收表单中的文件 Part bookImg = request.getPart("bookImg"); // getParts(): 接收表单中所有文件 //Collection<Part> parts = request.getParts(); }
-
保存图片
-
在web工程的web目录下新建一个 files目录(保存文件的目录如果不在web服务器上,用户将无法访问
-
在files目录先放-一个任意的文件(空的目录在进行项目部署的时候不会在web服务器中创建)
//4.保存图片 // a.获取files目录在web服务器上的路径(不是工作空间的路径) ServletContext servletContext = getServletContext(); String dir = servletContext.getRealPath("/files"); // b.给上传的文件重命名 (不同用户有可能上传相同名称的图片,如果不重命名将导致文件覆盖) // 文件重命名后缀名不能改变 String header = bookImg.getHeader("Content-Disposition"); //form-data; name="bookImg"; filename="千锋武汉(横版).jpg" // 截取上传的文件的后缀名 int begin = header.lastIndexOf("."); int end = header.lastIndexOf("\""); String ext = header.substring(begin, end); // 取名(时间毫秒数、UUID、雪花算法) String fileName = UUID.randomUUID().toString()+ext; //c.存储文件到目录 bookImg.write(dir+"\\"+fileName); //5.将图书信息保存到数据库: 保存到数据库的是图片的访问路径(不是绝对路径) Book book = new Book(id, name, "files/" + fileName); //调用BookDAO 将book对象保存到数据库
-
-
8.2文件下载
-
准备工作(接上面)
- 在files文件夹里存放几个图片
- img01,img02,img03等....
- 新建一个servlet类,重写doget和dopost方法
- 在files文件夹里存放几个图片
-
创建一个html类
-
编写代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>文件下载</title> </head> <body> <img src="files/img01.png" height="100"/><br/> <a href="FileDownloadServlet?fileName=img01.png">下载</a><br/> <img src="files/img02.png" height="100"/><br/> <a href="FileDownloadServlet?fileName=img02.png">下载</a><br/> <img src="files/img03.png" height="100"/><br/> <a href="FileDownloadServlet?fileName=img03.png">下载</a><br/> </body> </html>
-
-
在servlet类中编写代码
-
package Servlets; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; public class FileDownloadServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.接收客户端传递过来的文件名(即为要下载的文件) String fileName = request.getParameter("fileName"); //img01.png //2.获取存储文件的files目录路径 ServletContext servletContext = getServletContext(); String dir = servletContext.getRealPath("/files"); // 拼接要下载的文件路径 String filePath = dir+"\\"+fileName; //3.设置响应头 response.setContentType("application/image"); //设置响应的类型如果浏览器无法识别则会提示另存为 response.addHeader("Content-Disposition","attachment; fileName="+fileName); //4. 通过IO流将文件数据响应给浏览器(文件是二进制数据,所以获取字节流) ServletOutputStream outputStream = response.getOutputStream(); // 读取服务文件,写给客户端 FileInputStream fis = new FileInputStream(filePath); byte[] bs = new byte[1024]; int len = -1; while( (len = fis.read(bs))!=-1){ outputStream.write(bs,0,len); } outputStream.close(); fis.close(); } }
-