Struts 1与Spring整合及Spring AOP+AspectJ实现方法拦截审计
我之前刚好搞定过Struts 1 + Spring整合并通过AspectJ实现无侵入式审计的需求,给你一步步梳理操作细节,全程不用改原有业务类,放心跟着来:
第一步:完成Struts 1与Spring的整合
这是实现AOP的基础,核心是让Spring接管Struts的Action实例,同时加载Spring上下文。
1.1 配置web.xml
替换原生Struts的ActionServlet为Spring提供的代理类,同时添加Spring上下文加载监听器:
<!-- Spring上下文配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Struts 1 代理ActionServlet配置 --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.springframework.web.struts.DelegatingActionProxy</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
关键说明:DelegatingActionProxy会把Action的创建权交给Spring,这样Spring才能对Action或其依赖的业务类做AOP增强。
1.2 配置struts-config.xml
指定Spring的请求处理器,同时修改Action的type属性为Spring容器中bean的ID(不再是全类名):
<struts-config> <!-- 启用Spring请求处理器,让Spring接管Action调用 --> <controller> <set-property property="processorClass" value="org.springframework.web.struts.SpringRequestProcessor"/> </controller> <!-- 示例Action配置:type对应Spring中bean的id --> <action-mappings> <action path="/user/save" type="userSaveAction" name="userForm" scope="request"> <forward name="success" path="/user/list.do"/> </action> </action-mappings> </struts-config>
1.3 配置applicationContext.xml
开启组件扫描、AOP自动代理,并注册Action和业务类的bean:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 扫描业务层、Action包,自动注册带有@Component/@Service/@Controller注解的类 --> <context:component-scan base-package="com.yourcompany.service, com.yourcompany.action"/> <!-- 开启AspectJ注解驱动的AOP自动代理 --> <aop:aspectj-autoproxy/> <!-- 示例Action bean(如果不用@Component注解,就手动注册) --> <bean id="userSaveAction" class="com.yourcompany.action.UserSaveAction"> <property name="userService" ref="userService"/> </bean> <!-- 示例业务层bean --> <bean id="userService" class="com.yourcompany.service.impl.UserServiceImpl"/> </beans>
第二步:实现AspectJ审计切面
编写一个切面类,用注解定义切点和通知,完全无侵入式拦截方法调用:
package com.yourcompany.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import java.util.Date; @Aspect @Component // 让Spring扫描并管理这个切面类 public class AuditAspect { // 定义切点:拦截业务层所有方法(可根据需求调整表达式) @Pointcut("execution(* com.yourcompany.service.*.*(..))") public void serviceMethodPointcut() {} // 后置通知:方法执行成功后记录审计日志 @AfterReturning(pointcut = "serviceMethodPointcut()", returning = "result") public void logSuccessAudit(JoinPoint joinPoint, Object result) { String className = joinPoint.getTarget().getClass().getSimpleName(); String methodName = joinPoint.getSignature().getName(); Object[] params = joinPoint.getArgs(); // 这里替换为你的实际审计逻辑:比如写入数据库、调用日志服务等 System.out.println(String.format("[%s] 审计记录:类%s的方法%s执行成功,参数:%s,返回结果:%s", new Date(), className, methodName, params, result)); } // 异常通知:方法抛出异常时记录错误审计 @AfterReturning(pointcut = "serviceMethodPointcut()", throwing = "ex") public void logErrorAudit(JoinPoint joinPoint, Exception ex) { String className = joinPoint.getTarget().getClass().getSimpleName(); String methodName = joinPoint.getSignature().getName(); System.out.println(String.format("[%s] 错误审计记录:类%s的方法%s执行失败,异常信息:%s", new Date(), className, methodName, ex.getMessage())); } }
关键说明:@Pointcut的表达式可以灵活调整,比如只拦截save/update开头的方法:execution(* com.yourcompany.service.*.save*(..)),或者拦截带有自定义@Audit注解的方法。
第三步:准备依赖包
如果用Maven,确保引入以下核心依赖(版本可根据项目兼容性调整):
<!-- Spring核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> <!-- Struts1与Spring整合依赖 --> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts-core</artifactId> <version>1.3.10</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts-spring</artifactId> <version>1.3.10</version> </dependency>
关键说明:struts-spring是Struts1和Spring整合的桥梁,必须引入,它提供了我们之前用到的DelegatingActionProxy等类。
注意事项
- 确保所有需要被AOP拦截的类(业务类、Action)都由Spring管理,要么用注解,要么手动注册到
applicationContext.xml。 - 如果需要拦截Struts的Action方法,只需要调整
@Pointcut的表达式,比如execution(* com.yourcompany.action.*.*(..))。 - 审计日志的实现建议异步处理,避免影响主业务流程,比如用Spring的
@Async注解或者消息队列。
内容的提问来源于stack exchange,提问作者KESO
相关产品推荐
相关产品推荐

