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

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

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
	@GeneratedValue
	private 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类型。
	
	@Transient
	private Date btime; // 起始时间 搜索用到  如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,
	
	public Date getBtime() {
		return btime;
	}
	@Transient
	private 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>{

	@Override
	public 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 {

	@Resource
	private LogService logService;
	
	
	@InitBinder
	public 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{
	@Resource
	private LogRepository logRepository;
	
	@Resource
	private UserRepository userRepository;
	
	@Override
	public 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
	 */
	@Override
	public List<Log> list(Log log, Integer page, Integer pageSize, Direction direction, String... properties) {

		Pageable pageable=new PageRequest(page-1,pageSize,direction,properties);//查询所需参数pageable
		Page<Log> pageLog=logRepository.findAll(new Specification<Log>() {
			
			@Override
			public 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
	 */
	@Override
	public Long getCount(Log log) {

		Long count=logRepository.count(new Specification<Log>() {

			@Override
			public 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值