使用拦截器(intercept)和AOP写操作日志-springboot
2017-07-11 18:52
501 查看
写用户的操作日志,使用拦截器还是使用aop的方式呢?纠结了好久,
先是使用拦截器的方式,写了一半,发现好多参数没法获取,感觉比较麻烦。
后来又换做aop的方式。再后来,发现两种方式其实都可以。对于一些
自定义的参数,可以写一个注解来解决。
以下是两种方式的总结:
拦截器的执行顺序,这里不解释了。这里注意mapper类是如何创建的。
2. 注册拦截器
LoggerUtil类
loggerUtil类主要返回一个Log对象的实体类。
LogAopAction类
我们可以将切入方法设置到自定义的log注解上,这样aop就会只在有log注解的方法进行拦截了。
特殊字段的注解
引用部分
先是使用拦截器的方式,写了一半,发现好多参数没法获取,感觉比较麻烦。
后来又换做aop的方式。再后来,发现两种方式其实都可以。对于一些
自定义的参数,可以写一个注解来解决。
以下是两种方式的总结:
日志拦截器方法
1.创建拦截器类public class LogInterceptor implements HandlerInterceptor { private final Logger logger = LoggerFactory.getLogger(LogInterceptor.class); @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //把整个log中的参数,交给logUtil来获取,并返回log对象 Log log = null; try { log = LoggerUtil.getLog(httpServletRequest); }catch (GeneralException g){ logger.warn("logger",g.getMessage()); }catch (Exception e){ logger.error("logger",e.getMessage()); } httpServletRequest.setAttribute(LoggerUtil.LOG_OPERATE,log); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { //返回视图时,插入操作日志 LogMapper logMapper = getMapper(LogMapper.class,httpServletRequest); Log log = (Log) httpServletRequest.getAttribute(LoggerUtil.LOG_OPERATE); if(log == null){ logger.warn("日志信息为空",log); }else{ logMapper.insert(log); } } private <T> T getMapper(Class<T> clazz,HttpServletRequest request) { BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()); return factory.getBean(clazz); } }
拦截器的执行顺序,这里不解释了。这里注意mapper类是如何创建的。
2. 注册拦截器
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**").excludePathPatterns("/user/login"); registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } }
LoggerUtil类
public class LoggerUtil { public static final String LOG_TARGET_TYPE="targetType"; public static final String LOG_ACTION="action"; public static final String LOG_REMARK="remark"; public LoggerUtil(){} public static Log getLog(HttpServletRequest request){ //1.依次获取每个属性信息 userId,operator,action,remark,ip,targetType Log log = new Log(); log.setIp(LoggerUtil.getCliectIp(request)); log.setOperator("operator"); log.setUserId(1); log.setAction("create"); log.setCustomerId("0000-1111"); log.setTargetType("message"); log.setRemark("消息发布"); return log; } /** * 获取客户端ip地址 * @param request * @return */ public static String getCliectIp(HttpServletRequest request){ String ip = request.getHeader("X-Real-IP"); if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { return ip; } ip = request.getHeader("X-Forwarded-For"); if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { // 多次反向代理后会有多个IP值,第一个为真实IP。 int index = ip.indexOf(','); if (index != -1) { return ip.substring(0, index); } else { return ip; } } else { return request.getRemoteAddr(); } } }
loggerUtil类主要返回一个Log对象的实体类。
AOP记录操作日志
引入springboot的aop的jar<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
LogAopAction类
@Aspect @Component public class LogAopAction { private final Logger logger = LoggerFactory.getLogger(LogAopAction.class); @Autowired private LogMapper logMapper; @Pointcut("execution(public * cn.vobile.hss.controller..*(..))") private void pointCutMethod(){} /** * 记录操作日志 */ @After("pointCutMethod()") // 使用上面定义的切入点 public void recordLog(JoinPoint joinPoint){ Long start = System.currentTimeMillis(); Log log = new Log(); HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); User user = (User) request.getSession().getAttribute("user"); if(user == null){ logger.warn("user 信息为空"); }else{ log.setUserId(user.getId()); log.setOperator(user.getUserName()); log.setCustomerId(user.getCustomerId()); } //下面开始获取 ip,targetType,remark,action try { Map<String,String> map = getLogMark(joinPoint); log.setAction(map.get(LoggerUtil.LOG_ACTION)); log.setTargetType(map.get(LoggerUtil.LOG_TARGET_TYPE)); log.setRemark(map.get(LoggerUtil.LOG_REMARK)); log.setIp(LoggerUtil.getCliectIp(request)); logMapper.insert(log); }catch (ClassNotFoundException c){ logger.error(c.getMessage()); }catch (Exception e){ logger.error("插入日志异常",e.getMessage()); } Long end = System.currentTimeMillis(); logger.info("记录日志消耗时间:"+ (end - start) / 1000); } private Map<String,String> getLogMark(JoinPoint joinPoint) throws ClassNotFoundException { Map<String,String> map = new HashMap<>(); String methodName = joinPoint.getSignature().getName(); String targetName = joinPoint.getTarget().getClass().getName(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); for (Method method : methods){ if(method.getName().equals(methodName)){ LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); map.put(LoggerUtil.LOG_TARGET_TYPE,logAnnotation.targetType()); map.put(LoggerUtil.LOG_ACTION,logAnnotation.action()); map.put(LoggerUtil.LOG_REMARK,logAnnotation.remark()); } } return map; } }
2.1 Pointcut优化部分
//切入点设置到自定义的log注解上 @Pointcut("@annotation(cn.vobile.hss.annotation.LogAnnotation)") private void pointCutMethod(){}
我们可以将切入方法设置到自定义的log注解上,这样aop就会只在有log注解的方法进行拦截了。
特殊字段的注解
@Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取 @Target(ElementType.METHOD)//目标是方法 @Documented//文档生成时,该注解将被包含在javadoc中,可去掉 public @interface LogAnnotation { String action() default ""; String targetType() default ""; String remark() default ""; }
引用部分
@LogAnnotation(targetType = "user",action = "create",remark = "用户登录") @RequestMapping(value = "/login",method = RequestMethod.POST) public ModelMap login(HttpServletRequest request){ ModelMapHelper helper = new ModelMapHelper(); String userName = request.getParameter("userName"); String password = request.getParameter("password"); String imgCode = request.getParameter("imageCode"); String sessionCode = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); logger.info("input code is "+imgCode+" session id is "+request.getSession().getId()+" session code is "+sessionCode); if(StringUtils.isEmpty(imgCode)){ helper.setErrorMap("验证码不能为空"); return helper; } ..... }
相关文章推荐
- 使用Spring AOP记录Controller层操作日志
- Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况)
- 使用Aop面向切面技术实现记录详细操作日志功能
- 使用Spring MVC拦截器管理操作日志
- springboot 实现拦截器权限过滤,以及用拦截器实现操作日志功能(二)
- 使用Spring AOP使用注解记录用户操作日志
- Springboot学习-使用AOP统一处理Web请求日志(六)
- SSM使用AOP切面获取用户登录操作日志
- 幸福框架:用户想看到的操作日志也要使用AOP吗?
- 使用structs 的拦截器记录操作日志系统
- Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况,在方法调用前和调用后记录相关日志。)
- Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况,在方法调用前
- springboot 实现拦截器权限过滤,以及用拦截器实现操作日志功能
- Java自定义注解 和 springMVC拦截器 配合使用记录系统操作日志的案例
- 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录
- Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况,在方法调用前和调用后记录相关日志。)
- 使用spring aop + 注解完成对业务操作的日志记录
- SpringBoot实践之(十四)--- AOP拦截器 Aspect的使用
- [EntLib]微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录
- Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况,在方法调用前