使用拦截器(intercept)和AOP写操作日志-springboot
来源:互联网 发布:linux终端选项 编辑:程序博客网 时间:2024/05/17 23:39
写用户的操作日志,使用拦截器还是使用aop的方式呢?纠结了好久,
先是使用拦截器的方式,写了一半,发现好多参数没法获取,感觉比较麻烦。
后来又换做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. 注册拦截器
@Configurationpublic 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@Componentpublic 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; } .....}
阅读全文
1 0
- 使用拦截器(intercept)和AOP写操作日志-springboot
- SpringBoot intercept拦截器中获取JPA数据库操作实例
- SpringBoot AOP 拦截器 Aspect
- SpringBoot使用自定义注解+拦截器 实现日志记录
- springboot使用拦截器
- Spring Aop 日志拦截器
- springboot-aop访问拦截
- 过滤器(filter)和拦截器(intercept)的区别
- springboot 实现拦截器权限过滤,以及用拦截器实现操作日志功能
- springboot 实现拦截器权限过滤,以及用拦截器实现操作日志功能(二)
- springboot学习(7)springboot使用AOP打印日志信息
- SpringBoot拦截器的使用
- SpringBoot拦截器的使用
- Springboot 自定义注解 AOP切面获取操作日志
- Spring AOP 日志拦截器的事务管理
- 日志AOP拦截Controller
- AOP实现日志拦截
- Java自定义注解 和 springMVC拦截器 配合使用记录系统操作日志的案例
- 添加白名单功能
- php设计模式_简单工厂
- vue响应式原理
- 百度Web生态开花结果:Lavas等多项新技术帮助开发者效率提升
- mac下解决mysql5.7 Plugin 'mysql_native_plugin' is not loaded错误
- 使用拦截器(intercept)和AOP写操作日志-springboot
- 数据结构 资料
- Github:在Github上创建自己的代码仓库
- CString与LPCWSTR、LPSTR、char*、LPWSTR等类型的转换【转】
- epoll详解【转】
- 系统操作指令汇总(运行->输入指令)
- Java Rasp技术浅析
- python中类的命名空间和面向对象的诸多问题
- linux批量添加用户shell并随机生成用户密码