当前位置: 代码迷 >> 综合 >> Jpa+EasyUI 实现 “日志管理” (@JsonSerialize、对象级联、initBinder、datetimebox、@Temporal)
  详细解决方案

Jpa+EasyUI 实现 “日志管理” (@JsonSerialize、对象级联、initBinder、datetimebox、@Temporal)

热度:85   发布时间:2023-11-24 03:46:27.0

一、写在前面,需要注意的几点

1.@JsonSerialize注解
此注解用于属性或者getter方法上,用于在序列化时嵌入开发者自定义的代码。
使用时先 自定义日期序列化类,比如CustomDateTimeSerializer ,然后再在实体的get方法上加上@JsonSerialize(using = CustomDateTimeSerializer .class)
2.对象级联
大致是这意思:比如日志实体里面还有个对象类型的user属性
在这里插入图片描述
然后前台搜索框中输入的用户名是Log对象(实体)里面的User对象中的一个属性trueName:
在这里插入图片描述
在这里插入图片描述

function formatUser(val,row){
    return val.trueName+" ("+val.userName+") ";}function searchLog(){
    $("#dg").datagrid('load',{
    "type":$("#s_type").combobox("getValue"),"user.trueName":$("s_trueName").val(),"btime":$("#s_btime").datetimebox("getValue"),'etime':$("#s_etime").datetimebox("getValue")});}

然后service实现类中有这样一个条件:
在这里插入图片描述
3.Controller中加上initBinder方法,完成指定日期格式参数绑定

4.datetimebox获取时间
$("#s_btime").datetimebox(“getValue”)

5.@Temporal注解
原文链接:
https://www.cnblogs.com/meng-ma-blogs/p/8474175.html

数据库的字段类型有date、time、datetime
而Temporal注解的作用就是帮Java的Date类型进行格式化,一共有三种注解值:

第一种:@Temporal(TemporalType.DATE)——>实体类会封装成日期“yyyy-MM-dd”的 Date类型。

第二种:@Temporal(TemporalType.TIME)——>实体类会封装成时间“hh-MM-ss”的 Date类型。

第三种:@Temporal(TemporalType.TIMESTAMP)——>实体类会封装成完整的时间“yyyy-MM-dd hh:MM:ss”的 Date类型。

注解方式有两种:

写在字段上:

    @Temporal(TemporalType.TIMESTAMP)private Date birthday;

写在 getXxx方法上:

    @Temporal(TemporalType.DATE)@Column(name = "birthday", length = 10)public Date getBirthday() {
    return this.birthday;}

二、日志实体和表

在这里插入图片描述
表数据:
在这里插入图片描述
实体:

/*** 日志实体* @author Administrator**/
@Entity
@Table(name="t_log")
public class Log {
    public final static String LOGIN_ACTION="登录操作";public final static String LOGOUT_ACTION="注销操作";public final static String SEARCH_ACTION="查询操作";public final static String UPDATE_ACTION="更新操作";public final static String ADD_ACTION="添加操作";public final static String DELETE_ACTION="删除操作";@Id@GeneratedValueprivate Integer id; // 编号@Column(length=100)private String type; // 日志类型@ManyToOne@JoinColumn(name="userId")private User user; // 操作用户@Column(length=1000)private String content; // 操作内容@Temporal(TemporalType.TIMESTAMP) //对Date类型进行格式化private Date time; // 操作日期时间 封装成完整的时间“yyyy-MM-dd hh:MM:ss”的 Date类型。@Transientprivate Date btime; // 起始时间 搜索用到 如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,public Date getBtime() {
    return btime;}@Transientprivate Date etime; // 结束时间 搜索用到 如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient, public void setBtime(Date btime) {
    this.btime = btime;}public Date getEtime() {
    return etime;}public void setEtime(Date etime) {
    this.etime = etime;}public Log() {
    super();}	public Log(String type, String content) {
    super();this.type = type;this.content = content;}public Integer getId() {
    return id;}public void setId(Integer id) {
    this.id = id;}public String getType() {
    return type;}public void setType(String type) {
    this.type = type;}public User getUser() {
    return user;}public void setUser(User user) {
    this.user = user;}public String getContent() {
    return content;}public void setContent(String content) {
    this.content = content;}	@JsonSerialize(using=CustomDateTimeSerializer.class) //自定义日期序列化类public Date getTime() {
    return time;}public void setTime(Date time) {
    this.time = time;}	
}
/*** 自定义返回JSON 数据格式中日期格式化处理*/
public class CustomDateTimeSerializer extends JsonSerializer<Date>{
    @Overridepublic void serialize(Date value, JsonGenerator gen, SerializerProvider serializers)throws IOException, JsonProcessingException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  gen.writeString(sdf.format(value));  }}

