SSM框架下通过aspect切面实现日志信息的保存和展示
通过AOP切面实现日志信息的保存
mysql日志表数据库设计
第一步创建SysLog实体类
package com.travel_ssm_pojo.pojo;
import com.travel_ssm_utils.utils.FormatDateUtil;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class SysLog {
private String id;//无意义,主键 UUID
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private Date visitTime;//访问时间
private String visitTimeStr;
private String username;//操作者用户名
private String ip;//访问IP
private String url;//访问资源URL
private Long executionTime;//执行时长
private String method;//访问方法
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Date getVisitTime() {
return visitTime;
}
public void setVisitTime(Date visitTime) {
this.visitTime = visitTime;
}
public String getVisitTimeStr() {
if (this.visitTime!=null){
this.visitTimeStr=FormatDateUtil.dateToStrLong(this.visitTime);
}
return visitTimeStr;
}
public void setVisitTimeStr(String visitTimeStr) {
this.visitTimeStr = visitTimeStr;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Long getExecutionTime() {
return executionTime;
}
public void setExecutionTime(Long executionTime) {
this.executionTime = executionTime;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
@Override
public String toString() {
return "SysLog{" +
"id='" + id + '\'' +
", visitTime=" + visitTime +
", visitTimeStr='" + visitTimeStr + '\'' +
", username='" + username + '\'' +
", ip='" + ip + '\'' +
", url='" + url + '\'' +
", executionTime=" + executionTime +
", method='" + method + '\'' +
'}';
}
}
第二步创建SysLogDao持久层
该类采用mybatis注解的方式实现SQL语句
@Repository
public interface SysLogDao {
/*保存日志信息*/
@Insert("INSERT INTO syslog VALUES(#{id},#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})")
void saveSysLog(SysLog sysLog);
/*查询所有日志信息*/
@Select("select * from syslog")
List<SysLog> findAllLogs();
}
第三步创建SYSLogService业务层
service接口
public interface SysLogService {
//保存日志信息
void saveSysLog(SysLog sysLog);
//查看所有日志信息
List<SysLog> findAllLogs(Integer page,Integer size);
}
serviceImpl实现类
@Service
@Transactional
public class SysLogServiceImpl implements SysLogService {
@Autowired
private SysLogDao logDao;
/*保存日志信息,通过切面*/
public void saveSysLog(SysLog sysLog) {
logDao.saveSysLog(sysLog);
}
/*查询所有日志信息,分页*/
public List<SysLog> findAllLogs(Integer page,Integer size) {
PageHelper.startPage(page,size);
return logDao.findAllLogs();
}
}
第四步在springMVC.xml配置文件中开启切面注解代理
<!--开启切面-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
第五步在web.xml配置文件中配置request监听器
<!--配置HttpServletRequest监听器-->
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
第六步创建LogAOP切面类
package com.travel_ssm_web.web.logaop;
import com.travel_ssm_pojo.pojo.SysLog;
import com.travel_ssm_service.service.SysLogService;
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;
import java.util.UUID;
@Component
@Aspect
public class LogAop {
private Class executionClass;//类
private Method executionMethod;//方法
private Date startTime;//开始时间
private long executionTime;//执行的时长
private String ip;//访问IP地址
private String username;//访问用户名
@Autowired
private HttpServletRequest request;
@Autowired
private SysLog sysLog;
@Autowired
private SysLogService logService;
/**
* 获取方法返回时间
* 前置通知
*/
@Before("execution(* com.travel_ssm_web.web.*.*(..))")
public void doBefore(JoinPoint joinPoint){
//获取访问时间
startTime = new Date();
//获取访问的方法
//第一,获取访问的类
executionClass = joinPoint.getTarget().getClass();
//获取访问方法的名称
String methodName = joinPoint.getSignature().getName();
//获取方法的参数
Object[] args = joinPoint.getArgs();
//判断参数是否为空,来判断是有参构造还是无参构造
if (args==null||args.length==0){
try {
//通过获取的访问的类来获取方法
executionMethod = executionClass.getMethod(methodName);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}else {
//不为空,为有参方法,遍历方法的 参数,获取到class类型,放入到数组中
//定义类数组,长度为参数长度
Class[] classes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
classes[i]= args[i].getClass();
}
//通过类得到类中的方法,通过方法名和参数
try {
executionMethod= executionClass.getMethod(methodName,classes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
/**
* 后置通知
* 获取对应的总访问时长,访问ip和访问URL
*/
@After("execution(* com.travel_ssm_web.web.*.*(..))")
public void doAfter(){
//获取URL通过获取的注解类的requestMapping(value="")的属性来获取
RequestMapping classMapping = (RequestMapping) executionClass.getAnnotation(RequestMapping.class);
if (classMapping!=null){
//获取对应方法的requestMapping的注解类
RequestMapping methodMapping = executionMethod.getAnnotation(RequestMapping.class);
if (methodMapping!=null){
//获取类requestMapping中的value的属性值
String classValue = classMapping.value()[0];
//获取方法requestMapping中的value属性的值
String methodValue = methodMapping.value()[0];
String url=classValue+methodValue;
//获取对应controller中方法的时长
executionTime = new Date().getTime() - startTime.getTime();
//获取IP地址
ip = request.getRemoteAddr();
//获取用户名
SecurityContext context = SecurityContextHolder.getContext();
User user = (User) context.getAuthentication().getPrincipal();
username=user.getUsername();
//生成UUID主键id
String id = UUID.randomUUID().toString().replace("-", "");
//保存日志信息
sysLog.setId(id);
sysLog.setVisitTime(startTime);
sysLog.setUsername(username);
sysLog.setIp(ip);
sysLog.setUrl(url);
sysLog.setExecutionTime(executionTime);
sysLog.setMethod("[类名]" + executionClass.getName() + "[方法名]" +executionMethod.getName());
//调用service方法
logService.saveSysLog(sysLog);
}
}
}
}
实现页面展示所有日志信息
controller层
@Controller
@RequestMapping("/log")
public class LogController {
@Autowired
private SysLogService logService;
/**
* 通过pageHelper实现分页查询所有日志信息
* @param page
* @param size
* @return
*/
@RequestMapping("/findall")
public ModelAndView findAll(@RequestParam(defaultValue = "1",required = false) Integer page,@RequestParam(defaultValue = "5",required = false) Integer size){
ModelAndView modelAndView = new ModelAndView();
List<SysLog> allLogs = logService.findAllLogs(page,size);
PageInfo<SysLog> pageInfo = new PageInfo<>(allLogs);
modelAndView.addObject(pageInfo);
modelAndView.setViewName("log-list");
return modelAndView;
}
}
log-list.jsp的日志数据展示核心代码
<!--数据列表-->
<table id="dataList"
class="table table-bordered table-striped table-hover dataTable">
<thead>
<tr>
<th class="" style="padding-right: 0px"><input
id="selall" type="checkbox" class="icheckbox_square-blue">
</th>
<th class="sorting_asc">ID</th>
<th class="sorting_desc">访问时间</th>
<th class="sorting_asc sorting_asc_disabled">操作者</th>
<th class="sorting_desc sorting_desc_disabled">访问IP</th>
<th class="sorting">访问资源URL</th>
<th class="text-center">执行时长</th>
<th class="text-center">访问方法</th>
</tr>
</thead>
<tbody>
<c:forEach items="${pageInfo.list}" var="log">
<tr>
<td><input name="ids" type="checkbox"></td>
<td>${log.id }</td>
<td>${log.visitTimeStr }</td>
<td>${log.username }</td>
<td>${log.ip }</td>
<td>${log.url }</td>
<td>${log.executionTime }</td>
<td>${log.method }</td>
</tr>
</c:forEach>
</tbody>
<!--
<tfoot>
<tr>
<th>Rendering engine</th>
<th>Browser</th>
<th>Platform(s)</th>
<th>Engine version</th>
<th>CSS grade</th>
</tr>
</tfoot>-->
</table>
<!--数据列表/-->