SSMAOP日志
数据库与表结构
日志表信息描述sysLog
基于AOP日志处理
创建切面类处理日志
package com.sibd.travel.controller;
import com.sibd.travel.controller.SyslogController;
import com.sibd.travel.pojo.SysLog;
import com.sibd.travel.pojo.Users;
import com.sibd.travel.service.SyslogService;
import com.sibd.travel.util.UuidUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
@Component
@Aspect
public class LogAop {
@Autowired
private SyslogService sysLogService;
@Autowired
private HttpServletRequest request;
private Date startTime; // 访问时间
private Class executionClass;// 访问的类
private Method executionMethod; // 访问的方法
@Before("execution(* com.sibd.travel.controller.*.*(..))")
public void doBefore(JoinPoint jp) throws NoSuchMethodException, SecurityException {
// 访问时间
startTime=new Date();
// 获取访问的类字节码文件
executionClass = jp.getTarget().getClass();
// 获取访问的方法
String methodName = jp.getSignature().getName();// 获取访问的方法的名称
Object[] args = jp.getArgs();// 获取访问的方法的参数
if (args == null || args.length == 0) {// 无参数
executionMethod = executionClass.getMethod(methodName); // 只能获取无参数方法
} else {
// 有参数,就将args中所有元素遍历,获取对应的Class,装入到一个Class[]
Class[] classArgs = new Class[args.length];
for (int i = 0; i < args.length; i++) {
classArgs[i] = args[i].getClass();
}
executionMethod = executionClass.getMethod(methodName, classArgs);// 获取有参数方法
}
}
// 主要获取日志中其它信息,时长、ip、url...
@After("execution(* com.sibd.travel.controller.*.*(..))")
public void doAfter(JoinPoint jp) throws Exception {
// 获取类上的@RequestMapping对象
if (executionClass != SyslogController.class) {
RequestMapping classAnnotation = (RequestMapping) executionClass.getAnnotation(RequestMapping.class);
if (classAnnotation != null) {
// 获取方法上的@RequestMapping对象
RequestMapping methodAnnotation = executionMethod.getAnnotation(RequestMapping.class);
if (methodAnnotation != null) {
String url = ""; // 它的值应该是类上的@RequestMapping的value+方法上的@RequestMapping的value
url = classAnnotation.value()[0] + methodAnnotation.value()[0];
SysLog sysLog = new SysLog();
sysLog.setId(UuidUtil.getId());
// 获取访问时长
Long executionTime = new Date().getTime() - startTime.getTime();
// 将sysLog对象属性封装
sysLog.setExecutionTime(executionTime);
// 获取ip
String ip = request.getRemoteAddr();
sysLog.setIp(ip);
sysLog.setMethod("[类名]" + executionClass.getName() + "[方法名]" + executionMethod.getName());
// 可以通过securityContext获取,也可以从request.getSession中获取
SecurityContext context = SecurityContextHolder.getContext();
//request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
String username = ((User)
(context.getAuthentication().getPrincipal())).getUsername();
sysLog.setUsername(username);
sysLog.setUrl(url);
sysLog.setVisitTime(startTime);
// 调用Service,调用dao将sysLog insert数据库
sysLogService.save(sysLog);
}
}
}
}
}
在切面类中我们需要获取登录用户的username,还需要获取ip地址,我们怎么处理?
-
username获取
SecurityContextHolder获取
-
ip地址获取
ip地址的获取我们可以通过request.getRemoteAddr()方法获取到。
在Spring中可以通过RequestContextListener来获取request或session对象。
@Aspect:作用是把当前类标识为一个切面供容器读取
@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行
SysLogController
package com.sibd.travel.controller;
import com.sibd.travel.pojo.SysLog;
import com.sibd.travel.service.SyslogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@Controller
@RequestMapping("sysLog")
public class SyslogController {
@Autowired
private SyslogService syslogService;
@RequestMapping("findAll.do")
public ModelAndView findAll(){
ModelAndView mv = new ModelAndView();
List<SysLog> sysLogs = syslogService.findAll();
mv.setViewName("syslog-list");
mv.addObject("sysLogs",sysLogs);
return mv;
}
}
Service
package com.sibd.travel.service.impl;
import com.sibd.travel.mapper.SysLogMapper;
import com.sibd.travel.pojo.SysLog;
import com.sibd.travel.service.SyslogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class SyslogServiceImpl implements SyslogService {
@Autowired
private SysLogMapper sysLogMapper;
@Override
public List<SysLog> findAll() {
return sysLogMapper.findAll();
}
@Override
public void save(SysLog sysLog) {
sysLogMapper.save(sysLog);
}
}
Dao
package com.sibd.travel.mapper;
import com.sibd.travel.pojo.SysLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface SysLogMapper {
@Select("select * from syslog")
List<SysLog> findAll();
@Insert("insert into syslog(id,visitTime,username,ip,url,executionTime,method) values(#{id},#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
void save(SysLog sysLog);
}