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. MyBatis:分页的实现

    日志工厂 思考:我们在测试SQL的时候,要是能够在控制台输出 SQL 的话,是不是就能够有更快的排错效率? 如果一个 数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查问题. 对于以往的 ...

  2. vue实现CheckBox与数组对象绑定

    实现需求: 实现一个简易的购物车,页面的表格展示data数据中的一个数组对象,并提供选中商品和全选商品checkbox复选框,页面实时显示选中商品的总金额: 分析: 1:使用v-for循环渲染arra ...

  3. FFmpeg命令大全(更新中)

    1.视频抽取音频: ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aacffmpeg -i 3.mp4 -vn -y -acodec copy 3.m4a

  4. Jquery输入框焦点事件及鼠表事件汇总

    对于用户的输入框input,我们常常会用ajax来实现与后台的交互.输入框的内容我们可以用.val()方法获取,对于输入框内的事件,我们常用到焦点,如:input.blur.focus.... inp ...

  5. dac oracle

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  6. UVA-101 The Blocks Problem 栈模拟

    终于AC了,这道题目去年寒假卡得我要死,最后一气之下就不做了...想想居然一年之久了,我本来都快忘了这道题了,最近发现白书的奥秘,觉得刘汝佳的题目真的相当练思维以及对代码的操作,决定又刷起题目来,这时 ...

  7. MySQL的优化与执行

    MySQL会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写查询.决定表的读取顺序,以及选择合适的索引等.用户可以通过特殊的关键字提示(hint)优化器,影响它的决策过程.也可以 ...

  8. Python中使用print打印进度条

    import time for i in range(0,101,2): time.sleep(0.1) char_num = i//2 #打印多少个'*' per_str = '\r%s%% : % ...

  9. 当切换用户时出现-bash-4.1$

    问题重现 [root@localhost ~]# su - yh -bash-4.1$ -bash-4.1$ -bash-4.1$ -bash-4.1$ -bash-4.1$ cd /home -ba ...

  10. python学习笔记-模块和包

    模块导入方法 1.import 语句 import module1[,module2[,...moduleN]] 当我们使用import语句的时候,Python解释器是怎么找到对应对文件对呢?答案是解 ...