Filter 过滤器:
对在客户端和服务器之间的中间层 接口,可对客户请求消息和服务器响应消息做拦截处理。并且 一个 servlet 文件可以添加多个过滤器,一个过滤器也可过滤多个 servlet 文件 都在 xml 文件中配置。
1 2 3 4 5 6 7
| public interface Filter { default void init(FilterConfig filterConfig) throws ServletException {} void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {} }
|
源码中可以看出它与 servlet 类似,都有 init 初始化和 destroy 销毁的方法。但这两方法与 servlet 不同的是,它们前面加入了 default 关键字(java8 新特性)。可以看到它们后面有方法体,所以我们可以选择不重写此两方法,只重写过滤的关键方法 doFilter 。且此方法与 servlet 中 service 方法类似,可对请求和响应做操作。
- 实例情景模拟:在浏览器中用post方式并以 name 为 key 传递一个中文的值访问
/servlet
映射如下。
1 2 3 4
| <form action="/web/servlet" method="post"> 名字:<input type="text" value="" name="name" /> <input type="submit" value="提交" name="sub" /> </form>
|
1 2 3 4 5 6 7 8 9 10 11 12
| @WebServlet("/servlet") public class Servlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); System.out.println(name); response.getWriter().write("哈哈哈"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MyFilter implements Filter { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8"); servletResponse.setContentType("text/html;charset=UTF-8"); filterChain.doFilter(servletRequest,servletResponse); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <web-app> <filter > <filter-name>myfilter</filter-name> <filter-class>io.ruoxijun.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myfilter</filter-name> <url-pattern>/servlet</url-pattern> <url-pattern>/此url标签不限个数</url-pattern> </filter-mapping>
<filter-mapping> <filter-name>filters</filter-name> <url-pattern>/servlet</url-pattern> </filter-mapping> </web-app>
|
Filter 生命周期:
与 servlet 类似唯一不同是当 服务器启动 便利用反射加载类调用无参构造函数,还有一个前提是必须在 xml 中配置了 Filter。之后便于 servlet 类似: init初始化 → doFilter(执行多次,到服务器关闭) → destory销毁
当一个 servlet 文件对应多个过滤器时,在 xml 中排在前的过滤器先执行。且注意过滤器是否有继续传递请求。
Filter 注解:
与 servlet 一样,Filter 也能使用注解:
在 Filter 类上方: @WebFilter("/servlet")
它还能过滤 jsp: @WebFilter("/路径全名.jsp")
Filter 使用场景:
- 同一处理中文乱码
- 屏蔽敏感词汇
- 控制资源访问权限
文件上传:
知识补充: req.getServletContext().getRealPath("/file/1.txt");
可拿到当前文件的路径,且传入参数会附加在该路径之后。返回字符串
上传时表单设置:
- input 的
type
设置为 file
- form 属性
method
需要设置为 post
(get 不会传输文件,只会提交文件的 name)
- form 属性
enctype
设置为 multipart/form-data
(文件传输必须设置)
1 2 3 4 5
| <form action="servlet" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <br /><br /> <input type="submit" value="提交" /> </form>
|
- servlet 中直接利用
resp
获取文件:
通过 req.getInputStream()
方法,接收到文件流
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { BufferedReader buReader=new BufferedReader( new InputStreamReader(req.getInputStream())); String values=null; BufferedWriter buWriter=new BufferedWriter( new OutputStreamWriter( new FileOutputStream("E:/test/str.txt"))); while ((values=buReader.readLine())!=null){ System.out.println(values); buWriter.write(values); buWriter.newLine(); buWriter.flush(); } }
|
注意: 此流输出的文件并不是指包含文件本身,它流的开头和末尾都插入了,一些浏览器信息。不经过处理直接保存可能导致文件无法正常使用。
- 使用
fileupload
获取上传文件:
使用 fileupload
需要导入 commons-fileupload
和 commons-io
的 jar 包。它将所有的请求都解析成了 FileItem
对象,以面像对象的方式完成文件的上传。如我们不用再考虑怎么处理浏览器头尾自带的信息,它的将文件和信息提取分离了出来。我们只需调用它提供的方法就能获取到我们需要的数据信息。
ServletFileUpload
文件管理对象的 parseRequest(HttpServletRequest)
请求解析方法,会将 form 的每一个 input 都解析为一个 fileitem 对象,并组成 List<FileItem>
集合返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { DiskFileItemFactory dfif=new DiskFileItemFactory(); ServletFileUpload sfu=new ServletFileUpload(dfif); try { List<FileItem> fileItems=sfu.parseRequest(req); for(FileItem fileItem: fileItems){ if(fileItem.isFormField()){ String name=fileItem.getFieldName(); String value=fileItem.getString("UTF-8"); }else{ String fileName=fileItem.getName(); long size=fileItem.getSize(); InputStream input=fileItem.getInputStream(); FileOutputStream output=new FileOutputStream("e:/test/"+fileName); int b=0; while ((b=input.read())!=-1){ output.write(b); } output.close(); input.close(); } } } catch (FileUploadException e) { e.printStackTrace(); } }
|
文件下载:
1
| <a href="servlet">下载</a>
|
servlet 中:
resp.setContentType
和 resp.setHeader
为文件下载必须设置方法。它们会掉用浏览器自带的下载程序。
resp.getOutputStream()
获取到指向浏览器的输出流,输出文件。
1 2 3 4 5 6 7 8 9 10 11 12 13
| protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("application/x-msdownload"); resp.setHeader("Content-Disposition","attachment;filename=ha.txt"); OutputStream output = resp.getOutputStream(); FileInputStream input = new FileInputStream("E:\\test\\1.txt");
int b=0; while ((b=input.read())!=-1){ output.write(b); } }
|