简介

Filter也称之为过滤器,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

过滤器可以拦截请求和响应,,操作请求和响应中的数据,,控制是否允许访问目标资源,,url级别的拦截 (粗粒度)。

原理

一个过滤器

首先在HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest 。根据需要检查HttpServletRequest,也可以修改HttpServletRequest 头和数据。
然后在HttpServletResponse到达客户端之前,拦截HttpServletResponse 。根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

基本应用

1,创建一个Filter

public class Filter1 implements Filter {

    @Override
public void init(FilterConfig filterConfig) throws ServletException {
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 为了调用子类的方法
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
System.out.println("***** 执行过滤器1 ... ...拦截路径: " + httpServletRequest.getRequestURI());
// 允许访问目标资源,简称 放行
chain.doFilter(httpServletRequest, response);
} @Override
public void destroy() {
} }

2,web.xml配置

<!-- 注册过滤器 -->
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.test.web.filter.Filter1</filter-class>
<!-- 配置当前过滤器的配置信息 -->
<init-param>
<param-name>safeNum</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<!-- 映射过滤器需要拦截的路径 -->
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/hello.jsp</url-pattern>
<url-pattern>/HelloServlet</url-pattern>
</filter-mapping>

过滤器链(多个过滤器共同拦截)

注意:我们下面的两个过滤器都拦截了同样的路径,先后顺序是由映射决定的,而不是注册顺序,也就是说下面这两个过滤器先执行的是filter2而不是filter1

  <!-- 注册过滤器 -->
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.test.web.filter.Filter1</filter-class>
</filter>
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.test.web.filter.Filter2</filter-class>
</filter>
<!-- 映射过滤器需要拦截的路径 -->
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/hello.jsp</url-pattern>
<url-pattern>/HelloServlet</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/hello.jsp</url-pattern>
<url-pattern>/HelloServlet</url-pattern>
</filter-mapping>

生命周期

如下所示,1:实例化  2,初始化  3,拦截工作  4,销毁

public class Filter2 implements Filter {

    public Filter2() {
System.out.println("----------- 1 执行Filter2的构造方法");
} public void init(FilterConfig fConfig) throws ServletException {
System.out.println("----------- 2 执行Filter2的初始化方法");
} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 为了调用子类的方法
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
System.out.println("----------- 3 执行Filter2的执行拦截的方法 , 拦截路径:" + httpServletRequest.getRequestURI());// 放行
chain.doFilter(request, response);
} public void destroy() {
System.out.println("----------- 4 执行Filter2的销毁的方法 ");
} }

过滤器拦截方式

​ 1 直接请求(默认)

​ 2 请求转发(forward)

​ 3 错误页面跳转(error)

​ 4 引入其他页面(include)

如果你修改拦截方式,需要在web.xml中 通过 dispatcher标签指定。

    <filter>
<display-name>Filter2</display-name>
<filter-name>Filter2</filter-name>
<filter-class>com.test.web.filter.Filter2</filter-class>
<!-- 配置当前过滤器的配置信息 -->
<init-param>
<param-name>safeNum</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/hello.jsp</url-pattern>
<!-- 配置拦截jsp的方式: 请求转发 -->
<dispatcher>FORWARD</dispatcher>
<!-- 增加拦截方式: 直接请求 -->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/HelloServlet</url-pattern>
</filter-mapping>

案例演示一:解决post方式获取参数乱码和浏览器乱码

Filter:

public class EncodingFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 1 解决获取参数中文乱码(post)
request.setCharacterEncoding("utf-8");
// 2 解决浏览器出现的中文乱码
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request, response);
} public void destroy() {
} public void init(FilterConfig fConfig) throws ServletException {
} }

web.xml:

  <filter>
<display-name>EncodingFilter</display-name>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.test.web.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

案例演示二:统一解决get和post获取参数乱码

Filter:

public class GenericEncodingFilter implements Filter {

