一、pom.xml依赖导入
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入druid依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.14</version>
</dependency>
<!--Spring Boot Mybatis 依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
<!-- MySQL 连接驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!-- 这里我使用lombok生成getting和setting等方法,如果没安装插件的,可以不需要加这个 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
<!-- aop依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二、日志信息实体类
记得配置lombok插件
@Getter
@Setter
@ToString
@Data
//系统日志管理
public class SystemLog {
/**
* 主键,标识列,自动生成
*/
private Integer logid;
/**
* 关联员工表主键
*/
private String empname;
/**
* Ip地址
*/
private String ipaddr;
/**
* 操作时间
*/
private Date optime;
/**
* 操作的内容
*/
private String params;
/**
* 信息
*/
private String msg;
}
三、SystemLogDao(Dao层)
@Repository
@Transactional
public interface SystemLogDao {
//保存日志信息到数据库
int insert(SystemLog systemLog);
}
四、建立Dao层的mapper.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stodgy.dao.SystemLogDao">
<insert id="insert" keyColumn="logId" keyProperty="logid" parameterType="com.stodgy.bean.SystemLog" useGeneratedKeys="true">
<!--@mbg.generated-->
insert into systemLog (empName, ipAddr, optime,
params, msg)
values (#{empname,jdbcType=VARCHAR}, #{ipaddr,jdbcType=VARCHAR}, #{optime,jdbcType=TIMESTAMP},
#{params,jdbcType=VARCHAR}, #{msg,jdbcType=VARCHAR})
</insert>
</mapper>
五、建立Service类
public interface SystemLogService {
int insert(SystemLog systemLog);
}
六、建立ServiceImpl类
@Service
public class SystemLogServiceImpl implements SystemLogService {
@Resource
private SystemLogDao sd;
@Override
public int insert(SystemLog systemLog) {
return sd.insert(systemLog);
}
}
七、建立自定义注解Log
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
}
八、工具类IPUtils和HttpContextUtils
IPUtils
package com.atqh.logistics.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class IpUtils {
/**
* 获取IP地址
* <p>
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null, unknown = "unknown", seperator = ",";
int maxLength = 15;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
log.error("IpUtils ERROR ", e);
}
// 使用代理,则获取第一个IP地址
if (StringUtils.isEmpty(ip) && ip.length() > maxLength) {
int idx = ip.indexOf(seperator);
if (idx > 0) {
ip = ip.substring(0, idx);
}
}
return ip;
}
/**
* 获取ip地址
*
* @return
*/
public static String getIpAddr() {
HttpServletRequest request = com.atqh.logistics.utils.HttpContextUtils.getHttpServletRequest();
return getIpAddr(request);
}
}
HttpContextUtils
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
九、LogAspect类
@Aspect
@Component
public class LogAspect {
@Autowired
private SystemLogDao sd;
@Pointcut("@annotation(com.ht.annotation.Log)")
public void pointcut() { }
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) {
Object result = null;
long beginTime = System.currentTimeMillis();
try {
// 执行方法
result = point.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 保存日志
saveLog(point, time);
return result;
}
private void saveLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SystemLog systemLog = new SystemLog();
Log logAnnotation = method.getAnnotation(Log.class);
if (logAnnotation != null) {
//获取注解@Log在controller上的描述
systemLog.setMsg(logAnnotation.value());
}
// 获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//获取session
HttpSession session = request.getSession();
// 设置IP地址
systemLog.setIpaddr(IPUtils.getIpAddr(request));
//这里我是获取登录的用户,我已将登录的用户的信息放进了session
//获取session的用户
Emp emp = (Emp)session.getAttribute("emp");
systemLog.setEmpname(emp.getEmpname());
//设置登录时间
systemLog.setOptime(new Date());
//设置登录参数
systemLog.setParams(emp.toString());
// 保存系统日志
sd.insert(systemLog);
}
}
十、在需要监控的Controller类使用
@Controller
@RequestMapping("/login")
public class LoginController {
@Resource
private LoginService ls;
//在每个方法前加,当访问这个方法的时候,就会自动去保存你已经设置好的日志信息
@Log("登录系统")
//查询是否该员工账号
@RequestMapping("/isnEmp")
@ResponseBody
public Map isnEmp(Emp emp, HttpSession session){
Emp login = ls.login(emp);
Map map = new HashMap();
if (login!=null){
session.setAttribute("emp",login);
map.put("i",1);
}
return map;
}
//退出登录
@RequestMapping("/out")
public String out(HttpSession session){
session.removeAttribute("emp");
return "login";
}
}