后台管理系统之系统操作日志开发(Java实现)
一,功能点
实现管理员操作数据的记录。效果如下
二,代码实现
基于注解的Aop日志记录
1.Log实体类
package com.ideal.manage.guest.bean.log; import javax.persistence.*; import java.io.Serializable; import java.util.Date; /** * @apiNote 日志 * @author Yaming * @since 2019-01-24 */ @Entity @Table(name = "visitor_sys_log") public class Log implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Long id; private String content; private String description; private String ip; private String module; private String username; private Date createAt; private Date updateAt; private Integer able; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getModule() { return module; } public void setModule(String module) { this.module = module; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public static long getSerialVersionUID() { return serialVersionUID; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Date getCreateAt() { return createAt; } public void setCreateAt(Date createAt) { this.createAt = createAt; } public Date getUpdateAt() { return updateAt; } public void setUpdateAt(Date updateAt) { this.updateAt = updateAt; } public Integer getAble() { return able; } public void setAble(Integer able) { this.able = able; } }
2.定义注解
package com.ideal.manage.guest.annotation; import java.lang.annotation.*; /** * @author Hao * @create 2017-03-29 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Log { /**模块*/ String module() default ""; /**描述*/ String description() default ""; }
3.定义切面
package com.ideal.manage.guest.aop; import com.ideal.manage.guest.annotation.Log; import com.ideal.manage.guest.service.log.LogService; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.lang.reflect.Method; /** * 日志切面处理类 * * @author Yaming * @create 2019-01-24 */ @Aspect @Component public class LogAspect { @Autowired private LogService logService; /** * 日志切入点 */ @Pointcut("@annotation(com.ideal.manage.guest.annotation.Log)") public void logPointCut(){} @AfterReturning(pointcut = "logPointCut()") public void doAfter(JoinPoint joinPoint){ /** * 解析Log注解 */ String methodName = joinPoint.getSignature().getName(); Method method = currentMethod(joinPoint,methodName); Log log = method.getAnnotation(Log.class); logService.put(joinPoint,methodName,log.module(),log.description()); } /** * 获取当前执行的方法 * * @param joinPoint 连接点 * @param methodName 方法名称 * @return 方法 */ private Method currentMethod(JoinPoint joinPoint, String methodName) { /** * 获取目标类的所有方法,找到当前要执行的方法 */ Method[] methods = joinPoint.getTarget().getClass().getMethods(); Method resultMethod = null; for (Method method : methods) { if (method.getName().equals(methodName)) { resultMethod = method; break; } } return resultMethod; } }
4.业务处理:LogService
package com.ideal.manage.guest.service.log; import com.alibaba.fastjson.JSONObject; import com.ideal.manage.guest.bean.DTO.PageDto; import com.ideal.manage.guest.bean.log.Log; import com.ideal.manage.guest.config.shiro.MyShiroRealm; import com.ideal.manage.guest.repository.framework.MySpecification; import com.ideal.manage.guest.repository.framework.SpecificationOperator; import com.ideal.manage.guest.repository.log.LogRepository; import com.ideal.manage.guest.util.Const; import com.ideal.manage.guest.util.HttpRequests; import com.ideal.manage.guest.util.IPUtils; /*import org.apache.ibatis.javassist.*; import org.apache.ibatis.javassist.bytecode.CodeAttribute; import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute; import org.apache.ibatis.javassist.bytecode.MethodInfo;*/ import javassist.*; import javassist.bytecode.CodeAttribute; import javassist.bytecode.LocalVariableAttribute; import javassist.bytecode.MethodInfo; import org.apache.shiro.SecurityUtils; import org.aspectj.lang.JoinPoint; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * <p> * 服务实现类 * </p> * * @author * @since 2017-09-05 */ @Service public class LogService{ private static final String LOG_CONTENT = "[类名]:%s,[方法]:%s,[参数]:%s,[IP]:%s"; private String username; @Autowired private LogRepository logRepository; public String initUsername(String username) { if(!StringUtils.isEmpty(username)){ this.username = username; } return this.username; } public void put(JoinPoint joinPoint, String methodName, String module, String description) { try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); Log log = new Log(); //username = ((JwtClient) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername(); // 获取当前登录用户 MyShiroRealm.ShiroUser shiroUser = (MyShiroRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal(); // User user = userRepository.findOne(shiroUser.getId()); username = shiroUser.getUsername(); if (StringUtils.isEmpty(username)) { username = Const.USERNAME_IN_CONTEXT != null ? Const.USERNAME_IN_CONTEXT : "未知用户"; } String ip = IPUtils.getIpAddr(request); log.setUsername(username); log.setModule(module); log.setDescription(description); log.setIp(ip); log.setContent(operateContent(joinPoint, methodName, ip, request)); log.setAble(1); //insert(log); logRepository.save(log); } catch (Exception e) { e.printStackTrace(); } } /*public Page<Log> page(LogRequest request, Page<Log> page) { if(request == null){ request = new LogRequest(); } request.setIsDeleted(Config.ABLE_CONFIG.ABLE); List<Log> logs = baseMapper.page(request,page); page.setRecords(logs); return page; }*/ /** * 查询所有日志 * @param pageNum * @param request * @return */ public PageDto findAll(int pageNum, HttpServletRequest request) { Sort sort = new Sort(Sort.Direction.DESC, "updateAt"); List<SpecificationOperator> operators = HttpRequests.getParametersStartingWith(request, "Q_"); //增加删除标识的过滤 SpecificationOperator isValid = new SpecificationOperator("able", "1", "EQ"); operators.add(isValid); MySpecification<Log> mySpecifications = new MySpecification<>(operators); Pageable pageable = new PageRequest(pageNum, 10, sort); Page<Log> page = logRepository.findAll(mySpecifications, pageable); //设置PageDto List<Log> parameters = page.getContent(); long total = page.getTotalElements(); PageDto pageDto = new PageDto(); pageDto.setRows(parameters); pageDto.setTotal(total); return pageDto; } public String operateContent(JoinPoint joinPoint, String methodName, String ip, HttpServletRequest request) throws ClassNotFoundException, NotFoundException { String className = joinPoint.getTarget().getClass().getName(); Object[] params = joinPoint.getArgs(); String classType = joinPoint.getTarget().getClass().getName(); Class<?> clazz = Class.forName(classType); String clazzName = clazz.getName(); Map<String,Object > nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName,params); StringBuffer bf = new StringBuffer(); if (!CollectionUtils.isEmpty(nameAndArgs)){ Iterator it = nameAndArgs.entrySet().iterator(); while (it.hasNext()){ Map.Entry entry = (Map.Entry) it.next(); String key = (String) entry.getKey(); String value = JSONObject.toJSONString(entry.getValue()); bf.append(key).append("="); bf.append(value).append("&"); } } if (StringUtils.isEmpty(bf.toString())){ bf.append(request.getQueryString()); } return String.format(LOG_CONTENT, className, methodName, bf.toString(), ip); } private Map<String,Object> getFieldsName(Class cls, String clazzName, String methodName, Object[] args) throws NotFoundException { Map<String,Object > map=new HashMap<String,Object>(); ClassPool pool = ClassPool.getDefault(); ClassClassPath classPath = new ClassClassPath(cls); pool.insertClassPath(classPath); CtClass cc = pool.get(clazzName); CtMethod cm = cc.getDeclaredMethod(methodName); MethodInfo methodInfo = cm.getMethodInfo(); CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); if (attr == null) { // exception return map; } int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1; for (int i = 0; i < cm.getParameterTypes().length; i++){ map.put( attr.variableName(i + pos),args[i]);//paramNames即参数名 } return map; } }
5.dao
package com.ideal.manage.guest.repository.log; import com.ideal.manage.guest.bean.log.Log; import com.ideal.manage.guest.repository.framework.BaseRepository; /** * <p> * Mapper 接口 * </p> * * @author Yankee * @since 2017-09-05 */ public interface LogRepository extends BaseRepository<Log,String> { /** * 查询分页 * @param request * @param page * @return */ //List<Log> page(@Param("re") LogRequest request, Pagination page); }
三,使用注解在需要的地方记录日志
@Log(module = "设备管理",description = "添加设备") public Integer saveEquipment(Equipment equipment) { equipment.setAble(1); Equipment resultEquipment = equipmentRepository.save(equipment); if(resultEquipment == null){ return StateUtil.RESULT_FAILED; } return StateUtil.RESULT_SUCCESS; }