package me.zhengjie.common.aop.log;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @author jie
* @date 2018-11-24
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String description() default "";
}
package me.zhengjie.common.aop.log;

import lombok.extern.slf4j.Slf4j;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.monitor.domain.Logging;
import me.zhengjie.monitor.service.LoggingService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.io.PrintWriter;
import java.io.StringWriter; /**
* @author jie
* @date 2018-11-24
*/
@Component
@Aspect
@Slf4j
public class LogAspect { @Autowired
private LoggingService loggingService; private long currentTime = 0L; /**
* 配置切入点
*/
@Pointcut("@annotation(me.zhengjie.common.aop.log.Log)")
public void logPointcut() {
// 该方法无方法体,主要为了让同类中其他方法使用此切入点
} /**
* 配置环绕通知,使用在方法logPointcut()上注册的切入点
*
* @param joinPoint join point for advice
*/
@Around("logPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint){
Object result = null;
currentTime = System.currentTimeMillis();
try {
result = joinPoint.proceed();
} catch (Throwable e) {
throw new BadRequestException(e.getMessage());
}
Logging logging = new Logging("INFO",System.currentTimeMillis() - currentTime);
loggingService.save(joinPoint, logging);
return result;
} /**
* 配置异常通知
*
* @param joinPoint join point for advice
* @param e exception
*/
@AfterThrowing(pointcut = "logPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
Logging logging = new Logging("ERROR",System.currentTimeMillis() - currentTime);
logging.setExceptionDetail(e.getMessage());
loggingService.save((ProceedingJoinPoint)joinPoint, logging);
}
}
package me.zhengjie.monitor.service;

import me.zhengjie.monitor.domain.Logging;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.scheduling.annotation.Async; /**
* @author jie
* @date 2018-11-24
*/
public interface LoggingService { /**
* 新增日志
* @param joinPoint
* @param logging
*/
@Async
void save(ProceedingJoinPoint joinPoint, Logging logging);
}
package me.zhengjie.monitor.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import me.zhengjie.common.utils.IpUtil;
import me.zhengjie.common.utils.RequestHolder;
import me.zhengjie.core.security.AuthorizationUser;
import me.zhengjie.core.utils.JwtTokenUtil;
import me.zhengjie.monitor.domain.Logging;
import me.zhengjie.monitor.repository.LoggingRepository;
import me.zhengjie.monitor.service.LoggingService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method; /**
* @author jie
* @date 2018-11-24
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class LoggingServiceImpl implements LoggingService { @Autowired
private LoggingRepository loggingRepository; @Value("${jwt.header}")
private String tokenHeader; @Autowired
private JwtTokenUtil jwtTokenUtil; private final String LOGINPATH = "authenticationLogin"; @Override
@Transactional(rollbackFor = Exception.class)
public void save(ProceedingJoinPoint joinPoint, Logging logging){ // 获取request
HttpServletRequest request = RequestHolder.getHttpServletRequest();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
me.zhengjie.common.aop.log.Log log = method.getAnnotation(me.zhengjie.common.aop.log.Log.class); // 描述
if (log != null) {
logging.setDescription(log.description());
} // 方法路径
String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()"; String params = "{";
//参数值
Object[] argValues = joinPoint.getArgs();
//参数名称
String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
// 用户名
String username = ""; if(argValues != null){
for (int i = 0; i < argValues.length; i++) {
params += " " + argNames[i] + ": " + argValues[i];
}
} // 获取IP地址
logging.setRequestIp(IpUtil.getIP(request)); if(!LOGINPATH.equals(signature.getName())){
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
username = userDetails.getUsername();
} else {
AuthorizationUser user = JSONUtil.toBean(new JSONObject(argValues[0]),AuthorizationUser.class);
username = user.getUsername(); }
if (params.length() > 1000){
params = params.substring(0,999);
}
logging.setUsername(username);
logging.setParams(params + " }");
loggingRepository.save(logging);
}
}
package me.zhengjie.monitor.domain;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.sql.Timestamp; /**
* @author jie
* @date 2018-11-24
*/
@Entity
@Data
@Table(name = "log")
@NoArgsConstructor
public class Logging { @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; /**
* 操作用户
*/
private String username; /**
* 描述
*/
private String description; /**
* 方法名
*/
private String method; /**
* 参数
*/
@Column(length = 1500)
private String params; /**
* 日志类型
*/
private String logType; /**
* 请求ip
*/
private String requestIp; /**
* 请求耗时
*/
private Long time; /**
* 异常详细
*/
@Column(length = 1500)
private String exceptionDetail; /**
* 创建日期
*/
@CreationTimestamp
private Timestamp createTime; public Logging(String logType, Long time) {
this.logType = logType;
this.time = time;
}
}
package me.zhengjie.monitor.repository;

import me.zhengjie.monitor.domain.Logging;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import java.util.List; /**
* @author jie
* @date 2018-11-24
*/
@Repository
public interface LoggingRepository extends JpaRepository<Logging,Long>, JpaSpecificationExecutor { /**
* 获取一个时间段的IP记录
* @param date1
* @param date2
* @return
*/
@Query(value = "select count(*) FROM (select * FROM log where createTime between ?1 and ?2 GROUP BY requestIp) as s",nativeQuery = true)
Long findIp(String date1, String date2);
}
package me.zhengjie.monitor.service.query;