    public void destroy() {
} public void init(FilterConfig fConfig) throws ServletException {
} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 为了能够使用 子类的方法, 向下转型
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 对子类获取参数的方法进行增强: 包装
HttpServletRequest myRequest = new MyRequest(httpServletRequest);
// 放行
chain.doFilter(myRequest, response);
} class MyRequest extends HttpServletRequestWrapper { private HttpServletRequest request; // 标识: 表示map是否处理过
private boolean isUpdate = false; // 表示没有处理 public MyRequest(HttpServletRequest request) {
super(request); // 注意: 这行代码不能丢失 this.request = request;
} @Override
public Map<String, String[]> getParameterMap() {
// 1 获取请求方式
String method = request.getMethod();
// 2 判断
if ("post".equalsIgnoreCase(method)) {
// 2.1 如果是post方式, 设置请求编码集, 返回map即可
try {
request.setCharacterEncoding("utf-8");
return request.getParameterMap(); // 结束当前方法
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if ("get".equalsIgnoreCase(method)) {
// 2.2 如果是get方式
// 2.2.1 获取map(没有处理)
Map<String, String[]> parameterMap = request.getParameterMap();
// 2.2.2 遍历map中的值, 使用先编码,再解码 解决乱码问题
if (parameterMap != null && isUpdate==false) { // 如果map没有处理过且不为null,才会被处理
for (Entry<String, String[]> en : parameterMap.entrySet()) {
String[] valArr = en.getValue(); // 数组是一个引用(地址)
for (int i = 0; i < valArr.length; i++) { // 注意:
// 这里不能使用增强for循环
try {
valArr[i] = new String(valArr[i].getBytes("iso-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
// 处理完map需要将状态修改为true
isUpdate = true;
}
// 2.2.3 返回map(处理过)
return parameterMap;
}
return super.getParameterMap();
} // 改造获取非多选的值
@Override
public String getParameter(String name) {
// 1 获取已经处理好的map
Map<String, String[]> parameterMap = this.getParameterMap();
// 2 从map中获取正确的值
String[] valArr = parameterMap.get(name);
// 3 判断
if (valArr != null) {
return valArr[0];
} else {
return null;
}
} @Override
public String[] getParameterValues(String name) {
// 1 获取已经处理好的map
Map<String, String[]> parameterMap = this.getParameterMap();
// 2 从map中获取正确的值
String[] valArr = parameterMap.get(name);
return valArr;
} } }

web.xml:

  <filter>
<display-name>GenericEncodingFilter</display-name>
<filter-name>GenericEncodingFilter</filter-name>
<filter-class>com.test.web.filter.GenericEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GenericEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

java Web 过滤器Filter详解的更多相关文章

  1. java web之Filter详解

    java web之Filter详解 2012-10-20 0 个评论 作者:chenshufei2 收藏 我要投稿 .概念: Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,W ...

  2. java web.xml配置详解(转)

    源出处:java web.xml配置详解 1.常规配置:每一个站的WEB-INF下都有一个web.xml的设定文件,它提供了我们站台的配置设定. web.xml定义: .站台的名称和说明 .针对环境参 ...

  3. 《Tomcat与Java Web开发技术详解》思维导图

    越想构建上层建筑,就越觉得底层基础很重要.补课系列. 书是良心书,就是太基础了,正适合补课. [纯文字版] Tomcat与Java Web开发技术详解 Servlet Servlet的生命周期 初始化 ...

  4. Java web.xml 配置详解

    在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...

  5. java web.xml配置详解

    1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Servl ...

  6. Java Web(一) Servlet详解!!

    这篇文章到上一篇,距离的有点遥远呀,隔了大概有两个月把,中间在家过了个年,哈哈~ 现在重新开始拾起,最近在看一本个人觉得很棒的书,<Java Web 整合开发王者归来>,现在写的这一系列基 ...

  7. Servlet中的过滤器Filter详解

    加载执行顺序 context-param->listener->filter->servlet web.xml中元素执行的顺序listener->filter->stru ...

  8. (转)Java Web(一) Servlet详解!!

    https://www.cnblogs.com/whgk/p/6399262.html 这篇文章到上一篇,距离的有点遥远呀,隔了大概有两个月把,中间在家过了个年,哈哈~ 现在重新开始拾起,最近在看一本 ...

  9. Java Web开发之详解JSP

    JSP作为Java Web开发中比较重要的技术,一般当作视图(View)的技术所使用,即用来展现页面.Servlet由于其本身不适合作为表现层技术,所以一般被当作控制器(Controller)所使用, ...

随机推荐

  1. Every derived table must have its own alias

    完整错误信息如下: Every derived table must have its own alias 三月 28, 2017 10:20:46 上午 org.apache.catalina.co ...

  2. 学习Java有没有什么捷径?

    很多网友咨询学习Java有没有什么捷径,我说“ 无他,唯手熟尔 ”.但是愿意将一些经验写出来,以便后来者少走弯路,帮助别人是最大的快乐嘛! 要想学好Java,首先要知道Java的大致分类. 我们知道, ...

  3. 剑指Offer面试题:1.实现单例模式

    一 题目:实现单例模式Singleton 题目:设计一个类,我们只能生产该类的一个实例. 只能生成一个实例的类是实现了Singleton(单例)模式的类型.由于设计模式在面向对象程序设计中起着举足轻重 ...

  4. bzoj 4448 情报传递

    Written with StackEdit. Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有\(n\)名情报员.每名情报员能有若干名(可能没有)下线,除\ ...

  5. 剑指offer-第五章优化时间和空间效率(从1到n的整数中1出现的次数)

    题目:输入一个整数n,从1到n这n个十进制整数中1出现的次数. 思路1:对1到n中的任意一个数i对其进行求余数来判断个位是否为1,然后再求除数,判断十位是否为1.统计出1的个数.然后对1到n用一个循环 ...

  6. 序列化 SqlAlchemy 的结果为 json 字符串

    http://my.oschina.net/gongshang/blog/395431?p=1 在设计 RESTful 的网站时,我们总是希望 ORM 框架返回的结果是可以直接给 View 层使用的 ...

  7. React组件性能优化总结

    性能优化的思路 影响网页性能最大的因素是浏览器的重排(repaint)和重绘(reflow). React的Virtual DOM就是尽可能地减少浏览器的重排和重绘. 从React渲染过程来看,如何防 ...

  8. Tomcat起了一个测试桩,调用该测试桩无响应

    有时在测试新业务流程时因为涉及多个不同接口的调用,而这些被调用的服务端因为网络权限或开发进度问题暂时对我们不可达,那么我们可以通过模拟接口返回来完成我们新业务的测试.这次碰到的问题是我明明起了该测试桩 ...

  9. PHP大小写:函数名和类名不区分,变量名区分

    PHP对大小写敏感问题的处理比较乱,写代码时可能偶尔出问题,所以这里总结一下. 但我不是鼓励大家去用这些规则.推荐大家始终坚持“大小写敏感”,遵循统一的代码规范. 1. 变量名区分大小写 <?p ...

  10. 《转载》ubuntu Sublime text 3 解决中文输入问题

    其实,在这个文章之前,网上都有好多教程了.不知道是不是因为复制黏贴的传播太多,导致有些字符串的丢失,导致编译失败,so库文件无法载入,从而不能输入中文.折腾了许久之后,终于搞定了.记录下来,方便自己下 ...