1 环境搭建
该系统使用了adminLTE脚手架
address:adminlte.io
1.1 数据库
set names utf8; 设置编码格式
source d:/jtsys.sql 执行脚本
1.2 修改idea编码
1.3 application.yml文件配置
#server
server:
port: 80
servlet:
context-path: /
#spring
spring:
datasource:
url: jdbc:mysql://localhost:3306/dbsys?serverTimezone=GMT%2B8&characterEncoding=utf8
username: root
password: root
thymeleaf:
cache: false
prefix: classpath:/templates/pages/
suffix: .html
#mybatis
mybatis:
mapper-locations: classpath:/mapper/*/*.xml
configuration:
default-statement-timeout: 60
map-underscore-to-camel-case: true
#log
logging:
level:
com.cy: debug
file:
path: d:/dblogs/
1.4 创建页面controller
package com.cy.pj.sys.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
//通过此controller处理页面请求
@Controller
@RequestMapping("/")
public class PageController { //Handler:请求响应逻辑的处理对象
//显示首页
@GetMapping("doIndexUI")
public String doIndexUI() {
return "starter";
}
//返回数据列表组件
@GetMapping("/log/log_list")
public String doLogUI() {
return "sys/log_list";
}
//返回分页组件
@GetMapping("doPageUI")
public String doPageUI() {
return "common/page";
}
1.5 日志菜单事件处理
首先准备日志列表页面(/templates/pages/sys/log_list.html),然后在starter.html页面中点击日志管理菜单时异步加载日志列表页面
//$(function(){ //jquery中提供的页面加载完成以后要执行的函数
$(()=>{
doLoadUI("load-log-id", "log/log_list");
doLoadUI("load-menu-id", "menu/menu_list");
})
function doLoadUI(id, url){
//$("#"+id).click(function(){
$("#"+id).click(()=>{
$("#mainContentId").load(url);
});
}
1.6 日志列表页面事件处理
当日志列表页面加载完成以后异步加载分页页面(page.html)。
在log_list.html页面中异步加载page页面,这样可以实现分页页面重用,哪里需要分页页面,哪里就进行页面加载即可。关键代码如下:
$(function(){
$("#pageId").load("doPageUI");
});
2 日志管理设计与实现
2.1 创建pojo
package com.cy.pj.sys.pojo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/*
pojo对象分为
1、do/po:数据逻辑层封装数据的对象
2、bo:业务逻辑层封装数据的对象
3、vo:控制逻辑层封装数据的对象
4、dto:跨进程数据通讯时封装数据的对象
FAQ:
1、序列化;将对象转换为字节的过程,转换以后便于通过网络进行传输或存储到相关介质中
2、反序列化:将字节转换为对象的过程
建议:在java中所有存储数据的对象都实现Serializable接口
*/
@Data
public class SysLog implements Serializable {
/*
settings->inspections->Java->Serialization issues
选中Serializable class without 'serialVersionUID'
idea自动生成序列化号快捷键:alt+enter
*/
private static final long serialVersionUID = -1592163223057343412L;
private Integer id;
private String username; //用户名
private String operation; //用户操作
private String method; //请求方法
private String params; //请求参数
private Long time; //执行时长(毫秒)
private String ip; //IP地址
private Date createdTime; //创建时间
}
2.2 dao接口实现
package com.cy.pj.sys.dao;
import com.cy.pj.sys.pojo.SysLog;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysLogDao { //系统底层会基于接口产生JDK Proxy (这个代理对象实现了SysLogDao接口)
/**
* 基于条件查询日志总记录数
* @param username
* @return 总记录数
*/
int getRowCount(String username);
/**
* 分页查询当前页用户日志数据
* @param username 用户名
* @param startIndex 起始位置
* @param pageSize 每页显示记录数
* @return 查询到的当前页的日志记录
*/
List<SysLog> findPageObjects(@Param("username")String username, @Param("startIndex")Integer startIndex, @Param("pageSize")Integer pageSize);
}
2.3 Mapper文件实现
在映射文件的设计目录(mapper/sys)中添加SysLogMapper.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.cy.pj.sys.dao.SysLogDao">
<sql id="queryWhereId">
from sys_logs
<where>
<if test="username!=null and username!=''">
username like concat("%", #{username}, "%")
</if>
</where>
</sql>
<select id="findPageObjects" resultType="com.cy.pj.sys.pojo.SysLog">
select *
<include refid="queryWhereId" ></include>
order by createdTime desc
limit #{startIndex}, #{pageSize}
</select>
<select id="getRowCount" resultType="int">
select count(*)
<include refid="queryWhereId" ></include>
</select>
<mapper/>
2.4 对数据层方法进行测试
编写单元测试类SysLogDaoTests,对数据层方法进行测试。
package com.cy.pj.sys.dao;
import com.cy.pj.sys.pojo.SysLog;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class SysLogDaoTests {
@Autowired
private SysLogDao sysLogDao;
@Test
void testGetRowCount() {
int rowCount=sysLogDao.getRowCount("admin");
System.out.println("rowCount=" + rowCount);
}
@Test
void testFindPageObjects() {
List<SysLog> list = sysLogDao.findPageObjects("admin", 0, 3);
/*for(SysLog sysLog : list) {
System.out.println(sysLog);
}*/
list.forEach((sysLog)->System.out.println(sysLog));
}
}
2.5 Service接口及实现类
1、业务描述与设计实现
业务层主要是实现模块中业务逻辑的处理。在日志分页查询中,业务层对象首先要通过业务方法中的参数接收控制层数据(例如username,pageCurrent)并校验。然后基于用户名进行总记录数的查询并校验,再基于起始位置及页面大小进行当前页记录的查询,最后对查询结果进行封装并返回。
2、关键代码设计及实现
业务值对象定义,基于此对象封装数据层返回的数据以及计算的分页信息。
创建包:com.cy.pj.common.pojo
package com.cy.pj.common.pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
//在业务层封装业务逻辑结果
@Data
@NoArgsConstructor
public class PageObject<T> implements Serializable { //类名<泛型>;类泛型;约束类中属性、方法参数以及返回值类型
private static final long serialVersionUID = 1249348157133284936L; //自动生成序列化号快捷键:alt+enter
private Integer rowCount; //总记录数(通过查询获得)
private List<T> records; //当前页记录
private Integer pageCount; //总页数(通过计算获得)
private Integer pageCurrent; //当前页的页码值
private Integer pageSize; //每页显示记录数;页面大小
public PageObject(Integer rowCount, List<T> records, Integer pageCurrent, Integer pageSize) {
this.rowCount = rowCount;
this.records = records;
this.pageCurrent = pageCurrent;
this.pageSize = pageSize;
this.pageCount = rowCount/pageSize;
if(this.rowCount%this.pageSize!=0){
this.pageCount++;
}
}
}
2.6 定义日志业务接口及方法,暴露外界对日志业务数据的访问
package com.cy.pj.sys.service;
import com.cy.pj.common.pojo.PageObject;
import com.cy.pj.sys.pojo.SysLog;
public interface SysLogService {
/**
* 定义日志业务接口及方法,暴露外界对日志业务数据的访问
* @param username
* @param pageCurrent
* @return
*/
PageObject<SysLog> findPageObjects(String username, Integer pageCurrent);
}