Filter过滤器(拦截器)实现AOP思想

本文介绍如何通过Filter过滤器实现AOP(面向切面编程)的思想。主要步骤包括实现Filter接口、覆写doFilter方法及在web.xml中配置过滤器。提供了一个具体的字符编码过滤器示例。

Filter过滤器(拦截器)实现AOP思想

   Filter过滤器(拦截器)的使用是声明试的。即只需在web.xml配置文件中做简单的声明就Filter就能发挥作用。

实现过滤器简单的三个步骤就能实现:

1)写一个类实现Filter接口(javax.servlet.Filter);

2)覆写doFilter()方法;

3)在web.xml中配置,过滤器的作用范围。

 

关键代码:第(1)、(2)步在java类中进行:

	package com.bjpowernode.drp.util.filter;
	
	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.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	
	public class TestFilter implements Filter {
		/**
		 * 初始化时执行此方法
		 */
		@Override
		public void init(FilterConfig arg0) throws ServletException {
			/**
			 *  初始化加载时执行:—————可不实现
			 *  	可通过传入的参数(FilterConfig的对象)获取web.xml中约定俗成的配置内容。
			 *  	所谓约定俗成是指,读取的内容,是在web.xml特定标签【是按规范来的】中的内容。
			 */
		}
		
		@Override
		public void doFilter(ServletRequest arg0, ServletResponse arg1,
				FilterChain arg2) throws IOException, ServletException {
			
			/**
			 * 因为需要用到 扩展类————HttpServletRequest的一些扩展方法;
			 * 同样地,也会用到 扩展类————HttpServletResponse的一些扩展方法。
			 * 因而,需要做如下转化:
			 */
			// 将 父类ServletRequest强制转化为子类HttpServletRequest
			HttpServletRequest request = (HttpServletRequest)arg0;
			// 将 父类ServletResponse强制转化为子类HttpServletResponse
			HttpServletResponse response = (HttpServletResponse)arg1;
			
			// 执行目标内容前执行
			System.out.println("TestFilter------>>begin");
			
			/**
			 * 在这个位置,可以添加,该过滤器想要实现的过滤效果。比如:设置字符编码、错误转接等
			 */
			
			// 执行目标方法
			arg2.doFilter(request, response);
			
			// 执行完目标后,回来执行
			System.out.println("TestFilter------>end");
			
			// 按request中指定的url,转发
	        request.getRequestDispatcher(request.getContextPath()).forward(request, response);
		}
		
		@Override
		public void destroy() {
			// 销毁时(退出时)执行————可不实现
		}
	
	}


