spring aop的案例(一)日志拦截
来源:互联网 发布:d3.js官网下载 编辑:程序博客网 时间:2024/04/30 08:34
日志拦截,一般主要在service和action进行日志拦截。这里我们直接讲用法,至于原理就不做具体讲解。
我们使用spring+spring mvc架构项目
aplicationContext-common.xml:
<context:component-scan base-package="com.tonghui.thcws"> <!--删除controller注解扫描--> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /></context:component-scan> <!-- 启动对@AspectJ注解的支持 --> <aop:aspectj-autoproxy/> <!--事务注解--><tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
applicationContext-mvc.xml:
<context:component-scan base-package="com.tonghui.thcws.web.controller"> <!--只扫描controller注解--> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
Log注解声明:SystemLogAspect.java
import java.lang.reflect.Method;import java.util.Date;import javax.servlet.http.HttpServletRequest;import org.apache.shiro.SecurityUtils;import org.apache.shiro.subject.Subject;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import com.tonghui.cws.vo.Principal;import com.tonghui.thcws.model.SysLog;import com.tonghui.thcws.service.SysLogService;/** * 切点类 * * @author 崔金睿 * @since 2015年6月24日 10:17:51 * @version 1.0 */@Aspect@Componentpublic class SystemLogAspect { // 注入Service用于把日志保存数据库 @Autowired private SysLogService logService; // 本地异常日志记录对象 private static final Logger logger = LoggerFactory .getLogger(SystemLogAspect.class); // Service层切点 @Pointcut("@annotation(SystemServiceLog)") public void serviceAspect() { } // Controller层切点 @Pointcut("@annotation(SystemControllerLog)") public void controllerAspect() { } private String getUser() { Subject subject = SecurityUtils.getSubject(); Principal principal= (Principal) subject.getPrincipal(); return principal==null?"未登录用户":principal.getUsername(); } /** * 前置通知 用于拦截Controller层记录用户的操作 * * @param joinPoint * 切点 */ @After("controllerAspect()") public void doAfter(JoinPoint joinPoint) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder .getRequestAttributes()).getRequest(); // 请求的IP String ip = request.getRemoteAddr(); // 获取用户请求方法的参数并序列化为JSON格式字符串 StringBuffer params = new StringBuffer(); if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) { params.append("["); for (int i = 0; i < joinPoint.getArgs().length; i++) { params.append(joinPoint.getArgs()[i]); params.append(","); } params.deleteCharAt(params.length()-1); params.append("]"); } try { // *========数据库日志=========*// SysLog log = new SysLog(); log.setType("0");// 0录用户的操作日志 1为异常日志 log.setCreateBy(getUser()); log.setCreateDate(new Date()); log.setRemoteAddr(ip); log.setUserAgent(request.getHeader("User-Agent")); log.setRequestUri(request.getRequestURI()); log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); log.setDescription(getControllerMethodDescription(joinPoint)); // 参数 log.setParams(params.toString()); log.setExceptionCode(null); log.setExceptionDetail(null); // 保存数据库 logService.addLog(log); } catch (Exception e) { // 记录本地异常日志 logger.error("==前置通知异常=="); logger.error("异常信息:{}", e.getMessage()); } } /** * 异常通知 用于拦截serviceAspect层记录异常日志 * * @param joinPoint * @param e */ @AfterThrowing(pointcut = "serviceAspect()", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Throwable e) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder .getRequestAttributes()).getRequest(); // 获取请求ip String ip = request.getRemoteAddr(); // 获取用户请求方法的参数并序列化为JSON格式字符串 StringBuffer params = new StringBuffer(); if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) { params.append("["); for (int i = 0; i < joinPoint.getArgs().length; i++) { params.append(joinPoint.getArgs()[i]); params.append(","); } params.deleteCharAt(params.length()-1); params.append("]"); } try { // *========数据库日志=========*// SysLog log = new SysLog(); log.setType("1");// 0录用户的操作日志 1为异常日志 log.setCreateBy(getUser()); log.setCreateDate(new Date()); log.setRemoteAddr(ip); log.setUserAgent(request.getHeader("User-Agent")); log.setRequestUri(request.getRequestURI()); log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); log.setDescription(getControllerMethodDescription(joinPoint)); // 参数 log.setParams(params.toString()); log.setExceptionCode(e.getClass().getName()); log.setExceptionDetail(e.getMessage()); // 保存数据库 logService.addLog(log); } catch (Exception ex) { // 记录本地异常日志 logger.error("==异常通知异常=="); logger.error("异常信息:{}", ex.getMessage()); } /* ==========记录本地异常日志========== */ logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget() .getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params); } /** * 获取注解中对方法的描述信息 用于service层注解 * * @param joinPoint * 切点 * @return 方法描述 * @throws Exception */ @Deprecated public static String getServiceMthodDescription(JoinPoint joinPoint) throws Exception { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); String description = ""; for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { description = method.getAnnotation(SystemServiceLog.class) .description(); break; } } } return description; } /** * 获取注解中对方法的描述信息 用于Controller层注解 * * @param joinPoint * 切点 * @return 方法描述 * @throws Exception */ public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); String description = ""; for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { description = method.getAnnotation( SystemControllerLog.class).description(); break; } } } return description; }}
Controller日志拦截注解类:SystemControllerLog.java
import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** *自定义注解 拦截Controller */ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documentedpublic @interface SystemControllerLog { String description() default "";}
Service异常日志拦截注解类:SystemServiceLog.java
import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** *自定义注解 拦截Service */ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documentedpublic @interface SystemServiceLog { String description() default "";}
如何使用?
Controller:
@SystemControllerLog(description ="账户启用账户")@RequestMapping(value ="/accountStart",method=RequestMethod.POST)@ResponseBodypublic JsonVO accountStart(Long id){ JsonVO j = new JsonVO(); try { accountService.accountEnable(id); j.setStatus(CwsConstants.STATUS_SUCCESS); j.setMessage("启停成功!"); } catch (Exception e) { j.setMessage("账户启用失败!"); j.setStatus(CwsConstants.STATUS_ERROR); logger.error("账户启用失败",e.getMessage()); } return j;}
Service:
@SystemServiceLog(description="保存账户发生异常")@Transactionalpublic void save(CwsAccount entity) throws Exception{ try { sqlSession.insert(DOMAIN_NAME+".insertSelective",entity); } catch (Exception e) { e.printStackTrace(); throw e; }}
使用的过程中会发现,service捕捉异常的时候会出现事务回滚的现象,为什么?如何解决?
原因是因为aop的先后顺序导致,刚刚写入数据库就被事务拦截后并发生异常则回滚操作了。
<!--事务注解--><tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="2" />
这样就实现了我们自己写的aop在事务介入之前就执行了!
1 0
- spring aop的案例(一)日志拦截
- Spring AOP 日志拦截器的事务管理
- Spring Aop 日志拦截器
- Spring Aop 日志拦截应用
- spring aop 拦截实现日志管理
- spring AOP的异常拦截
- spring AOP的异常拦截
- spring AOP的异常拦截
- spring AOP的异常拦截
- spring的aop拦截器
- spring AOP的异常拦截
- Spring的AOP(一):什么是AOP
- spring的aop实现案例
- Spring模拟aop静态代理案例<一>
- 为struts的action添加到SPRING的AOP日志拦截器
- 为struts的action添加到SPRING的AOP日志拦截器
- 为struts的action添加到SPRING的AOP日志拦截器
- Spring AOP拦截Service实现日志管理(自定义注解的方式)
- POJ 2718Smallest Difference(DFS)
- mybatis在xml文件中处理大于号小于号的方法
- 按钮背景图片 大小 和 位置 设置。
- 全局404定义
- Linux的用户和用户组管理
- spring aop的案例(一)日志拦截
- 洛谷P1012 拼数
- 常用链接
- 服务器配置(建站助手),使用MSFTP服务器FTP无法连接解决方法
- Spring+SpringMVC+mybatis+easyui整合实例-----spring mvc整合及mybatis事务部分
- 实战分析一个性能问题
- 在android的service中启动一个通知,点击通知无法启动activity,报一个SecurityException异常
- 基于directshow技术实现的录音程序
- swift 初级 第一个程序 HollowWorld