三.日志保存 大致流程

1.比如用户 进行登录 操作
在登录成功后调用logService,保存登录这条日志:

logService.save(new Log(Log.LOGIN_ACTION,"用户登录"));

在这里插入图片描述

在这里插入图片描述
2.比如用户添加或者修改了用户信息,当然要将这日志保存起来

/*** 添加或者修改用户信息* @param user* @return* @throws Exception*/@ResponseBody  @RequestMapping("/save")public Map<String,Object> save(User user) throws Exception{
    Map<String,Object> resultMap=new HashMap<>();if(user.getId()==null) {
    if(userService.findByUserName(user.getUserName())!=null) {
    resultMap.put("success", false);resultMap.put("errorInfo", "用户名已存在!");return resultMap;}}if(user.getId()!=null) {
    logService.save(new Log(Log.UPDATE_ACTION,"更新用户信息:"+user));}else {
    logService.save(new Log(Log.ADD_ACTION,"添加用户:"+user));}userService.save(user);resultMap.put("success", true);return resultMap;}

四、日志后台管理 分页、多条件查询

在这里插入图片描述
1.页面easyui和js代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>系统日志</title>
<link rel="stylesheet" type="text/css" href="/static/jquery-easyui-1.3.3/themes/default/easyui.css"></link>
<link rel="stylesheet" type="text/css" href="/static/jquery-easyui-1.3.3/themes/icon.css"></link>
<script type="text/javascript" src="/static/jquery-easyui-1.3.3/jquery.min.js"></script>
<script type="text/javascript" src="/static/jquery-easyui-1.3.3/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/static/jquery-easyui-1.3.3/locale/easyui-lang-zh_CN.js"></script><script type="text/javascript">function formatUser(val,row){
    return val.trueName+"&nbsp;("+val.userName+")&nbsp;";}//多条件搜索框function searchLog(){
    $("#dg").datagrid('load',{
    "type":$("#s_type").combobox("getValue"),"user.trueName":$("s_trueName").val(),"btime":$("#s_btime").datetimebox("getValue"),'etime':$("#s_etime").datetimebox("getValue")});}//重置输入框function resetValue(){
    $("#s_type").combobox("setValue","");$("#s_trueName").val("");$("#s_btime").datetimebox("setValue","");$("#s_etime").datetimebox("setValue","");}
</script></head>
<body style="margin: 1px"><table id="dg" title="系统日志" class="easyui-datagrid"fitColumns="true" pagination="true" rownumbers="true" singleSelect="true"url="/admin/log/list" fit="true" toolbar="#tb"><thead><th field="id" width="20" align="center">编号</th><th field="type" width="30" align="center">日志类型</th><th field="user" width="50" align="center" formatter="formatUser">操作用户</th><th field="time" width="50" align="center">操作时间</th><th field="content" width="250" align="left">操作内容</th></thead></table><div id="tb"><fieldset style="border-color: #E7F0FF"><legend>查询设置</legend>&nbsp;查询设置&nbsp;<select class="easyui-combobox" id="s_type" style="width: 154px" editable="false" panelHeight="auto"><option value="">所有类型</option><option value="登录操作">登录操作</option><option value="注销操作">注销操作</option><option value="查询操作">查询操作</option><option value="更新操作">更新操作</option><option value="添加操作">添加操作</option><option value="删除操作">删除操作</option></select>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;操作用户:&nbsp;<input type="text" id="s_trueName" size="20" onkeydown="if(event.keyCode==13) searchLog()"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;操作时间:&nbsp;<input id="s_btime" class="easyui-datetimebox" editable=false style="width:150px"/>&nbsp;&nbsp;-&nbsp;&nbsp;<input id="s_etime" class="easyui-datetimebox" editable=false style="width:150px"/>&nbsp;&nbsp;<a href="javascript:searchLog()" class="easyui-linkbutton" iconCls="icon-search" plain="true">搜索</a>&nbsp;&nbsp;<a href="javascript:resetValue()" class="easyui-linkbutton" iconCls="icon-reset" plain="true">重置</a></fieldset></div>
</body>
</html>
  1. Controller层