import me.zhengjie.monitor.domain.Logging;
import me.zhengjie.monitor.repository.LoggingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List; /**
* @author jie
* @date 2018-11-24
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class LoggingQueryService { @Autowired
private LoggingRepository loggingRepository; public Page queryAll(Logging logging, Pageable pageable){ return loggingRepository.findAll(new Spec(logging),pageable);
} public List queryAll(Logging logging){ return loggingRepository.findAll(new Spec(logging));
} class Spec implements Specification<Logging> { private Logging logging; public Spec(Logging logging){
this.logging = logging;
} @Override
public Predicate toPredicate(Root<Logging> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) { List<Predicate> list = new ArrayList<Predicate>(); if(!ObjectUtils.isEmpty(logging.getUsername())){
list.add(cb.like(root.get("username").as(String.class),"%"+logging.getUsername()+"%"));
} if (!ObjectUtils.isEmpty(logging.getLogType())) {
list.add(cb.equal(root.get("logType").as(String.class), logging.getLogType()));
} Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p));
}
}
}

LoggingService的更多相关文章

  1. .Net中的AOP系列之《单元测试切面》

    返回<.Net中的AOP>系列学习总目录 本篇目录 使用NUnit编写测试 编写和运行NUnit测试 切面的测试策略 Castle DynamicProxy测试 测试一个拦截器 注入依赖 ...

  2. 用Feature的方式删除SharePoint2010的Page中重复的WebPart

    用Feature的方式删除SharePoint2010的Page中重复的WebPart. 代码如下所示: public class SupportCenterDuplicatedWebpartRemo ...

  3. 计划将项目中使用entity framework的要点记录到改栏目下

    ef监控sql执行性能日志.http://www.cnblogs.com/CreateMyself/p/5277681.html http://123.122.205.38/cn_sql_server ...

  4. Weblogic 所有BEA错误代码详细信息列表

    范围 子系统 类别 BEA-000001 – BEA-009999 ConsensusLeasing DatabaseLessLeasing DatabaseLessLeasing BEA-00010 ...

  5. 快速稳定的维护PHP

    Just to recap, previously we'd have this sort of thing: namespace me\adamcameron\testApp; use Guzzle ...

  6. Net中的AOP

    .Net中的AOP系列之<单元测试切面>   返回<.Net中的AOP>系列学习总目录 本篇目录 使用NUnit编写测试 编写和运行NUnit测试 切面的测试策略 Castle ...

  7. 分布式内存网格Hazelcast源码导读

    去年项目需要看了hazelcast源码,当时记录的笔记. Node是节点的抽象,里面包含节点引擎.客户端引擎.分区服务.集群服务.组播服务.连接管理.命令管理.组播属性.节点配置.本地成员.tcp地址 ...

  8. .NET Core TDD 前传: 编写易于测试的代码 -- 构建对象

    该系列第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念. 本文是第2篇, 介绍的是如何避免在构建对象时写出不易测试的代码. 本文的概念性内 ...

  9. Asp.Net Core中利用Seq组件展示结构化日志功能

    在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...

随机推荐

  1. django-替代为自定义的User model

    https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model Subs ...

  2. JavaWeb之搭建自己的MVC框架(一)

    1. 介绍 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的 ...

  3. CentOS 7 连接不到网络解决方法

    使用VM12创建虚拟机并安装CentOS 7,但是安装完成后发现连接不到网络. ping jd.com发现不通 因为在创建虚拟机的时候我们选择的是NAT模式 这里给出NAT模式下对应的的解决方法: 一 ...

  4. Class.forName(String className)解析

    功能: Class.forName(xxx.xx.xx)返回的是一个类 Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类, 也就是说JVM会执行该类的静态代码段 一 ...

  5. adaboost 基于错误提升分类器

    引自(机器学习实战) 简单概念 Adaboost是一种弱学习算法到强学习算法,这里的弱和强学习算法,指的当然都是分类器,首先我们需要简单介绍几个概念. 1:弱学习器:在二分情况下弱分类器的错误率会低于 ...

  6. php魔术常量,_CLASS_,_METHOD_,_FUNCTION_

    _CLASS_: 返回当前类的类名 _METHOD_:返回当前类方法的方法名(并显示类的调用,类名::方法名) _FUNCTION_:返回当前函数的函数名 _FILE_:当前文件的绝对路径(包含_FI ...

  7. SQL基础教程(第2版)第2章 查询基础:练习题

    SELECT product_name, regist_date FROM Product WHERE regist_date > '2009-04-28'; ① ~ ③中的 SQL 语句都无法 ...

  8. A - Shortest path of the king (棋盘)

    The king is left alone on the chessboard. In spite of this loneliness, he doesn't lose heart, becaus ...

  9. Hough直线and圆环变换(如何检测直线、圆环)

    1.霍夫变换 2.cv2.HoughLines() 返回值就是(ρ, θ).ρ 的单位是像素,θ 的单位是弧度.这个函数的第一个参 数是一个二值化图像,所以在进行霍夫变换之前要首先进行二值化,或者进行 ...

  10. 统计_statistics_不同的人_大样本_分析_统计方法_useful ?

    统计_statistics_不同的人_大样本_分析_