构建自己的Java Web框架(二)之一个Filter引发的血案
2016-06-27 11:25
519 查看
Filter也称之为过滤器,该技术是在Servlet 2.3中新增加的功能,不过他就是一种特殊的Servlet。我们通过Filter技术,可以对web服务器的所有资源:例如CSS样式、Js脚本、图片或静态html文件、jsp、servlet 等文件进行拦截,从而在这个基础上增加我们所需的功能,例如实现统一编码、相关日志处理、URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
下面我画了一个Filter的时序图:
在这个图中我们可以看到Filter是一个“链式”的处理方式(“servlet chaining” servlet 链),它放在web资源之前,在servlet被调用之前截获,
但它本身并不生成请求和响应对象。HttpServletRequest和HttpServletResponse在整个链中是两个重要的对象,当Request/Reponse在客户端与服务器端进行传输的过程中,filter对这两个对象进行过滤,比如:检查servlet request,根据需要修改request头和request数据,根据需要修改response头和response数据等。然而不仅仅是单纯的过滤掉一些东西,更主要的是增加扩展一些功能/服务。我们使用的时候需要在web.xml中去声明它,web容器会按照web.xml中过滤器声明的的先后循序组装成一条链挨个执行。
Filter生命周期的四个阶段:
(1)实例化:Web容器在部署Web应用程序时对所有过滤器进行实例化。Web容器回调它的无参构造方法。
(2)初始化:实例化完成之后,马上进行初始化工作。Web容器回调init()方法。
(3)过滤:请求路径匹配过滤器的URL映射时。Web容器回调doFilter()方法--主要的工作方法。
(4)销毁: Web容器在卸载Web应用程序前,Web容器回调destroy()方法。
其实就是:init()->doFilter()->destroy(),接下来我们来用点实例来看看它怎么工作的:
一、新建一个Dynamic Web Project工程:
点击next
注意红框内容,点击Finish,这样我们就创建了一个J2EE web工程。
二、创建包:
点击Finish结束。
三、创建Filter:
点击Finish结束。这样我们就创建了第一个Filter,接下来我们再创建一个Filter步骤同上面。
四、添加代码:
BootstrapFilter.java
TollGateFilter.java:
修改web.xml,位置在webroot -> WEB-INF
五、发布到web容器
点击Next
点击Finish,然后Tomcat就启动了。
我们注意观察控制台中输出的信息,大家会发现
Filter初始化化的顺序和我们web.xml配置的顺序是相反的。
在浏览器中执行我们的连接:http://localhost:8080/seframework/
我们的Filter是按照我们配置的顺序,按照链的方式依次执行。
然后我们看销毁的执行顺序,你会发现他和初始化的顺序是一样的。
通过上面我们可以完整的看到过滤器的一个执行顺序,它在整个过程中是如此的重要。 我们在学习其他框架的时候,你会注意到当我们添加完jar包文件后就会让你到web.xml中去添加他们的Filter,正是这个Filter接管了我们的所有Url请求,然后才有了强大的框架功能,因此我们向自己的框架开始迈开了第一步,接下来是我们大展身手的时候了。
下面是我自己框架的一个Filter,他拦截了所有的Url请求,首先会去判断服务器上是否存在相关资源,如果存在就不做任何操作,非资源则我们就开始让请求到我们的index.servlet ,我们开始在这个servlet上面加砖加瓦了。
如果你感觉本文对你有帮助,你可以继续关注我的博客,我会一步一步把框架实现。
这个路还很长很长,非常希望能和大家一起交流,共同学习和进步。
大家看过后觉得有启发的话可以顶一下这篇文章,让更多的朋友有机会看到它。也希望大家可以多留言来和我探讨框架相关的问题和知识。
最后,谢谢大家的支持!~~~
下面我画了一个Filter的时序图:
在这个图中我们可以看到Filter是一个“链式”的处理方式(“servlet chaining” servlet 链),它放在web资源之前,在servlet被调用之前截获,
但它本身并不生成请求和响应对象。HttpServletRequest和HttpServletResponse在整个链中是两个重要的对象,当Request/Reponse在客户端与服务器端进行传输的过程中,filter对这两个对象进行过滤,比如:检查servlet request,根据需要修改request头和request数据,根据需要修改response头和response数据等。然而不仅仅是单纯的过滤掉一些东西,更主要的是增加扩展一些功能/服务。我们使用的时候需要在web.xml中去声明它,web容器会按照web.xml中过滤器声明的的先后循序组装成一条链挨个执行。
Filter生命周期的四个阶段:
(1)实例化:Web容器在部署Web应用程序时对所有过滤器进行实例化。Web容器回调它的无参构造方法。
(2)初始化:实例化完成之后,马上进行初始化工作。Web容器回调init()方法。
(3)过滤:请求路径匹配过滤器的URL映射时。Web容器回调doFilter()方法--主要的工作方法。
(4)销毁: Web容器在卸载Web应用程序前,Web容器回调destroy()方法。
其实就是:init()->doFilter()->destroy(),接下来我们来用点实例来看看它怎么工作的:
一、新建一个Dynamic Web Project工程:
点击next
注意红框内容,点击Finish,这样我们就创建了一个J2EE web工程。
二、创建包:
点击Finish结束。
三、创建Filter:
点击Finish结束。这样我们就创建了第一个Filter,接下来我们再创建一个Filter步骤同上面。
四、添加代码:
BootstrapFilter.java
package com.seframework; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; /** * Servlet Filter implementation class BootstrapFilter */ @WebFilter("/BootstrapFilter") public class BootstrapFilter implements Filter { /** * Default constructor. */ public BootstrapFilter() { // TODO Auto-generated constructor stub } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub System.out.println("交警,销毁!"); } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub // place your code here System.out.println("请出示通行证!"); // pass the request along the filter chain chain.doFilter(request, response); System.out.println("收回通行证!"); } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub System.out.println("初始化,交警!"); } }
TollGateFilter.java:
package com.seframework; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; /** * Servlet Filter implementation class TollGateFilter */ @WebFilter("/TollGateFilter") public class TollGateFilter implements Filter { /** * Default constructor. */ public TollGateFilter() { // TODO Auto-generated constructor stub } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub System.out.println("收费站, 销毁!"); } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub // place your code here System.out.println("缴费中..."); // pass the request along the filter chain chain.doFilter(request, response); System.out.println("缴费完毕"); } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub System.out.println("初始化收费站"); } }
修改web.xml,位置在webroot -> WEB-INF
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>seframework</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 定义Filter --> <filter> <!-- Filter的名字 --> <filter-name>seframework</filter-name> <!-- Filter的实现类 --> <filter-class>com.seframework.BootstrapFilter</filter-class> </filter> <filter> <filter-name>toll gate</filter-name> <filter-class>com.seframework.TollGateFilter</filter-class> </filter> <!-- 定义Filter拦截的URL地址 --> <filter-mapping> <!-- Filter的名字 --> <filter-name>seframework</filter-name> <!-- Filter拦截规则 --> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>toll gate</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
五、发布到web容器
点击Next
点击Finish,然后Tomcat就启动了。
我们注意观察控制台中输出的信息,大家会发现
Filter初始化化的顺序和我们web.xml配置的顺序是相反的。
在浏览器中执行我们的连接:http://localhost:8080/seframework/
我们的Filter是按照我们配置的顺序,按照链的方式依次执行。
然后我们看销毁的执行顺序,你会发现他和初始化的顺序是一样的。
通过上面我们可以完整的看到过滤器的一个执行顺序,它在整个过程中是如此的重要。 我们在学习其他框架的时候,你会注意到当我们添加完jar包文件后就会让你到web.xml中去添加他们的Filter,正是这个Filter接管了我们的所有Url请求,然后才有了强大的框架功能,因此我们向自己的框架开始迈开了第一步,接下来是我们大展身手的时候了。
下面是我自己框架的一个Filter,他拦截了所有的Url请求,首先会去判断服务器上是否存在相关资源,如果存在就不做任何操作,非资源则我们就开始让请求到我们的index.servlet ,我们开始在这个servlet上面加砖加瓦了。
package com.seframework.Foundation; import java.io.File; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet Filter implementation class BaseFilter */ @WebFilter("/BootstrapFilter") public class BootstrapFilter implements Filter { /** * Default constructor. */ public BootstrapFilter() { // TODO Auto-generated constructor stub } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub // place your code here HttpServletRequest rq = (HttpServletRequest) request; HttpServletResponse rp = (HttpServletResponse) response; String realPath = rq.getServletContext().getRealPath("/"); String uri = rq.getRequestURI(); File file = new File(realPath + uri); if (!file.exists() && !file.isDirectory()) { String rewriteUrl = "/index"; rewriteUrl += "?" + uri.trim(); String query = rq.getQueryString(); if (query != null) { query = query.toString(); rewriteUrl += "?" + query; } if (null != rewriteUrl) { request.getRequestDispatcher(rewriteUrl).forward(rq, rp); return; } } // pass the request along the filter chain chain.doFilter(request, response); } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub } }
如果你感觉本文对你有帮助,你可以继续关注我的博客,我会一步一步把框架实现。
这个路还很长很长,非常希望能和大家一起交流,共同学习和进步。
大家看过后觉得有启发的话可以顶一下这篇文章,让更多的朋友有机会看到它。也希望大家可以多留言来和我探讨框架相关的问题和知识。
最后,谢谢大家的支持!~~~
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- JSP/PHP基于Ajax的分页功能实现
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序