EasyUI + Spring MVC + hibernate实现增删改查导入导出
Posted 小赞的技术园子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EasyUI + Spring MVC + hibernate实现增删改查导入导出相关的知识,希望对你有一定的参考价值。
(这是一个故事……)
前言作为一个JAVA开发工程师,我觉得最基本是需要懂前端、后台以及数据库。
练习的内容很基础,包括:基本增删改查、模糊查询、分页查询、树菜单、上传下载、tab页
主管发我一个已经搭建好的框架平台,在平台上进行编码,不限制技术。
虽然说不限制技术,但还是得根据已经搭建的框架平台进行编码。
所以首先第一步,分析框架平台结构组成。
入手:看目录、看配置、看jar包、看js库、看数据库...
不难发现项目是基于:Spring + Hibernate + Spring MVC + EasyUI + mysql
除了基本框架外,完成我需要的功能,平台还提供了如下Java类库和JS插件:
zTree:树菜单
POI:Excel读写
需求不难,可是对于Spring MVC和EasyUI,我算是第一次使用。
我之前用过Struts2和DWZ。这次Spring MVC替代了Strut2、EasyUI替代了DWZ。
我觉得曾经接触过类似东西的话,再学同类型的就会容易上手。所以我对我自己有信心。
当要完成一个完整的功能的时候,我3/4的时间花在了前端数据展示和前端后台数据交互上。
大部分细节的问题,都需要前端的处理,同时也需要后台的配合。
做项目绝对不能盲目开始,必须先掌握基本的理论知识。
首先展示一下效果:
![](https://image.cha138.com/20210612/2376921499944a9abefb85c0e0c2cd97.jpg)
EasyUI
它做出来的应用是一个富客户端。
大概的特点是:所有资源文件只加载一次,页面局部刷新,所有请求都基于ajax请求,所有打开的tab页在同一个浏览器窗口算是同一个页面,这个就要注意当通过id(在同一个页面应该是唯一的)或者name(如果同一个页面存在相同的name)获取页面元素的值时的问题。
树菜单
![](https://image.cha138.com/20210612/87438fc875f04c4cb565c24ec8ee4e85.jpg)
这是个4级菜单,在一个表中,每一行数据含有以上4个列。根据Hibernate一个实体bean对应一个表的思想,这4列就是bean的4个属性。在整个功能需求中,都是对单表进行操作。
菜单要求的层级关系为:所属城市 =》 设备类型 =》 设备型号 =》 设备名,即对一个设备进行分类显示。
对于树菜单,现成的插件有EasyUI自带的插件和zTree。因为我之前有接触过zTree,但还没用过EasyUI的树菜单插件,所以我用zTree实现这一功能。(我加入了zTree的技术交流群(1806431),群老大就是写zTree插件的人,他告诉我,基于EasyUI开发的话,其实用EasyUI自带树菜单插件更好,而且它自身的树菜单功能强大,整合得更好。后续会学习,暂时是用zTree实现了)
zTree支持两种格式的JSON数据:
![](https://image.cha138.com/20210612/431f6883549f439f9f38e8b1820cc885.jpg)
![](https://image.cha138.com/20210612/838dec9c951341be8056a98a670ceced.jpg)
平台提供了一个zTree的实体bean。
![](https://image.cha138.com/20210612/a47d4672da3842d19a383d8f125baec5.jpg)
上面的属性跟zTree的插件本身定义的属性是一一对应的,这样可以方便转换成JSON之后直接生成树菜单,而无须重新指定属性。
需要注意的是:url赋的值默认就是在zTree的树菜单中的a标签的href的值。在EasyUI中,当点击菜单节点,会打开一个新的浏览器窗口,这肯定是不符合要求的。API中如下说明,可以重新指向属性,其他重新指向属性原理相同,具体查看API。
![](https://image.cha138.com/20210612/59c1795078af403cbca61877339c850c.jpg)
Spring MVC返回JSON需要添加@ResponseBody注解
![](https://image.cha138.com/20210612/d7de0608499a4d6ebcbba4630908cb8d.jpg)
根据我的bean生成的JSON为标准JSON格式,可以直接使用(我一开始还傻傻的将它拆来拼成简单格式的JSON,后来发现傻了~)
![](https://image.cha138.com/20210612/3ddf748a49164272b4eed17602e36cf0.jpg)
![](https://image.cha138.com/20210612/d86207d9a5024834b168485fd5cb78f7.jpg)
![](https://image.cha138.com/20210612/70191b0a82774530af91d8714ed6444e.jpg)
![](https://image.cha138.com/20210612/571ea00c94c1437f896694a7fef81fc8.jpg)
我指定当节点被点击时执行onClick()函数
![](https://image.cha138.com/20210612/d1b3ed733ab446e7acc66afbec62406c.jpg)
![](https://image.cha138.com/20210612/80b3616f8d884f0e81d412e28f4eb88c.jpg)
至于JAVA,首先不知道好不好,但还是实现了,分享一下我的思路:
1、从数据库获取所有的设备信息
1、从数据库获取所有的设备信息
2、遍历将设备信息按城市分类
![](https://image.cha138.com/20210612/e74f138641974435a76b9d288ff6ddce.jpg)
3、遍历Map,将List传入添加子结点
![](https://image.cha138.com/20210612/33529e6e583f449e9d578c3a9f45b16c.jpg)
4、同理先分类,再将List传入进行下一级分类,最后得到的就是一个树结构
这功能,第一次也是大概这样的思路,但是查数据库实现分类的,结果查了N次数据库,那肯定是不行的,然后就改成了这样只查一次数据库,再遍历处理数据。虽然写得不是很好,但功能是实现了。期待更好的思路~
查询
查询包括了模糊查询和分页查询
![](https://image.cha138.com/20210612/f7ac71e969424c5fa89a1fbb554982a1.jpg)
![](https://image.cha138.com/20210612/b4dfc0d2db2e43288841c77ea21f80e7.jpg)
新手做这个功能的时候都是一步一步慢慢演变成完整功能的。(过程略……)
为了确保查询条件的不变,我需要设置一个隐藏的表单,存储查询条件,当点击分页工具栏的按钮时,获取隐藏表单的数据作为分页条件,进行分页查询。所以当我们点击查询按钮的时候,实际上先将表单中的数据赋值到隐藏表单中,然后触发分页查询。通过$(\'#dTable\').datagrid(\'reload\');即可以重新加载表格。
![](https://image.cha138.com/20210612/3bcb44f7acab4cdc941efe5f3f350907.jpg)
EasyUI获取下拉或者日期控件的值需要采用控件的方法去获取
在EasyUI中,每一个控件都含有属性,事件和方法。
大概用法是:
$("#id").控件名(\'方法名\', {
属性名:属性值,
事件名:function(){
}
});
具体的查看API
新增和修改
这个看似两个功能,但传到后台java处理是对应同一个处理。对应的是saveOrUpdate方法。
hibernate中提供了saveOrUpdate方法实现保存或更新操作。
saveOrUpdate方法:如果设置了主键则执行update操作,如果主键为null(null和“”是有区别的,jsp获取到的空值为"",我们需要将其置为null)则执行inset操作 。
![](https://image.cha138.com/20210612/124b0ad2c7b14d74a651a2bf31c0fb59.jpg)
至于前端页面,肯定打开的是同一个窗口,但是点击【新增】和【更新】按钮时需要修改窗口内的相应值,最后获取值通过Ajax提交即可。
![](https://image.cha138.com/20210612/9b843c0a6e1d460eb610b0bfbbb36dbf.jpg)
![](https://image.cha138.com/20210612/82f5d264fc4d4931bd28a29ebdc78a65.jpg)
删除
删除和新增、跟新都需要为方法添加事务注解,否则运行不报错,但数据库数据死活不变
![](https://image.cha138.com/20210612/f27beb0b817743639faabf492f4eb0cb.jpg)
到这里,应该注意到,新增、修改、删除都对设备信息造成影响,那么我们应该重新获取菜单和表格的数据,同时下拉框(我的下拉选项是当前存在在数据库的分类)的数据也要相应变化。
导入/上传
![](https://image.cha138.com/20210612/9b5488e9829e4b4b940c4d5093a2f04d.jpg)
那个上传的地址后面有个/,我搞了半天上传不了,结果是少了一个/
![](https://image.cha138.com/20210612/c189b5bdbbb64bb98860c34c2cd74760.jpg)
基本都是固定的
导出/下载
Spring MVC的下载也是相对固定的,最后返回的是一个byte数组,只要将需要下载的内容转换为byte数组,就可以实现下载。
![](https://image.cha138.com/20210612/3bfb4b4cb3434cffb2456958f1484386.jpg)
![](https://image.cha138.com/20210612/088f4a2776364256947dc05382c07f04.jpg)
简单地通过window.open就可以打开下载的窗口
![](https://image.cha138.com/20210612/7dc15381d1cc43a49ecf6943253e5c9f.jpg)
但当我通过window.open传递中文时,出现乱码,经查阅资料,可以用过encodeURL编码url,然后在JAVA再通过URLDecoder.decode解码即可解决中文乱码问题
POI读写
主要就基本步骤:
1、创建Excel工作簿:Workbook
2、在Workbook创建工作表Sheet
3、在Sheet创建行Row
4、在行Row创建单元格Cell
![](https://image.cha138.com/20210612/2e1d602ebd7248f0bd74076fbe840fe8.jpg)
对于Excel,POI有三个实现了Workbook接口的对象,分别是:
HSSFWorkbook:主要用于创建2003版格式的Excel,文件后缀为.xls,数据量大会报错
XSSFWorkbook:主要用于创建2007版格式的Excel,文件后缀为.xlsx,对于数据量大需要使用此类
SXSSFWorkbook:扩展了XSSFWorkbook,提高了性能
![](https://image.cha138.com/20210612/a8aa585771284ec1882d8896784fb6a0.jpg)
这样就可以生成baye数组
远程验证
<input class="easyui-textbox easyui-validatebox" type="text" id="wid" name="id" required="true" invalidmessage="设备ID已存在" missingMessage="设备ID不能为空" validType="remote[\'validateId\', \'id\']" />
有资料显示使用data-options的方法设置远程验证,结果出现单双引号混合使用的情况,导致不能正确执行,不知道有没有解,然后我就用了上面这种方式写,没问题
EasyUI1.3.6 TextBox
动态启动禁用验证
$("#wid").removeAttr("readonly");
$(\'#wid\').validatebox(\'reduce\'); // 恢复 $("#wid").attr("readonly", "readonly");// ID列不能改
$(\'#wid\').validatebox(\'remove\'); // 删除
/* 动态禁用启用验证 */
$.extend($.fn.validatebox.methods, {
remove : function(jq, newposition) {
return jq.each(function() {
$(this).removeClass("validatebox-text validatebox-invalid").unbind(
\'focus\').unbind(\'blur\');
});
},
reduce : function(jq, newposition) {
return jq.each(function() {
var opt = $(this).data().validatebox.options;
$(this).addClass("validatebox-text").validatebox(opt);
});
}
EasyUI1.3.6 TextBox
首先非常感谢 潇洒一剑 一丝不苟的态度,从图片中就看出了我的问题,并慷慨的为我指出。
首先症状就是如图, 这两个文本框的边框跟其他控件的不一致。
![](https://image.cha138.com/20210612/a607238075d643238bfb2c98112e0af3.jpg)
但是呀,我的确是按照网上的设置做的了呀,怎么就死活不出来呢
![](https://image.cha138.com/20210612/273b58ab2ff94e0fab8713e3c7aac48d.jpg)
查看了easyui.css文件,文件里有该样式:
![](https://image.cha138.com/20210612/342dc03edef5427f8de1a972c16a361f.jpg)
然后我将“easyui-”去掉,结果文本框变小了,也不符合要求
![](https://image.cha138.com/20210612/6d316ac1f141469e858e6cedb9197ff3.jpg)
然后嘛,跟在技术群上问了这个问题。
非常感谢树哥告诉我EasyUI英文在线API网址:
http://www.jeasyui.com/documentation/index.php#
API提供说明如下:
![](https://image.cha138.com/20210612/c5d2ca24adb54050b5a852793e078f5d.jpg)
第一种方式不行,我就尝试了第二种方式,结果报如下错误:
Uncaught TypeError: $(...).textbox is not a function
![](https://image.cha138.com/20210612/54626a4150c643fd87cffb357d79c48d.jpg)
在群上最终也没有得到答案。
突然想起EasyUI的压缩包里有Demo,看了Demo发现如下:
![](https://image.cha138.com/20210612/b1bcf6951e374fd292208876fe212a46.jpg)
![](https://image.cha138.com/20210612/13bff21bf03a445097aafb1bdcd9b2b0.jpg)
<style scoped="scoped">说明该样式是其父元素范围内有效。具体说明,可参考:http://blog.csdn.net/chelen_jak/article/details/18092947
将其套入到我应用中,得到了想要的结果:
![](https://image.cha138.com/20210612/198ae5c59b3b4f82b75b22b2fd52a729.jpg)
其实EasyUI1.3.6尚未引入textbox组件,在EasyiUI1.4以上的版本才能使用:
![](https://image.cha138.com/20210612/79451ff55b3c4f8b8114233844270078.jpg)
另外发现一开发神器:
Eclipse反编译插件 :Eclipse Class Decompiler
附件列表
以上是关于EasyUI + Spring MVC + hibernate实现增删改查导入导出的主要内容,如果未能解决你的问题,请参考以下文章
EasyUI + Spring MVC + hibernate实现增删改查导入导出
spring MVC +freemarker + easyui 实现sql查询和执行小工具总结
Spring MVC整合fastjsonEasyUI乱码问题
使用Jquery-easyUI的datagrid从后台加载数据不成功的解决办法