Browse Source

add:日志管理功能

Rlax 8 years ago
parent
commit
6bf985893e

+ 22 - 0
doc/jboot-admin-mysql.sql

@@ -239,6 +239,28 @@ CREATE TABLE `sys_user_role` (
 INSERT INTO `sys_user_role` VALUES ('20', '3', '1');
 
 -- ----------------------------
+-- Table structure for sys_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_log`;
+CREATE TABLE `sys_log` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `uid` bigint(20) DEFAULT NULL,
+  `browser` varchar(255) DEFAULT NULL,
+  `operation` varchar(20) DEFAULT NULL COMMENT 'GET/POST',
+  `from` varchar(255) DEFAULT NULL COMMENT '来源 url',
+  `ip` varchar(200) DEFAULT NULL,
+  `url` varchar(255) DEFAULT NULL,
+  `createDate` datetime DEFAULT NULL,
+  `status` varchar(2) DEFAULT '1' COMMENT '1-记录',
+  `lastUpdAcct` varchar(20) DEFAULT NULL,
+  `lastUpdTime` datetime DEFAULT NULL,
+  `note` varchar(200) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `FK_sys_EVENT` (`uid`) USING BTREE,
+  CONSTRAINT `sys_log_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `sys_user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=utf8;
+
+-- ----------------------------
 -- Function structure for querySysRes
 -- ----------------------------
 DROP FUNCTION IF EXISTS `querySysRes`;

+ 4 - 0
jboot-admin-base/pom.xml

@@ -25,6 +25,10 @@
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
         </dependency>
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 124 - 0
jboot-admin-service/jboot-admin-service-api/src/main/java/io/jboot/admin/service/api/LogService.java

@@ -0,0 +1,124 @@
+package io.jboot.admin.service.api;
+
+import com.jfinal.plugin.activerecord.Model;
+import com.jfinal.plugin.activerecord.Page;
+import io.jboot.admin.service.entity.model.Log;
+
+import java.util.List;
+
+public interface LogService  {
+
+    /**
+     * 分页查询数据字典信息
+     * @param log
+     * @param pageNumber
+     * @param pageSize
+     * @return
+     */
+    public Page<Log> findPage(Log log, int pageNumber, int pageSize);
+
+    /**
+     * 根据ID查找model
+     *
+     * @param id
+     * @return
+     */
+    public Log findById(Object id);
+
+
+    /**
+     * 根据ID删除model
+     *
+     * @param id
+     * @return
+     */
+    public boolean deleteById(Object id);
+
+    /**
+     * 删除
+     *
+     * @param model
+     * @return
+     */
+    public boolean delete(Log model);
+
+
+    /**
+     * 保存到数据库
+     *
+     * @param model
+     * @return
+     */
+    public boolean save(Log model);
+
+    /**
+     * 保存或更新
+     *
+     * @param model
+     * @return
+     */
+    public boolean saveOrUpdate(Log model);
+
+    /**
+     * 更新 model
+     *
+     * @param model
+     * @return
+     */
+    public boolean update(Log model);
+
+
+    public void join(Page<? extends Model> page, String joinOnField);
+    public void join(Page<? extends Model> page, String joinOnField, String[] attrs);
+    public void join(Page<? extends Model> page, String joinOnField, String joinName);
+    public void join(Page<? extends Model> page, String joinOnField, String joinName, String[] attrs);
+
+
+    public void join(List<? extends Model> models, String joinOnField);
+    public void join(List<? extends Model> models, String joinOnField, String[] attrs);
+    public void join(List<? extends Model> models, String joinOnField, String joinName);
+    public void join(List<? extends Model> models, String joinOnField, String joinName, String[] attrs);
+
+    /**
+     * 添加关联数据到某个model中去,避免关联查询,提高性能。
+     *
+     * @param model       要添加到的model
+     * @param joinOnField model对于的关联字段
+     */
+    public void join(Model model, String joinOnField);
+
+    /**
+     * 添加关联数据到某个model中去,避免关联查询,提高性能。
+     *
+     * @param model
+     * @param joinOnField
+     * @param attrs
+     */
+    public void join(Model model, String joinOnField, String[] attrs);
+
+
+    /**
+     * 添加关联数据到某个model中去,避免关联查询,提高性能。
+     *
+     * @param model
+     * @param joinOnField
+     * @param joinName
+     */
+    public void join(Model model, String joinOnField, String joinName);
+
+
+    /**
+     * 添加关联数据到某个model中去,避免关联查询,提高性能。
+     *
+     * @param model
+     * @param joinOnField
+     * @param joinName
+     * @param attrs
+     */
+    public void join(Model model, String joinOnField, String joinName, String[] attrs);
+
+
+    public void keep(Model model, String... attrs);
+
+    public void keep(List<? extends Model> models, String... attrs);
+}

+ 12 - 0
jboot-admin-service/jboot-admin-service-entity/src/main/java/io/jboot/admin/service/entity/model/Log.java

@@ -0,0 +1,12 @@
+package io.jboot.admin.service.entity.model;
+
+import io.jboot.db.annotation.Table;
+import io.jboot.admin.service.entity.model.base.BaseLog;
+
+/**
+ * Generated by Jboot.
+ */
+@Table(tableName = "sys_log", primaryKey = "id")
+public class Log extends BaseLog<Log> {
+	
+}

+ 129 - 0
jboot-admin-service/jboot-admin-service-entity/src/main/java/io/jboot/admin/service/entity/model/base/BaseLog.java

@@ -0,0 +1,129 @@
+package io.jboot.admin.service.entity.model.base;
+
+import io.jboot.db.model.JbootModel;
+import com.jfinal.plugin.activerecord.IBean;
+
+/**
+ * Generated by Jboot, do not modify this file.
+ */
+@SuppressWarnings("serial")
+public abstract class BaseLog<M extends BaseLog<M>> extends JbootModel<M> implements IBean {
+
+    public static final String ACTION_ADD = "Log:add";
+    public static final String ACTION_DELETE = "Log:delete";
+    public static final String ACTION_UPDATE = "Log:update";
+
+
+    @Override
+    public String addAction() {
+        return ACTION_ADD;
+    }
+
+    @Override
+    public String deleteAction() {
+        return ACTION_DELETE;
+    }
+
+    @Override
+    public String updateAction() {
+        return ACTION_UPDATE;
+    }
+
+
+	public void setId(java.lang.Long id) {
+		set("id", id);
+	}
+	
+	public java.lang.Long getId() {
+		return getLong("id");
+	}
+
+	public void setUid(java.lang.Long uid) {
+		set("uid", uid);
+	}
+	
+	public java.lang.Long getUid() {
+		return getLong("uid");
+	}
+
+	public void setBrowser(java.lang.String browser) {
+		set("browser", browser);
+	}
+	
+	public java.lang.String getBrowser() {
+		return getStr("browser");
+	}
+
+	public void setOperation(java.lang.String operation) {
+		set("operation", operation);
+	}
+	
+	public java.lang.String getOperation() {
+		return getStr("operation");
+	}
+
+	public void setFrom(java.lang.String from) {
+		set("from", from);
+	}
+	
+	public java.lang.String getFrom() {
+		return getStr("from");
+	}
+
+	public void setIp(java.lang.String ip) {
+		set("ip", ip);
+	}
+	
+	public java.lang.String getIp() {
+		return getStr("ip");
+	}
+
+	public void setUrl(java.lang.String url) {
+		set("url", url);
+	}
+	
+	public java.lang.String getUrl() {
+		return getStr("url");
+	}
+
+	public void setCreateDate(java.util.Date createDate) {
+		set("createDate", createDate);
+	}
+	
+	public java.util.Date getCreateDate() {
+		return get("createDate");
+	}
+
+	public void setStatus(java.lang.String status) {
+		set("status", status);
+	}
+	
+	public java.lang.String getStatus() {
+		return getStr("status");
+	}
+
+	public void setLastUpdAcct(java.lang.String lastUpdAcct) {
+		set("lastUpdAcct", lastUpdAcct);
+	}
+	
+	public java.lang.String getLastUpdAcct() {
+		return getStr("lastUpdAcct");
+	}
+
+	public void setLastUpdTime(java.util.Date lastUpdTime) {
+		set("lastUpdTime", lastUpdTime);
+	}
+	
+	public java.util.Date getLastUpdTime() {
+		return get("lastUpdTime");
+	}
+
+	public void setNote(java.lang.String note) {
+		set("note", note);
+	}
+	
+	public java.lang.String getNote() {
+		return getStr("note");
+	}
+
+}

+ 42 - 0
jboot-admin-service/jboot-admin-service-provider/src/main/java/io/jboot/admin/service/provider/LogServiceImpl.java

@@ -0,0 +1,42 @@
+package io.jboot.admin.service.provider;
+
+import com.jfinal.kit.StrKit;
+import com.jfinal.plugin.activerecord.Page;
+import io.jboot.admin.service.api.UserService;
+import io.jboot.aop.annotation.Bean;
+import io.jboot.admin.service.api.LogService;
+import io.jboot.admin.service.entity.model.Log;
+import io.jboot.core.rpc.annotation.JbootrpcService;
+import io.jboot.db.model.Columns;
+import io.jboot.service.JbootServiceBase;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Bean
+@Singleton
+@JbootrpcService
+public class LogServiceImpl extends JbootServiceBase<Log> implements LogService {
+
+    @Inject
+    private UserService userService;
+
+    @Override
+    public Page<Log> findPage(Log log, int pageNumber, int pageSize) {
+        Columns columns = Columns.create();
+
+        if (StrKit.notBlank(log.getIp())) {
+            columns.like("ip", "%"+log.getIp()+"%");
+        }
+        if (StrKit.notBlank(log.getUrl())) {
+            columns.like("url", "%"+log.getUrl()+"%");
+        }
+        if (StrKit.notBlank(log.getLastUpdAcct())) {
+            columns.like("lastUpdAcct", "%"+log.getLastUpdAcct()+"%");
+        }
+
+        Page<Log> page = DAO.paginateByColumns(pageNumber, pageSize, columns.getList(), "id desc");
+        userService.join(page, "uid", "user");
+        return page;
+    }
+}

+ 2 - 0
jboot-admin/src/main/java/io/jboot/admin/config/JfinalConfigListener.java

@@ -15,6 +15,7 @@ import io.jboot.admin.base.interceptor.BusinessExceptionInterceptor;
 import io.jboot.admin.base.interceptor.NotNullParaInterceptor;
 import io.jboot.admin.base.web.render.AppRenderFactory;
 import io.jboot.admin.support.auth.AuthInterceptor;
+import io.jboot.admin.support.log.LogInterceptor;
 import io.jboot.aop.jfinal.JfinalHandlers;
 import io.jboot.aop.jfinal.JfinalPlugins;
 import io.jboot.server.ContextListeners;
@@ -53,6 +54,7 @@ public class JfinalConfigListener extends JbootAppListenerBase {
 
     @Override
     public void onInterceptorConfig(Interceptors interceptors) {
+        interceptors.add(new LogInterceptor());
         interceptors.add(new AuthInterceptor());
         interceptors.add(new NotNullParaInterceptor("/template/exception.html"));
         interceptors.add(new BusinessExceptionInterceptor("/template/exception.html"));

+ 45 - 0
jboot-admin/src/main/java/io/jboot/admin/controller/system/LogController.java

@@ -0,0 +1,45 @@
+package io.jboot.admin.controller.system;
+
+import com.jfinal.plugin.activerecord.Page;
+import io.jboot.admin.base.rest.datatable.DataTable;
+import io.jboot.admin.base.web.base.BaseController;
+import io.jboot.admin.service.api.LogService;
+import io.jboot.admin.service.entity.model.Log;
+import io.jboot.core.rpc.annotation.JbootrpcService;
+import io.jboot.web.controller.annotation.RequestMapping;
+
+/**
+ * 日志管理
+ * @author Rlax
+ *
+ */
+@RequestMapping("/system/log")
+public class LogController extends BaseController {
+    
+    @JbootrpcService
+    private LogService logService;
+
+    /**
+     * index
+     */
+    public void index() {
+        render("main.html");
+    }
+
+    /**
+     * 表格数据
+     */
+    public void tableData() {
+        int pageNumber = getParaToInt("pageNumber", 1);
+        int pageSize = getParaToInt("pageSize", 30);
+
+        Log log = new Log();
+        log.setIp(getPara("ip"));
+        log.setUrl(getPara("url"));
+        log.setLastUpdAcct(getPara("userName"));
+
+        Page<Log> logPage = logService.findPage(log, pageNumber, pageSize);
+        renderJson(new DataTable<Log>(logPage));
+    }
+    
+}

+ 8 - 0
jboot-admin/src/main/java/io/jboot/admin/support/auth/AuthUtils.java

@@ -11,6 +11,14 @@ import org.apache.shiro.SecurityUtils;
 public class AuthUtils {
 
     /**
+     * 是否登录
+     * @return
+     */
+    public static boolean isLogin() {
+        return ShiroUtils.isAuthenticated();
+    }
+
+    /**
      * 获取平台登录用户
      * @return
      */

+ 60 - 0
jboot-admin/src/main/java/io/jboot/admin/support/log/LogInterceptor.java

@@ -0,0 +1,60 @@
+package io.jboot.admin.support.log;
+
+import com.jfinal.aop.Interceptor;
+import com.jfinal.aop.Invocation;
+import eu.bitwalker.useragentutils.Browser;
+import eu.bitwalker.useragentutils.UserAgent;
+import io.jboot.Jboot;
+import io.jboot.admin.base.web.base.BaseController;
+import io.jboot.admin.service.api.LogService;
+import io.jboot.admin.service.entity.model.Log;
+import io.jboot.admin.service.entity.model.User;
+import io.jboot.admin.support.auth.AuthUtils;
+
+import java.util.Date;
+
+/**
+ * 系统日志拦截器
+ * @author Rlax
+ *
+ */
+public class LogInterceptor implements Interceptor {
+
+	private final static com.jfinal.log.Log logger = com.jfinal.log.Log.getLog(LogInterceptor.class);
+
+	@Override
+	public void intercept(Invocation inv) {
+		if (inv.getController() instanceof BaseController) {
+			BaseController c = (BaseController) inv.getController();
+
+			User user = AuthUtils.getLoginUser();
+			UserAgent userAgent = UserAgent.parseUserAgentString(c.getRequest().getHeader("User-Agent"));
+			Browser browser = userAgent.getBrowser();
+
+			Log log = new Log();
+			log.setUid(user.getId());
+			log.setBrowser(browser.getName());
+			log.setOperation(c.getRequest().getMethod());
+			log.setFrom(c.getReferer());
+			log.setIp(c.getIPAddress());
+			log.setUrl(c.getRequest().getRequestURI());
+			log.setCreateDate(new Date());
+			log.setLastUpdAcct(user.getId() == null ? "guest" : user.getName());
+			log.setLastUpdTime(new Date());
+			log.setNote("记录日志");
+
+			try {
+				LogService logService = Jboot.service(LogService.class);
+				logService.save(log);
+			} catch (Exception e) {
+				logger.error(e.getMessage());
+				e.printStackTrace();
+			} finally {
+				inv.invoke();
+			}
+		} else {
+			inv.invoke();
+		}
+	}
+
+}

+ 101 - 0
jboot-admin/src/main/resources/template/system/log/main.html

@@ -0,0 +1,101 @@
+#include("/template/common/layout/_page_layout.html")
+#@layout()
+
+#define css()
+<style>
+
+</style>
+#end
+
+#define js()
+<script type="text/javascript">
+    layui.use(['table', 'layer'], function () {
+        var table = layui.table
+            , layer = layui.layer
+            , $ = layui.jquery
+            , form = layui.form;
+
+        // 表格渲染
+        var tableIns = table.render({
+            elem: '#dateTable'                  //指定原始表格元素选择器(推荐id选择器)
+            , id: 'dateTable'
+            , even: true //开启隔行背景
+            , size: 'sm' //小尺寸的表格
+            , height: 'full-150'    //容器高度
+            , cols: [[                  //标题栏
+                {checkbox: false, sort: true, fixed: true, space: true}
+                , {field: 'id', title: 'ID', width: 60}
+                , {field: 'lastUpdAcct', title: '用户', width: 100}
+                , {field: 'url', title: '请求url', width: 180}
+                , {field: 'from', title: '来源', width: 180}
+                , {field: 'ip', title: 'ip', width: 140}
+                , {field: 'browser', title: '浏览器', width: 120}
+                , {field: 'operation', title: '操作', width: 80}
+                , {field: 'createDate', title: '访问时间', width: 150}
+            ]]
+            , url: '#(ctxPath)/system/log/tableData'
+            , method: 'get'
+            , request: {
+                pageName: 'pageNumber' //页码的参数名称,默认:page
+                ,limitName: 'pageSize' //每页数据量的参数名,默认:limit
+            }
+            , page: true
+            , limits: [30, 60, 90, 150, 300]
+            , limit: 30 //默认采用30
+            , loading: true
+            , done: function (res, curr, count) {
+            }
+        });
+
+        reloadTableQuery = function () {
+            table.reload('dateTable', {
+                url: '#(ctxPath)/system/log/tableData'
+                ,where: {ip: $('#ip').val(), url: $('#url').val(), userName: $('#userName').val()} //设定异步数据接口的额外参数
+            });
+        }
+
+        reloadTable = function (ip, url, userName) {
+            table.reload('dateTable', {
+                url: '#(ctxPath)/system/log/tableData'
+                ,where: {ip: ip, url: url, userName: userName} //设定异步数据接口的额外参数
+            });
+        }
+
+        form.on('submit(search)', function(data){
+            reloadTable(data.field.ip, data.field.url, data.field.userName);
+            return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
+        });
+    });
+</script>
+#end
+
+#define content()
+    <div class="layui-fluid">
+        <form id="searchForm" class="layui-form x-center" >
+            <div class="layui-form-pane">
+                <div class="layui-form-item">
+                    <label class="layui-form-label">用户名</label>
+                    <div class="layui-input-inline">
+                        <input type="text" id="userName" name="userName" placeholder="用户名" class="layui-input"/>
+                    </div>
+                    <label class="layui-form-label">IP</label>
+                    <div class="layui-input-inline">
+                        <input type="text" id="ip" name="ip" placeholder="IP" class="layui-input"/>
+                    </div>
+                    <label class="layui-form-label">URL</label>
+                    <div class="layui-input-inline">
+                        <input type="text" id="url" name="url" placeholder="请求URL" class="layui-input"/>
+                    </div>
+                    <div class="layui-input-inline" style="width : 80px">
+                        <button class="layui-btn"  lay-submit="" lay-filter="search"><i class="layui-icon">&#xe615;</i></button>
+                    </div>
+                </div>
+            </div>
+        </form>
+        <hr>
+        <div class="layui-row">
+            <table id="dateTable" lay-filter="dateTable"></table>
+        </div>
+    </div>
+
+#end

+ 5 - 0
pom.xml

@@ -46,6 +46,11 @@
                 <artifactId>logback-classic</artifactId>
                 <version>${logback.version}</version>
             </dependency>
+            <dependency>
+                <groupId>eu.bitwalker</groupId>
+                <artifactId>UserAgentUtils</artifactId>
+                <version>1.15</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>