/*** 后台管理用户Controller* @author Administrator**/
@RestController
@RequestMapping("/admin/log")
public class LogAdminController {
    @Resourceprivate LogService logService;@InitBinderpublic void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");dateFormat.setLenient(true);binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));   //true:允许输入空值,false:不能为空值}/*** 根据条件分页查询日志信息* @param log* @param page* @param rows* @return* @throws Exception*/@RequestMapping("/list")@RequiresPermissions(value="系统日志")  //当前用户必须拥有 此权限才能访问此方法public Map<String,Object> list(Log log,@RequestParam(value="page",required=false)Integer page,@RequestParam(value="rows",required=false)Integer rows)throws Exception{
    Map<String,Object> resultMap=new HashMap<>();List<Log> logList=logService.list(log, page, rows, Direction.DESC, "time");Long total=logService.getCount(log);resultMap.put("rows", logList);resultMap.put("total", total);return resultMap;}}

3.Service实现类

@Service("logService")
public class LogServiceImpl implements LogService{
    @Resourceprivate LogRepository logRepository;@Resourceprivate UserRepository userRepository;@Overridepublic void save(Log log) {
    log.setTime(new Date()); //设置操作日期//设置当前用户log.setUser(userRepository.findByUserName((String) SecurityUtils.getSubject().getPrincipal()));logRepository.save(log);}/*** 根据条件分页查询日志信息* @param log* @param page* @param pageSize* @param direction* @param properties* @return*/@Overridepublic List<Log> list(Log log, Integer page, Integer pageSize, Direction direction, String... properties) {
    Pageable pageable=new PageRequest(page-1,pageSize,direction,properties);//查询所需参数pageablePage<Log> pageLog=logRepository.findAll(new Specification<Log>() {
    @Overridepublic Predicate toPredicate(Root<Log> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    Predicate predicate=cb.conjunction();//存储下面构造的查询条件if(log!=null) {
    if(StringUtil.isNotEmpty(log.getType())) {
    predicate.getExpressions().add(cb.like(root.get("type"), log.getType()));}if(log.getUser()!=null && StringUtil.isNotEmpty(log.getUser().getTrueName())) {
    predicate.getExpressions().add(cb.like(root.get("user").get("trueName"), "%"+log.getUser().getTrueName()+"%"));}if(log.getBtime()!=null) {
    predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get("time"), log.getBtime()));}if(log.getEtime()!=null) {
    predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("time"), log.getEtime()));}}return predicate;}}, pageable);	return pageLog.getContent();}/*** 获取总记录数* @param log* @return*/@Overridepublic Long getCount(Log log) {
    Long count=logRepository.count(new Specification<Log>() {
    @Overridepublic Predicate toPredicate(Root<Log> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    Predicate predicate=cb.conjunction();//存储下面构造的查询条件if(log!=null) {
    if(StringUtil.isNotEmpty(log.getType())) {
    predicate.getExpressions().add(cb.like(root.get("type"), log.getType()));}if(log.getUser()!=null && StringUtil.isNotEmpty(log.getUser().getTrueName())) {
    predicate.getExpressions().add(cb.like(root.get("user").get("trueName"), "%"+log.getUser().getTrueName()+"%"));}if(log.getBtime()!=null) {
    predicate.getExpressions().add(cb.greaterThanOrEqualTo(root.get("time"), log.getBtime()));}if(log.getEtime()!=null) {
    predicate.getExpressions().add(cb.lessThanOrEqualTo(root.get("time"), log.getEtime()));}}return predicate;}});return count;}}

完整代码地址:
https://gitee.com/never_enough/jxc_system/tree/master

  相关解决方案