首先,得利用上篇的工具类代码生成,OperateLogInfoMapper、OperateLogInfo、OperateLogInfoExample、OperateLogInfoMapper.xml还有user表的,放到对应的包下,代码有的没有判空这个不太好,最好自己可以加上非空判断!
设计日志记录注解SystemLog(在annotation包下),控制层的方法要记录操作日志,就需要增加该注解,具体代码如下:
package com.xll.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 进行系统日志控制的注释,如果Controller里面方法加上了该注解,
* 则表示该方法需要进行操作日志记录,该注释只作用在方法上
*
* @author lonely.xia
* @date 2017/10/15
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemLog {
/**
* 描述业务操作功能 例:登录、查看用户等等
* @return
*/
String description() default "";
}
spring-mvc.xml配置文件中加上
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="WaitForTasksToCompleteOnShutdown" value="true" />
</bean>
编写SystemLogAspect的AOP类,用来拦截被SystemLog注解的方法
package com.xll.aop;
import com.xll.annotation.SystemLog;
import com.xll.model.OperateLogInfo;
import com.xll.model.User;
import com.xll.service.OperateLogInfoService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.NamedThreadLocal;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 系统日志切面,针对使用了SystemLog注释的方法进行拦截
* 之后将日志数据写入数据库
*/
@Component
@Aspect
public class SystemLogAspect {
private static final Logger LOG = LoggerFactory.getLogger(SystemLogAspect.class);
/** 记录每个用户刚开始访问方法的时间 */
private static final ThreadLocal<Date> BEGIN_TIME_THREAD_LOCAL =
new NamedThreadLocal<Date>("ThreadLocal beginTime");
private static final ThreadLocal<OperateLogInfo> LOG_THREAD_LOCAL =
new NamedThreadLocal<OperateLogInfo>("ThreadLocal log");
@Autowired(required=false)
private HttpServletRequest request;
/** spring框架自带的线程池 */
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Resource
private OperateLogInfoService operateLogInfoService;
public SystemLogAspect() {}
/**
* 对使用SystemLog注释的方法进行拦截
*/
@Pointcut("@annotation(com.xll.annotation.SystemLog)")
public void systemLogAspectCtrl(){}
/**
* 前置通知 用于拦截记录用户的操作的开始时间
*
* @param joinPoint 切点
* @throws InterruptedException
*/
@Before("systemLogAspectCtrl()")
public void doBefore(JoinPoint joinPoint) throws InterruptedException {
Date beginTime = new Date();
BEGIN_TIME_THREAD_LOCAL.set(beginTime);
if (LOG.isDebugEnabled()){
LOG.debug("开始计时: {},URI: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.format(beginTime), request.getRequestURI());
}
}
/**
* 后置通知 用于拦截用户操作
*
* @param joinPoint 切点
*/
@After("systemLogAspectCtrl()")
public void doAfter(JoinPoint joinPoint) {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user != null) {
OperateLogInfo operateLogInfo = new OperateLogInfo();
operateLogInfo.setUid(user.getId());
operateLogInfo.setUname(user.getName());
operateLogInfo.setStatus(true);
operateLogInfo.setFromIp(request.getRemoteAddr());
operateLogInfo.setMethod(request.getMethod());
operateLogInfo.setUri(request.getRequestURI());
operateLogInfo.setLogType("info");
operateLogInfo.setOperateFunc(getMethodDescription(joinPoint));
operateLogInfo.setVisitMethod(getMethod(joinPoint));
operateLogInfo.setMethodCostTime(new Date().getTime() - BEGIN_TIME_THREAD_LOCAL.get().getTime() + "");
// 开启新线程进行日志记录
taskExecutor.execute(new SaveLogThread(operateLogInfo , operateLogInfoService));
LOG_THREAD_LOCAL.set(operateLogInfo);
}
}
/**
* 获取注解中对方法的描述信息
*
* @param joinPoint 切点
* @return description
*/
private String getMethodDescription(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SystemLog systemLog = method.getAnnotation(SystemLog.class);
String description = systemLog.description();
return description;
}
private String getMethod(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
return method.getName();
}
/**
* 异常通知 记录操作报错日志
*
* @param joinPoint
* @param e
*/
@AfterThrowing(pointcut = "systemLogAspectCtrl()" , throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint , Throwable e) {
OperateLogInfo operateLogInfo = LOG_THREAD_LOCAL.get();
operateLogInfo.setLogType("error");
operateLogInfo.setVisitMethodErrorInfo(e.getMessage());
taskExecutor.execute(new UpdateLogThread(operateLogInfo , operateLogInfoService));
}
/**
* 保存日志线程
*/
private static class SaveLogThread implements Runnable {
private OperateLogInfo operateLogInfo;
private OperateLogInfoService operateLogInfoService;
public SaveLogThread(OperateLogInfo operateLogInfo, OperateLogInfoService operateLogInfoService) {
this.operateLogInfo = operateLogInfo;
this.operateLogInfoService = operateLogInfoService;
}
@Override
public void run() {
//这里会将插入后的记录ID给,写入operateLogInfo所指的对象实例中(如何实现看OperateLogInfoMapper.xml中insert)
operateLogInfoService.insert(operateLogInfo);
}
}
/**
* 日志更新线程
*/
private static class UpdateLogThread extends Thread {
private OperateLogInfo operateLogInfo;
private OperateLogInfoService operateLogInfoService;
public UpdateLogThread(OperateLogInfo operateLogInfo, OperateLogInfoService operateLogInfoService) {
super(UpdateLogThread.class.getSimpleName());
this.operateLogInfo = operateLogInfo;
this.operateLogInfoService = operateLogInfoService;
}
@Override
public void run() {
operateLogInfoService.update(operateLogInfo);
}
}
}
OperateLogInfoMapper.xml中的insert(useGeneratedKeys=”true” keyProperty=”id”会将ID返回)
<insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="com.xll.model.OperateLogInfo">
insert into operate_log_info (id, uid, uname,
create_time, update_time, status,
from_ip, operate_func, visit_method,
visit_method_error_info, login_out_time, method_cost_time,
log_type, uri, method
)
values (#{id,jdbcType=INTEGER}, #{uid,jdbcType=INTEGER}, #{uname,jdbcType=VARCHAR},
#{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, #{status,jdbcType=BIT},
#{fromIp,jdbcType=VARCHAR}, #{operateFunc,jdbcType=VARCHAR}, #{visitMethod,jdbcType=VARCHAR},
#{visitMethodErrorInfo,jdbcType=VARCHAR}, #{loginOutTime,jdbcType=TIMESTAMP}, #{methodCostTime,jdbcType=VARCHAR},
#{logType,jdbcType=VARCHAR}, #{uri,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR}
)
</insert>
OperateLogInfoService.java接口
package com.xll.service;
import com.xll.model.OperateLogInfo;
/**
* Created by lonely.xia on 2017/10/16.
*/
public interface OperateLogInfoService {
int update(OperateLogInfo operateLogInfo);
int insert(OperateLogInfo operateLogInfo);
}
OperateLogInfoServiceImpl.java实现类
package com.xll.service.impl;
import com.xll.mapper.OperateLogInfoMapper;
import com.xll.model.OperateLogInfo;
import com.xll.service.OperateLogInfoService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* Created by lonely.xia on 2017/10/16.
*/
@Service("operateLogInfoService")
public class OperateLogInfoServiceImpl implements OperateLogInfoService {
@Resource
private OperateLogInfoMapper operateLogInfoDao;
@Override
public int update(OperateLogInfo operateLogInfo) {
return operateLogInfoDao.updateByPrimaryKeySelective(operateLogInfo);
}
@Override
public int insert(OperateLogInfo operateLogInfo) {
int count = operateLogInfoDao.insertSelective(operateLogInfo);
return count;
}
}
UserController.java
package com.xll.controller;
import com.xll.annotation.SystemLog;
import com.xll.dto.UserDTO;
import com.xll.enums.PageEnum;
import com.xll.enums.ResponseEnum;
import com.xll.model.Role;
import com.xll.model.User;
import com.xll.model.UserRole;
import com.xll.service.RoleService;
import com.xll.service.UserRoleService;
import com.xll.service.UserService;
import com.xll.util.BootstrapTablePage;
import com.xll.util.GeneralResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lonely.xia on 2017/10/10.
*/
@Controller
@RequestMapping("/user")
public class UserController {
private static final Logger LOG = LoggerFactory.getLogger(UserController.class);
@Resource
private UserService userService;
@SystemLog(description = "伪登录")
@RequestMapping(value = "/vlogin" , method = RequestMethod.GET)
public String vlogin(HttpSession httpSession
, HttpServletRequest request , HttpServletResponse response, @RequestParam Integer uid) {
User user = userService.vlogin(uid);
if (user != null) {
httpSession.setAttribute("user" , user);
request.setAttribute("page" , PageEnum.INDEX.getCode());
} else {
request.setAttribute("page" , PageEnum.LOGIN_HINT.getCode());
}
return "./../../index";
}
}
UserServiceImpl.java
package com.xll.service.impl;
import com.xll.mapper.UserMapper;
import com.xll.model.RoleExample;
import com.xll.model.User;
import com.xll.model.UserExample;
import com.xll.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
/**
* Created by lonely.xia on 2017/10/10.
*/
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userDao;
public User vlogin(int uid) {
User user = userDao.selectByPrimaryKey(uid);
return user;
}
}
PageEnum.java
package com.xll.enums;
/**
* Created by lonely.xia on 2017/10/12.
*/
public enum PageEnum {
LOGIN_HINT("登录提示" , -1) ,
INDEX("首页" , 0) ,
TEST_ONE("测试页面一" , 1) ,
TEST_TWO("测试页面二" , 2) ,
TEST_THREE("测试页面三" , 3) ,
TEST_FOUR("测试页面四" , 4) ,
USER_LIST("用户列表" , 10) ,
ROLE_LIST("角色列表" , 20) ,
ACCESS_LIST("权限列表" , 30) ,
NONE_ACCESS("无访问权限" , -9999);
private String name;
private int code;
private PageEnum(String name , int code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public int getCode() {
return code;
}
}
访问http://localhost:8080/user/vlogin/uid=xxx,就会在数据库插入一条数据:
下篇实现首页内容