Java Web进阶(4) -- 过滤器

第1章 过滤器基本使用

1-1 初识过滤器-Filter
过滤器- Filter
◆ Filter过滤器 (Filter)是J2EE Servlet模块下的组件
◆ Filter的作用是对URL进行统一的拦截处理
◆ Filter通常用于应用程序层面进行全局处理

在这里插入图片描述

开发过滤器三要素:
◆ 任何过滤器都要实现javax.servlet.Fiiter接口
◆ 在Filter接口的doFilter()方法中编写过滤器的功能代码
◆ 在web.xml中对过滤器进行配置,说明拦截URL的范围

1-2 开发第一个过滤器
过滤器类

public class MyFirstFilter implements Filter {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		System.out.println("过滤器已生效");
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub

	}

}

web.xml

 <!--  filter标签用于说明哪个类是过滤器,并在应用启动时自动加载 --> 
 <filter>
	  <filter-name>MyFirstFilter</filter-name> 
	  <filter-class>com.imooc.filter.MyFirstFilter</filter-class> 
 </filter>
 <!--  
  	filter-mapping标签用于说明过滤器对URL应用的范围,要点有二:
  	1. filter-name 过滤器名称与filter.filter-name保持一致
  	2. url-pattern 说明过滤器作用范围,/* 代表对所有URL进行过滤
-->
 <filter-mapping>
	  <filter-name>MyFirstFilter</filter-name> 
	  <url-pattern>/*</url-pattern> 
 </filter-mapping>

1-3 过滤器的生命周期
在这里插入图片描述
过滤器类

public class MyFirstFilter implements Filter {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println("过滤器已被销毁");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		System.out.println("过滤器已生效");
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("过滤器初始化成功");
	}

}

过滤器的特性
◆ 滤器对象在Web应用启动时被创建且全局唯一
◆ 唯一的过滤器对象在并发环境中采用“多线程”提供服务

第2章 过滤器进阶

2-1 过滤器的两种开发形式
过滤器两种开发方式
● 配置形式维护性更好,适用应用全局过滤 xml中配置
在这里插入图片描述

● 注解形式开发体验更好,适用于小型项目敏捷开发
在这里插入图片描述

//Servlet3.0版本之后,默认对注解有了支持
@WebFilter(filterName = "MyAnnoationFilter", urlPatterns = "/*")
public class MyAnnoationFilter implements Filter {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		System.out.println("注解形式过滤器已生效");
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

}

2-2 实战案例-字符集过滤器
Web中文乱码的解决
◆ GET请求-server.xml增加URIEncoding="UTF-8"
◆ POST请求-使用request.setCharacterEncoding("UTF-8");
◆ 响应-response.setContentType("text/html;charset=UTF-8")

@WebFilter(filterName = "CharacterEncodingFilter", urlPatterns = "/*")
public class CharacterEncodingFilter implements Filter {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req = (HttpServletRequest) request;
		req.setCharacterEncoding("UTF-8");
		HttpServletResponse res = (HttpServletResponse) response;
		res.setContentType("text/html;charset=UTF-8");
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

}

为什么doFilter使用的是ServletRequest而不是HttpServletRequest?
过滤器过滤的不是只有web页面的请求和响应,同时也需要过滤其他类型的请求和响应,其中涉及J2EE的底层机制;
ServletRequest接口是所有类型请求的最顶层的接口,包含了所有请求接口的通用方法;
HttpServletRequest接口是其中的一个子接口,扩展定义自己的方法,是针对Http协议进行定义;
RequestFacade类是tomcat服务器针对HttpServletRequest接口的实现类,如果使用别的web服务器,实现类也就不是RequestFacade了;
J2EE是定制者,定制所有的接口,而实现类都是由三方厂商自己定制,此处servlet-api.jar就是J2EE的规范,catalina.jar是由Tomcat提供的实现类;响应接口同理.

在这里插入图片描述

2-3 过滤器参数化
过滤器参数化
◆ 过滤器为了增强灵活性,允许配置信息放在web.xml
◆ 在web.xml中配置<init-param>设置过滤器参数
①web.xml中配置<init-param>

 <!-- filter标签用于说明哪个类是过滤器,并在应用启动时自动加载 -->
  <filter>
	  	<filter-name>CharacterEncodingFilter</filter-name>
	  	<filter-class>com.imooc.filter.CharacterEncodingFilter</filter-class>
	  	<init-param>
		  		<param-name>encoding</param-name>
		  		<param-value>GBK</param-value>
	  	</init-param>
	  	<init-param>
		  		<param-name>p1</param-name>
		  		<param-value>v1</param-value>
	  	</init-param>
	  	<init-param>
		  		<param-name>p2</param-name>
		  		<param-value>v2</param-value>
	  	</init-param>
  </filter> 
  <filter-mapping>
  		<filter-name>CharacterEncodingFilter</filter-name>
  		<url-pattern>/*</url-pattern>
  </filter-mapping> 
public class CharacterEncodingFilter implements Filter {
	private String encoding;
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		encoding=filterConfig.getInitParameter("encoding");
		System.out.println("encoding:"+encoding);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req = (HttpServletRequest)request;
		req.setCharacterEncoding(encoding);
		HttpServletResponse res = (HttpServletResponse)response;
		res.setContentType("text/html;charset=" + encoding);
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}

①注解

@WebFilter(filterName="CharacterEncodingFilter",urlPatterns="/*",
	initParams= {
			@WebInitParam(name="encoding" , value="GBK"),
			@WebInitParam(name="p1" , value="v1"),
			@WebInitParam(name="p2" , value="v2")
	})
public class CharacterEncodingFilter implements Filter {
	private String encoding;
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		encoding=filterConfig.getInitParameter("encoding");
		System.out.println("encoding:"+encoding);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req = (HttpServletRequest)request;
		req.setCharacterEncoding(encoding);
		HttpServletResponse res = (HttpServletResponse)response;
		res.setContentType("text/html;charset=" + encoding);
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}

2-4 UrlPattern设置过滤范围
url-pattern常用写法
/index.jsp- 执行资源精准匹配
/servlet/*-以前缀进行模糊匹配
*.jsp-以后缀进行模糊匹配

映射的问题
/指映射Web应用根路径,且只对Servlet生效
◆ 默认首页index.jsp会让 /失效
//*含义不同,前者指向根路径,后者代表所有
①配置

  <filter>
	    <filter-name>UrlPatternFilter</filter-name>
	    <filter-class>com.imooc.filter.UrlPatternFilter</filter-class>
  </filter>
  <filter-mapping>
	    <filter-name>UrlPatternFilter</filter-name>
	    <url-pattern>/</url-pattern>
  </filter-mapping>
  <filter-mapping>
	    <filter-name>UrlPatternFilter</filter-name>
	    <url-pattern>/servlet/*</url-pattern>
  </filter-mapping>
  <filter-mapping>
	    <filter-name>UrlPatternFilter</filter-name>
	    <url-pattern>*.jsp</url-pattern>
  </filter-mapping>

②注解

@WebFilter(filterName="UrlPatternFilter" , urlPatterns= {
		"/",
		"/servlet/*",
		"*.jsp"
})

2-5 过滤链
过滤器开发注意事项
◆ 每一个过滤器应具有单独的职能
◆ 过滤器的执行顺序以为准
◆ 调用chain.doFilter() 将请求向后传递

过滤链是双向的,响应返回时按逆序通过过滤链
以注解形式设置过滤器时,过滤器执行顺序按过滤器类名的字母顺序进行,比如:XXa,XXb,XXc

第3章 案例应用

3-1 多端设备自动适配

@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req = (HttpServletRequest)request;
		HttpServletResponse res = (HttpServletResponse)response;
		/*
		 /index.html
		 PC: /desktop/index.html
		 MOBILE: /mobile/index.html
		 /test.html
		 PC: /desktop/test.html
		 MOBILE: /mobile/test.html
		 */
		String uri = req.getRequestURI();
		System.out.println("URI:" + uri);
		if(uri.startsWith("/desktop") || uri.startsWith("/mobile")) {
			chain.doFilter(request, response);
		}else {
			String userAgent = req.getHeader("user-agent").toLowerCase();
			String targetURI="";
			if(userAgent.indexOf("android")!=-1 || userAgent.indexOf("iphone") != -1) {
				targetURI = "/mobile" + uri;
				System.out.println("移动端设备正在访问,重新跳转URI:" + targetURI);
				res.sendRedirect(targetURI);
			}else {
				targetURI = "/desktop" + uri;
				System.out.println("PC端设备正在访问,重新跳转URI:" + targetURI);
				res.sendRedirect(targetURI);
			}
		}
	}
  <filter>
  	<filter-name>DeviceAdapterFilter</filter-name>
  	<filter-class>com.imooc.filter.DeviceAdapterFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>DeviceAdapterFilter</filter-name>
  	<url-pattern>*.html</url-pattern>
  </filter-mapping>

笔记跟源码来源:慕课网,Java实战课程 链接: 慕课网.


版权声明:本文为zsnandzmn原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。