1、使用AOP做日志记录,pom.xml添加依赖。
<!-- AOP-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、新建切面类
package com.study.nms.aop;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.study.nms.model.security.User;
import com.study.nms.model.system.Log;
import com.study.nms.service.system.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
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.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 系统日志:切面处理类
*/
@Aspect
@Component
public class SystemLogAspect {
@Autowired
private LogService logService;
//定义切点 @Pointcut
//在注解的位置切入代码
@Pointcut("@annotation( com.haige.nms.aop.SystemLogInterface)")
public void logPoinCut() {
}
//切面 配置通知
@AfterReturning("logPoinCut()")
public void saveSysLog(JoinPoint joinPoint) {
//保存日志
Log saveLog = new Log();
//从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取操作
SystemLogInterface myLog = method.getAnnotation(SystemLogInterface.class);
if (myLog != null) {
String value = myLog.value();
saveLog.setOperation(value);//保存获取的操作
saveLog.setLevel(myLog.level());
}
//获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
//获取请求的方法名
String methodName = method.getName();
saveLog.setMethodName(methodName);
//请求的参数
Object[] args = joinPoint.getArgs();
//将参数所在的数组转换成json
Object[] arguments = new Object[args.length];
for (int i = 0; i < args.length; i++) {//排除不能序列化的参数
if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
continue;
}
arguments[i] = args[i];
}
String paramter = "";
if (arguments != null) {
try {
paramter = JSONObject.toJSONString(arguments);
} catch (Exception e) {
paramter = arguments.toString();
}
}
saveLog.setArgs(paramter);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
saveLog.setDate(sdf.format(new Date()));
//获取用户名
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
User user = (User)request.getSession().getAttribute("user");
if(user != null){
saveLog.setUsername(user.getUsername());
}else{
saveLog.setUsername("未知");
}
//获取用户ip地址
if(request.getRemoteAddr().equals("0:0:0:0:0:0:0:1")){
saveLog.setHost("localhost");
}else{
saveLog.setHost(request.getRemoteAddr());
}
saveLog.setUrl(request.getRequestURI());
//调用service保存SysLog实体类到数据库
logService.saveLog(saveLog);
}
@AfterThrowing("logPoinCut()")
public void saveThrowingSysLog(JoinPoint joinPoint) {
System.out.println("切面方法异常");
}
}
3、新建接口类,实现自定义操作内容及日志级别
import java.lang.annotation.*;
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented //生成文档
public @interface SystemLogInterface {
String value() default "";
String level() default "INFO";
}
4、在Controller类添加注解。
import com.study.nms.aop.SystemLogInterface;
import com.study.nms.model.security.User;
import com.study.nms.service.security.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.SessionStatus;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Map;
@Controller
public class LoginController {
@Autowired
private UserService userService;
@SystemLogInterface(value = "账号登录",level = "INFO")
@RequestMapping("/login")
public String login(@RequestParam(value = "username")String username,
@RequestParam(value = "password")String password,
Map<String,Object> map,HttpSession session,
HttpServletResponse response){
User user = userService.findUserByUsername(username);
session.setAttribute("user",user);
if(user != null){
if(user.getPassword().equals(password)){
if(user.isEnabled()){
Cookie cookie=new Cookie("username",user.getUsername());
cookie.setPath("/");
cookie.setMaxAge(30 * 24 * 60 * 60);
response.addCookie(cookie);
return "redirect:/index.html";
}else{
map.put("msg","该账号已被禁用");
return "login";
}
}else{
map.put("msg","用户名密码错误");
return "login";
}
}else{
map.put("msg","用户名不存在");
return "login";
}
}
}
5、重点!!!!!!!!!!!!!!!!!!!
AOP注解的Controller类方法必须为 public 或 protect ,千万不能用private!!!!!!!!否则会@Autowired注入的service会报空指针异常。