实现步骤(3),web.xml做如下配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name></display-name>
  
  <!-- filter过滤器 -->
  <filter>
  	<filter-name>TestFilter</filter-name>
  	<filter-class>com.bjpowernode.drp.util.filter.TestFilter</filter-class>
  </filter>
    <filter-mapping>
  	<filter-name>TestFilter</filter-name>
  	<url-pattern>/servlet/*</url-pattern>
  </filter-mapping>
</web-app>

仅仅只需如此,过滤器的功能就能实现了,就是如此简单。


下面是一个完整的实例:本实例完成了url路径的编码、字符编码

dofilter实现类:

package com.bjpowernode.drp.util.filter;

import java.io.IOException;
import java.net.URLDecoder;

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.http.HttpServletRequest;

public class CharsetEncodingFilter implements Filter {
	// 在程序中,预留一个默认的编码方式GB18030
    public final static String DEFAULT_URI_ENCODE = "GB18030";
    
    private FilterConfig filterConfig = null;
	private String encoding;

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		// 设置字符集
		// 将读出的 参数 设置到过滤器
		request.setCharacterEncoding(encoding);

        String uri = ((HttpServletRequest) request).getRequestURI();
        // 对uri进行 编码
        String ch = URLDecoder.decode(uri, encoding);
        
		// 继续执行
		// chain.doFilter(req, resp);
        if(uri.equals(ch)) {
            chain.doFilter(req, resp);
            return;
        }
        
        // 读取request中的链接地址
        ch = ch.substring(request.getContextPath().length());
        
        // 按request中指定的url,转发
        filterConfig.getServletContext().getRequestDispatcher(ch).forward(req, resp);
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
		// 读取web.xml配置文件中 设置的过滤器参数
		this.encoding = filterConfig.getInitParameter("set_encoding");
		if(this.encoding == null) {
			this.encoding = DEFAULT_URI_ENCODE;
		}
	}
	
	@Override
	public void destroy() {
		// 销毁————可不实现
	}

}

web.xml中的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name></display-name>
  <!-- 默认主页列表
  		* 地址栏输入“http://localhost/”,访问自动添加<welcome-file>标签内指定的页面,
  			根据配置时的顺序查找相应的文件,找到即去到该页面
   -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>

  <!-- filter过滤器
  			* filter-name:过滤器的名称(一般以过滤器类名充当,任意名称皆可)
  			* fliter-class:过滤类的路径
  			* init-param:参数
  				· param-name:参数名
  				· param-value:参数值
   -->
  <filter>
  	<filter-name>CharsetEncodingFilter</filter-name>
  	<filter-class>com.bjpowernode.drp.util.filter.CharsetEncodingFilter</filter-class>
  	<init-param>
  		<param-name>set_encoding</param-name>
  		<param-value>GB18030</param-value>
  	</init-param>
  </filter>
  
 </web-app>
完美结束!

<think>首先,用户的问题是关于过滤器拦截器AOP拦截的区别和应用场景。我需要基于系统级指令来构建回答。 系统级指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,保证回答真实可靠。 用户的问题:理解过滤器拦截器AOP拦截的区别和应用场景。具体是“过滤器 拦截器 AOP拦截 区别 应用场景”。 参考站内引用: - 引用[1]:讨论了过滤器拦截器AOP的区别,强调它们拦截的对象不同(URL vs. 类的元数据),功能不同(过滤器在请求到达时执行,拦截器有更细的钩子,AOP更复杂)。 - 引用[2]:在Spring框架中,这些技术用于横切关注点处理。 - 引用[3]:AOP用于更细粒度的控制,如动态数据源场景。 我的回答需要结构化: 1. **逐步解释**:先定义每个概念,然后比较区别,最后讨论应用场景。 2. **使用中文**。 3. **生成相关问题**:在回答末尾添加相关问题。 4. **引用标识**:在引用内容末尾添加[^1]、[^2]等。 内容大纲: - **介绍**:简要说明过滤器拦截器AOP在Web开发中的作用。 - **详细解释每个**: - **过滤器(Filter)**:基于Servlet规范,拦截HTTP请求和响应。应用场景如日志记录、安全过滤。 - **拦截器(Interceptor)**:在Spring MVC中,拦截请求处理过程,提供更细的控制(如preHandle, postHandle)。应用场景如权限检查、事务管理。 - **AOP拦截**:面向切面编程,拦截方法调用,基于类的元数据。应用场景如日志、事务、性能监控。 - **比较区别**: - 拦截对象:过滤器拦截URL,拦截器拦截请求处理链,AOP拦截方法调用。 - 粒度:过滤器粗粒度,拦截器中等,AOP细粒度。 - 执行顺序:在Spring中,过滤器 -> 拦截器 -> AOP。 - 功能:AOP更灵活,支持复杂的业务逻辑。 - **应用场景总结**: - 过滤器:全局请求处理,如编码设置、安全过滤。 - 拦截器:请求级别的控制,如登录验证。 - AOP:方法级别的横切关注点,如事务管理、日志。 - **生成相关问题**:基于主题,创建2-3个问题。 引用处理: - 在回答中,当引用参考内容时,添加引用标识。例如,提到执行顺序时引用[^1],提到AOP的细粒度时引用[^3]。 确保LaTeX正确:用户问题中没有数学内容,但指令要求所有行内数学表达式用$...$。既然主题是编程,可能没有数学表达式,但如果有,比如提到算法复杂度,可以用。但在这个上下文中,可能不需要。 最终回答结构: 1. **引言**:解释问题的重要性。 2. **定义和区别**:分点解释。 3. **应用场景**:列出每个的应用。 4. **总结**:简要对比。 5. **相关问题**:生成相关问题。</think>### 过滤器拦截器AOP拦截的区别与应用场景 在Web开发中,过滤器Filter)、拦截器(Interceptor)和AOP(面向切面编程)拦截都是处理横切关注点(cross-cutting concerns)的技术,例如日志记录、安全验证或性能监控。它们虽然功能相似,但在拦截粒度、执行顺序和应用场景上有显著差异。下面我将逐步解释它们的定义、区别和典型应用场景,帮助您清晰理解。 #### 1. **定义与核心概念** - **过滤器Filter)**:基于Servlet规范实现,工作在Web容器层面,拦截HTTP请求和响应。它在请求到达Servlet前执行,并在响应返回客户端前处理。过滤器只关注URL路径,不涉及具体业务逻辑的执行时机(例如,无法在业务方法执行前后插入逻辑)[^1]。 - 示例场景:设置全局字符编码、过滤恶意请求。 - 代码示意(Java Servlet): ```java public class EncodingFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { request.setCharacterEncoding("UTF-8"); chain.doFilter(request, response); // 继续执行后续过滤器或Servlet } } ``` - **拦截器(Interceptor)**:在Spring框架中实现,工作在MVC层面,拦截请求处理链。它提供更细粒度的钩子方法(如`preHandle`、`postHandle`和`afterCompletion`),能在Controller方法执行前后插入逻辑。拦截器基于URL和请求上下文,但比过滤器更贴近业务层[^1][^2]。 - 示例场景:用户登录验证、请求日志记录。 - 代码示意(Spring Interceptor): ```java public class AuthInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if (!checkLogin(request)) { response.sendRedirect("/login"); return false; // 中断请求 } return true; // 继续执行Controller } } ``` - **AOP拦截(Aspect-Oriented Programming)**:基于Spring AOP或AspectJ实现,工作在应用代码层面,拦截方法调用。它利用“切面”定义,基于类的元数据(如包名、类名、方法签名)进行拦截,支持在方法执行前、后或异常时插入逻辑。AOP的粒度最细,能处理复杂业务逻辑[^1][^3]。 - 示例场景:事务管理、性能监控、自定义注解处理。 - 代码示意(Spring AOP): ```java @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("方法执行前: " + joinPoint.getSignature()); } } ``` #### 2. **关键区别对比** 下面表格总结了核心区别(基于Spring框架的典型实现): | 特性 | 过滤器Filter) | 拦截器(Interceptor) | AOP拦截(AOP) | |--------------|-----------------------------------|-----------------------------------|-------------------------------------| | **拦截对象** | URL路径(HTTP请求/响应) | 请求处理链(Controller上下文) | 类的元数据(方法、参数等) | | **粒度** | 粗粒度:仅处理请求到达和响应返回 | 中等粒度:支持pre/post/after钩子 | 细粒度:精确到方法级别,支持环绕通知 | | **执行顺序** | 最先执行(在拦截器前) | 其次执行(在过滤器后,AOP前) | 最后执行(在拦截器后) | | **功能范围** | 简单:无业务逻辑上下文,仅过滤请求 | 中等:可访问请求参数,但受限 | 复杂:支持异常处理、自定义注解等 | | **依赖框架** | Servlet容器(如Tomcat) | Spring MVC | Spring AOP或AspectJ | - **执行顺序详解**:在Spring应用中,一个请求的处理流程为:过滤器拦截器AOP。这意味着过滤器先处理原始请求,拦截器在Controller执行前后介入,最后AOP在方法调用层面切入[^1][^3]。 - **为什么AOP更灵活**:AOP能拦截任意方法(包括Service层),而过滤器拦截器仅限于Web请求。例如,动态数据源切换需要方法级别的控制,只能用AOP实现[^3]。 #### 3. **应用场景总结** 根据实际需求选择合适的技术: - **过滤器的应用场景**: - 全局请求处理:如字符编码设置、跨域(CORS)处理。 - 安全防护:如XSS攻击过滤、IP黑名单拦截。 - 资源压缩:如Gzip压缩响应内容。 - 原因:过滤器在请求最外层,适合简单、高效的URL级操作[^1][^2]。 - **拦截器的应用场景**: - 请求验证:如用户权限检查、API令牌验证。 - 日志记录:记录请求耗时、参数信息。 - 事务预处理:在Controller前开启事务(但提交通常在AOP处理)。 - 原因:拦截器能访问HttpServletRequest对象,适合基于会话或请求上下文的逻辑[^1][^2]。 - **AOP拦截的应用场景**: - 业务逻辑增强:如事务管理(@Transactional)、缓存处理。 - 性能监控:统计方法执行时间。 - 异常处理:统一捕获并处理服务层异常。 - 自定义注解:实现如@Log、@Retry等注解驱动逻辑。 - 原因:AOP基于方法签名,能深入业务代码,支持复杂切面逻辑[^1][^3]。 #### 4. **总结** 过滤器拦截器AOP拦截各有所长:过滤器适合Web层基础过滤,拦截器处理请求级业务钩子,AOP则用于细粒度的方法拦截。在实际项目中,它们常结合使用——例如,用过滤器处理安全,拦截器处理认证,AOP管理事务。选择时需考虑拦截粒度、执行顺序和框架支持[^1][^2][^3]。 如果您有具体框架(如Spring Boot)的示例需求,我可以进一步提供代码演示。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值