1. SSMAOP日志
1.1 日志表信息描述sysLog
1.2 sql语句
CREATE TABLE sysLog(
id VARCHAR2(32) default SYS_GUID() PRIMARY KEY,
visitTime timestamp,
username VARCHAR2(50),
ip VARCHAR2(30),
url VARCHAR2(50),
executionTime int,
method VARCHAR2(200)
)
1.3.实体类
public class SysLog {
private String id;
private Date visitTime;
private String visitTimeStr;
private String username;
private String ip;
private String url;
private Long executionTime;
private String method;
}
2.基于AOP日志处理
2.1 切面类LogAop
注意:详细可以自行复习 反射、AOP面向切面编程
思考:
在切面类中我们需要获取登录用户的username,还需要获取ip地址,我们怎么处理?
- username获取
- SecurityContextHolder获取
- ip地址获取
ip地址的获取我们可以通过request.getRemoteAddr()方法获取到。
在Spring中可以通过RequestContextListener来获取request或session对象。
思路分析:
@Component
@Aspect
public class LogAop {
@Autowired
private HttpServletRequest httpServletRequest;
@Autowired
private ISysLogService sysLogService;
private Date startTime; // 访问时间
private Class executionClass;// 访问的类
private Method executionMethod; // 访问的方法
/**
* 前置通知
* 获取开始时间、执行的类是哪一个、访问的方法是哪一个
*/
@Before("execution(* code.controller.*.*(..))")
public void doBefore(JoinPoint jp) throws NoSuchMethodException {
startTime = new Date();//当前时间就是开始访问时间
executionClass = jp.getTarget().getClass();//具体要访问的类
String methodName = jp.getSignature().getName();//获取访问的方法名
Object[] args = jp.getArgs();//获取访问方法的参数
//获取method对象
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);
}
}
/**
* 后置通知
*/
@After("execution(* code.controller.*.*(..))")
public void doAfter(JoinPoint jp) throws Exception {
//1. 获取访问时长
Long executionTime = new Date().getTime() - startTime.getTime();
//2.获取url
String url ="";
if (executionClass != null && executionMethod !=null && executionClass != LogAop.class){
RequestMapping classAnnotation = (RequestMapping)executionClass.getAnnotation(RequestMapping.class);
if (classAnnotation != null){
String[] classValue = classAnnotation.value();
RequestMapping methodAnnotation = executionMethod.getAnnotation(RequestMapping.class);
if (methodAnnotation != null){
String[] methodValue = methodAnnotation.value();
url = classValue[0] + methodValue[0];
}
}
}
//3.获取访问的ip地址(request对象)
String ip = httpServletRequest.getRemoteAddr();
//4.获取当前操作的用户
//4.1 可以通过securityContext获取
//4.2 也可以从request.getSession中获取,request.getSession().getAttribute("SPRING_SECURITY_CONTEXT")
SecurityContext context = SecurityContextHolder.getContext();
User user = (User) context.getAuthentication().getPrincipal();
String username = user.getUsername();
//5.将信息封装到sysLog对象
SysLog sysLog = new SysLog();
sysLog.setExecutionTime(executionTime);
sysLog.setIp(ip);
sysLog.setMethod("[类名] "+executionClass.getName()+"[方法名] "+executionMethod.getName());
sysLog.setUrl(url);
sysLog.setUsername(username);
sysLog.setVisitTime(startTime);
// 调用Service,调用dao将sysLog insert数据库
sysLogService.save(sysLog);
}
}
public interface ISysLogDao {
@Insert("insert into syslog(visitTime,username,ip,url,executionTime,method) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
void save(SysLog sysLog);
}
注意:
- 请求controller时如果访问的方法有参数时,必须是包装类型的参数比如
Integer
,不可以是int
,因为通过反射获取
方法对象时会报错。 - Controller 的 @RequestMapping(value = “/findAll.do”) ,必须 指明
value属性
,因为在上面的代码上,解析url时 String[] classValue = classAnnotation.value(); 、 String[] methodValue = methodAnnotation.value(); 都获取的是注解的 value 属性
测试结果:
用户登录后每访问一次服务器的方法,都会在数据库中增加一条记录,记录了用户的访问时间、访问时长、访问的url、ip地址、用户名等日志信息。
2.2 通过页面查看日志
思路分析:
SysLogController
@Controller
@RequestMapping(value = "/sysLog")
public class SysLogController {
@Autowired
private ISysLogService sysLogService;
@RequestMapping(value = "/findAll.do")
public ModelAndView findAll()throws Exception{
ModelAndView mv = new ModelAndView();
List<SysLog> sysLogs = sysLogService.findAll();
mv.addObject("sysLogs",sysLogs);
mv.setViewName("syslog-list");
return mv;
}
}
ISysLogDao
@Select("select * from syslog")
@Results({
@Result(id = true,property = "id",column = "id"),
@Result(property = "visitTime",column = "visitTime"),
@Result(property = "username",column = "username"),
@Result(property = "ip",column = "ip"),
@Result(property = "url",column = "url"),
@Result(property = "executionTime",column = "executionTime"),
@Result(property = "method",column = "method")
})
List<SysLog> findAll();