1 创建一个切面类
注意:
saveLog 这个方法我加了获取request里的缓存seeion的用户信息,可根据自己业务调整
package com.another.aspect; import com.alibaba.fastjson.JSON; import com.another.aspect.anno.SysLog; import com.another.aspect.service.SysLogService; import com.another.book.model.User; import com.another.common.HttpSessionUtil; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; 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 javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author kql * 日志切面类 */ @Aspect @Component public class LogAspect { // private final static Logger logger = LoggerFactory.getLogger(LogAspect.class); @Autowired private SysLogService sysLogService; // ..表示包及子包 该方法代表controller层的所有方法 @Pointcut("execution(public * com.another.book.controller..*.*(..))") public void controllerMethod() { } /* @Before("controllerMethod()") public void LogRequestInfo(JoinPoint joinPoint) throws Exception { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); User user = HttpSessionUtil.getUser(request); String name= null==user?" 未登陆 ":user.getName(); StringBuffer requestLog = new StringBuffer(); requestLog.append("请求信息:") .append("URL = {" + request.getRequestURI() + "},\t") .append("HTTP_METHOD = {" + request.getMethod() + "},\t") .append("IP = {" + request.getRemoteAddr() + "},\t") .append("CLASS_METHOD = {" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + "},\t") .append(" 操作人 ={" + name + "},\t") ; if (joinPoint.getArgs().length == 0) { requestLog.append("ARGS = {} "); } else { requestLog.append("ARGS = " + new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL) .writeValueAsString(joinPoint.getArgs()[0]) + ""); } logger.info(requestLog.toString()); } @AfterReturning(returning = "resultVO", pointcut = "controllerMethod()") public void logResultVOInfo(ResultVO resultVO) throws Exception { logger.info("请求结果:" + resultVO.getCode() + "\t" + resultVO.getMsg()); } */ /** * 环绕通知 @Around , 当然也可以使用 @Before (前置通知) @After (后置通知) * * @param point * @return * @throws Throwable */ @Around("controllerMethod()") public Object around(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); Object result = point.proceed(); long time = System.currentTimeMillis() - beginTime; try { saveLog(point, time); } catch (Exception e) { } return result; } /** * 保存日志 * * @param joinPoint * @param time */ private void saveLog(ProceedingJoinPoint joinPoint, long time) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SysLogBO sysLogBO = new SysLogBO(); sysLogBO.setExecuteTime(time); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); sysLogBO.setCreateDate(dateFormat.format(new Date())); SysLog sysLog = method.getAnnotation(SysLog.class); if (sysLog != null) { //注解上的描述 sysLogBO.setRemark(sysLog.value()); } //请求的 类名、方法名 //操作人 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); User user = HttpSessionUtil.getUser(request); if (null!=user){ sysLogBO.setOperatorName(user.getName()); }else{ sysLogBO.setOperatorName("未登陆"); } String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); sysLogBO.setClassName(className); sysLogBO.setMethodName(methodName); //请求的参数 Object[] args = joinPoint.getArgs(); try { List<String> list = new ArrayList<String>(); for (Object o : args) { list.add(JSON.toJSONString(o)); } sysLogBO.setParams(list.toString()); } catch (Exception e) { } sysLogService.save(sysLogBO); } }
2 日志service
package com.another.aspect.service; import com.another.aspect.SysLogBO; import com.another.book.dao.SysLogDao; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import java.util.List; import java.util.Map; /** * @author kql * @date 2018/6/4 9:41 * @email 1529949535@qq.com */ @Slf4j @Service public class SysLogService { @Autowired private SysLogDao sysLogDao; @Autowired private EntityManager entityManager; public boolean save(SysLogBO sysLogBO) { //输出日志 log.info(sysLogBO.toString()); //保存 sysLogDao.save(sysLogBO); return true; }
}
3 日志实体类:
package com.another.aspect; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /** * 系统日志bo * @author kuangQingLin * @version 1.0 * @date 2019/12/12/012 14:48 **/ @ApiModel("系统日志bo") @Table(name = "log") @Entity @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}) @Data public class SysLogBO { /** * 主键id */ @GeneratedValue(strategy = GenerationType.IDENTITY) @Id @Column(name = "id") @ApiModelProperty(value = "主键id ", required = true) private Integer id; /** * 类名 */ @Column(name = "class_name") private String className; /** * 方法名 */ @Column(name = "method_name") private String methodName; /** * 参数 */ @Column(name = "params") private String params; /** * 执行时间,毫秒 */ @Column(name = "execute_time") private Long executeTime; /** * 备注(方法的备注) */ @Column(name = "remark") private String remark; /** * 执行开始时间 */ @Column(name = "create_date") private String createDate; /** * 操作人 */ @Column(name = "operator_name") private String operatorName; }
4:自定义日志注解:
package com.another.aspect.anno; import java.lang.annotation.*; /** * 定义系统日志注解 * @author zhuzhe * @date 2018/6/4 9:24 * @email 1529949535@qq.com */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SysLog { String value() default ""; }
5 代码里使用:
这里举例controller,
@SysLog("查询审批")
@GetMapping("/{id}") @ApiOperation("查询审批") @SysLog("查询审批") public String getApprove(@PathVariable("id") int id) { logger.info("查询审批"); approveService.select(id); return "index/index"; }
6 dao:
这里重写的方法是我业务中做统计时候用的,可自行更改
package com.another.book.dao; import com.another.aspect.SysLogBO; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import java.util.List; import java.util.Map; /** * @author kuangQingLin * @version 1.0 * @date 2019/12/12/012 15:09 **/ public interface SysLogDao extends JpaRepository<SysLogBO,Integer> { /** * 分组统计 * @return */ @Query(value = "SELECT DATE_FORMAT(create_date,'%Y-%m') months,COUNT(id) count FROM log GROUP BY months ORDER BY months",nativeQuery = true) List<Map> select(); }
注意:本例持久层用的jpa
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>