后台首页
通用的页面跳转
package com.jt.manage.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 通用的页面跳转控制器
*/
@RequestMapping(value = "/page")
@Controller
public class PageController {
@RequestMapping(value = "/{pageName}")
public String toPage(@PathVariable("pageName") String pageName) {
return pageName;
}
}
RESTFul方式请求
EasyUI富客户端
jQuery EasyUI 提供了用于创建跨浏览器网页的完整的组件集合,包括功能强大的 datagrid(数据网格)、treegrid(树形表格)、 panel(面板)、combo(下拉组合)等等。 用户可以组合使用这些组件,也可以单独使用其中一个。
插件列表如下:
分类 | 插件 |
Base(基础) |
|
Layout(布局) |
|
Menu(菜单)与 Button(按钮) |
|
Form(表单) |
|
Window(窗口) |
|
DataGrid(数据网格)与 Tree(树) |
|
执行过程:
页面控制:通过在div等标签上加特定的属性,引入easyUI js后,通过js进行相应的处理。或渲染,或者进行数据判断等等。
数据控制:页面通过ajax提交,在controller中准备数据,形成json串格式,返回页面,EasyUI拿到数据json串,利用自身提供的js函数来渲染EasyUI组件。
引入js支持:
<link rel="stylesheet" type="text/css" href="/js/jquery-easyui-1.4.1/themes/default/easyui.css" />
<link rel="stylesheet" type="text/css" href="/js/jquery-easyui-1.4.1/themes/icon.css" />
<script type="text/javascript" src="/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript" src="/js/jquery-easyui-1.4.1/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/js/jquery-easyui-1.4.1/locale/easyui-lang-zh_CN.js"></script>
布局layout
<body class="easyui-layout">
<div data-options="region:'west',title:'菜单',split:true" style="width:180px;"></div>
<div data-options="region:'center',title:''"></div>
</body>
菜单menu
ul和li组合形成多级结构
<ul id="menu" class="easyui-tree">
<li>
<span>第一级菜单</span>
<ul>
<li data-options="attributes:{'url':'/page/item-add'}">新增商品</li>
</ul>
</li>
</ul>
页夹Tabs
点击自动创建一个新页夹,页夹之间可以随意切换
<div id="tabs" class="easyui-tabs">
<div title="首页" style="padding:20px;">
</div>
</div>
注意:iframe。如果多个表格控件时,它们的值POST发生冲突。参数同名。修改成不同名称。
弹出窗口Window
$("<div>").css({padding:"5px"}).html("<ul>")
.window().window('open');
$(this).window("destroy");
点击自动创建一个新页夹,页夹之间可以随意切换。
树形组件Tree
$("ul",_win).tree({(url:ajax访问链接)
链接按钮
<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">选择类目</a>
提示框
$.messager.alert('提示','表单还未填写完成!');
页面校验
页面加了校验EasyUI(在表单的元素上增加属性,提交时,被js方法拦截,按特殊的属性进行校验,校验通过继续提交到后台,如果校验失败,在对应的元素后面增加错误提示。)
例如:商品信息的校验
标题 | class="easyui-textbox" data-options="required:true" 必填 |
卖点 | class="easyui-textbox" data-options="multiline:true,validType:'length[0,150]'" |
价格 | class="easyui-numberbox" data-options="min:1,max:99999999,precision:2,required:true" |
库存数量 | class="easyui-numberbox" data-options="min:1,max:99999999,precision:0,required:true" |
条形码 | class="easyui-textbox" data-options="validType:'length[1,30]'" |
提交 | class="easyui-linkbutton" οnclick="submitForm()" |
实现商品分类树功能
拷贝后台资源
链接:https://pan.baidu.com/s/1w1YzPedd_s9m-_WzqKpDpA
提取码:9d1l
链接:https://pan.baidu.com/s/1GEQZwqYzGG97vsxwdxBSUg
提取码:72s1
表设计
EasyUI异步加载树要求
- id: 节点id,它是重要的来加载远程数据
- text: 节点文本来显示
- state: 节点状态,“open”或“closed”,默认是“open”。当设置为“closed”,节点有子节点,并将负载从远程站点
需要POJO对象增加两个属性,以满足返回的json格式要求
// 扩展get方法,满足EasyUI的tree格式
public String getText() {
return getName();
}
public String getState() {
return getIsParent() ? "closed" : "open";
}
EasyUI异步加载树工作原理
用户创建一个空的树,然后指定一个服务器端动态返回JSON数据用来填充树与异步和需求。子节点加载依赖父节点状态。当扩展一个封闭的节点,如果节点没有子节点加载,它将发送节点id的值作为http请求参数命名为“id”到服务器上面定义通过URL检索的子节点。
商品分类树加载执行过程
用户点击EasyUI的selectItemCat按钮,调用页面加载时的jQuery的KindEditorUtil.init()方法,KindEditorUtil为在common.js中定义的js对象。在init方法中调用this.initItemCat(data)。Each遍历找到selectItemCat元素,给其绑定onclick事件,onclick事件中创建window窗口,在窗口的ul上加载EasyUITree。异步post提交,通过url(/item/cat/list)指定调用路径,通过注解找到ItemCatController,执行它的queryList方法,controller中调用service层,执行ItemCatService的queryListById方法,service中调用mybatis的mapper接口,调用 queryListById方法,其执行ItemCatMapper.xml文件中配置的queryListById。执行SQL语句。查询后返回ItemCat对象集合,并由springmvc的注解@ResponseBody将java对象转换为json串,最终返回给js,EasyUI解析并显示树形结构。
开发步骤
EasyUI.tree树为异步加载,点开树枝,才显示下级节点。将传递参数,父节点的id,默认第一次页面传值为0。
第一步:在item-add.jsp页面中调用js事件。
<tr>
<td>商品类目:</td>
<td>
<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">选择类目</a>
<input type="hidden" name="cid" style="width: 280px;"></input>
</td>
</tr>
在a标签上的class属性中,绑定了easyui的按钮,设定class名称为selectItemCat,在js中将利用这个class来绑定onclick事件。隐藏域用来返回用户选择树节点的值。
第二步:调用common.js中的initItemCat
……
initItemCat : function(data){
$(".selectItemCat").each(function(i,e){//i= index 下标,e:element:元素
var _ele = $(e);
if(data && data.cid){
_ele.after("<span style='margin-left:10px;'>"+data.cid+"</span>");
}else{
_ele.after("<span style='margin-left:10px;'></span>");
}
_ele.unbind('click').click(function(){
$("<div>").css({padding:"5px"}).html("<ul>")
.window({
width:'500',
height:"450",
modal:true,
closed:true,
iconCls:'icon-save',
title:'选择分类',
onOpen : function(){ //当窗口打开后执行
var _win = this; //this就指向当前的window
$("ul",_win).tree({
url:'/item/cat/list',
animate:true,
onClick : function(node){
//只有当是叶子节点时,才进行处理
if($(this).tree("isLeaf",node.target)){
// 填写到cid中
//_ele.parent,在当前元素的父对象,目的缩小查询范围 _ele.parent().find("[name=cid]").val(node.id);
//find(“[name=cid]”)通过jQuery的选择器,通过一个属性进行选择name=cid的
//元素后面,加上选择节点的文字。
_ele.next().text(node.text).attr("cid",node.id);
$(_win).window('close');
if(data && data.fun){
data.fun.call(this,node);
}
}
}
});
},
onClose : function(){
$(this).window("destroy");
}
}).window('open');
});
});
},
……
第三步:pojo
创建ItemCat pojo继承BasePojo;增加getText方法,为easy准备。
package com.jt.manage.pojo;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name = "tb_item_cat")
public class ItemCat extends BasePojo{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
// 主键自增长策略
private Long id;
// 父类目ID=0时,代表的是一级的类目
@Column(name = "parent_id")
private Long parentId;
private String name;
// 状态。可选值:1(正常),2(删除)
private Integer status;
// 排列序号,表示同级类目的展现次序,如数值相等则按名称次序排列。取值范围:大于零的整数
@Column(name = "sort_order")
private Integer sortOrder;
// 该类目是否为父类目,1为true,0为false
@Column(name = "is_parent")
private Boolean isParent;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getSortOrder() {
return sortOrder;
}
public void setSortOrder(Integer sortOrder) {
this.sortOrder = sortOrder;
}
public Boolean getIsParent() {
return isParent;
}
public void setIsParent(Boolean isParent) {
this.isParent = isParent;
}
// 扩展get方法,满足EasyUI的tree格式
public String getText() {
return getName();
}
public String getState() {
return getIsParent() ? "closed" : "open";
}
第四步:controller层
package com.jt.manage.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.jt.manage.pojo.ItemCat;
import com.jt.manage.service.ItemCatService;
/**
* 商品类目相关的业务逻辑处理
*
*/
@RequestMapping("/item/cat")
@Controller
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
@RequestMapping("list")
@ResponseBody
public List<ItemCat> queryList(@RequestParam(value="id", defaultValue="0") Long id){
return this.itemCatService.queryListById(id);
}
}
第五步:service层
package com.jt.manage.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jt.manage.mapper.ItemCatMapper;
import com.jt.manage.pojo.ItemCat;
@Service
public class ItemCatService extends BaseService<ItemCat> {
@Autowired
private ItemCatMapper itemCatMapper;
public List<ItemCat> queryListById(Long id) {
return this.itemCatMapper.queryListById(id);
}
}
第六步:interface接口
package com.jt.manage.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.jt.manage.mapper.base.mapper.SysMapper;
import com.jt.manage.pojo.ItemCat;
public interface ItemCatMapper extends SysMapper<ItemCat>{
/**
* 根据ID查询商品分类数据,parentId = id(参数)
*
* @param id
* @return
*/
List<ItemCat> queryListById(@Param("id") Long id);
}
第七步:mapper映射文件
<?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.jt.manage.mapper.ItemCatMapper">
<select id="queryItemCat" parameterType="long" resultType="ItemCat">
SELECT * FROM tb_item_cat WHERE STATUS=1 AND parent_id=#{id}
ORDER BY parent_id,sort_order
</select>
</mapper>
弹出窗口的调用过程
常见问题
trycatch能否写在service层?
service层受spring的事务保护,如果在service层进行trycatch将破坏spring的回滚机制,造成无法回滚。因为spring看到有try,认定客户要自己处理,所以不再执行回滚操作。因此需要try时,应该写在controller层。
将json转换List<ItemCat>时报错
错误信息:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "state" (class com.jt.manage.pojo.ItemCat), not marked as ignorable (8 known properties: "sortOrder", "status", "isParent", "parentId", "created", "updated", "name", "id"])
at [Source: N/A; line: -1, column: -1] (through reference chain: java.util.ArrayList[0]->com.jt.manage.pojo.ItemCat["state"])