- MP分页查询
1.1 编辑ItemController
package com.jt.controller;
import com.jt.pojo.Item;
import com.jt.vo.EasyUITable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.jt.service.ItemService;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/item")
public class ItemController {
@Autowired
private ItemService itemService;
/**
* 业务说明: 根据分页实现商品查询
* URL地址: http://localhost:8091/item/query?page=1&rows=20
* 参数: page/rows
* 返回值: EasyUITable
*/
@RequestMapping("/query")
public EasyUITable findItemByPage(Integer page, Integer rows){
return itemService.findItemByPage(page,rows);
}
}
1.2 编辑ItemService
@Override
public EasyUITable findItemByPage(Integer page, Integer rows) {
//1.通过分页对象 将page rows 进行参数封装
IPage iPage = new Page(page,rows);
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc(“updated”);
//通过iPage对象封装其他的分页数据
iPage = itemMapper.selectPage(iPage,queryWrapper);
long total = iPage.getTotal();
List itemList = iPage.getRecords(); //获取当前页的记录
return new EasyUITable(total,itemList);
}
1.3 编辑MP配置类
package com.jt.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration //标识配置类
public class MybatisPlusConfig {
//MP工作原理: MP --分页拦截器(分页策略)-- Mybatis -----DB
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
/*@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);1
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}*/
}
- 商品分类业务实现
2.1 商品分类表结构
在这里插入图片描述
2.2 封装ItemCat Pojo对象
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
@TableName(“tb_item_cat”)
@Data
@Accessors(chain = true)
public class ItemCat extends BasePojo{
@TableId(type = IdType.AUTO)
private Long id;
private Long parentId;
private String name;
private Integer status;
private Integer sortOrder; //排序号
private Boolean isParent; //false 0 true 1
}
2.3 数据格式化操作
2.3.1 格式化时间
1).编辑页面HTML代码
//只要通过formatter属性进行调用,则都会传递2个参数 参数1:当前值 参数2:行数据
// 格式化时间
formatDateTime : function(val,row){
//console.log(val);
//console.log(row);
//将数据库时间 转化为JS对象
var now = new Date(val);
//通过js函数,格式化时间
return now.format(“yyyy-MM-dd hh:mm:ss”);
},
2.3.2 格式化状态
1).编辑html页面
// 格式化商品的状态
formatItemStatus : function formatStatus(val,row){
if (val == 1){
return ‘正常’;;
} else if(val == 2){
return ‘下架’;
} else {
return ‘未知’;
}
},
2.4 实现商品分类回显
2.4.1 业务说明
说明:根据商品分类的Id,动态的查询数据库获取商品分类的名称,进行展现.
在这里插入图片描述
2.4.2 编辑页面HTML
叶子类目 2.4.3 编辑页面JS //格式化名称 发起ajax请求,实现商品分类展现 //Ajax嵌套问题,则需要将内层ajax设置为同步 findItemCatName : function(val,row){ let name = '' $.ajax({ type: "get", url: "/itemCat/findItemCatById", data: {id: val}, success: function(result){ //result要求返回的是ItemCat对象 name = result.name }, error: function(result){ console.log("查询失败") }, async: false }) return name }, 2.4.4 编辑ItemCatController package com.jt.controller;import com.jt.pojo.ItemCat;
import com.jt.service.ItemCatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/itemCat")
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
/**
* 业务需求: 根据商品分类Id查询商品分类对象
* URL地址: /itemCat/findItemCatById?id=497
* 类型: Request Method: GET
* 参数: id
* 返回值: ItemCat对象
*/
@RequestMapping("/findItemCatById")
public ItemCat findItemCatById(Long id){
return itemCatService.findItemCatById(id);
}
}
2.4.4 编辑ItemCatService
package com.jt.service;
import com.jt.mapper.ItemCatMapper;
import com.jt.pojo.ItemCat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ItemCatServiceImpl implements ItemCatService{
@Autowired
private ItemCatMapper itemCatMapper;
@Override
public ItemCat findItemCatById(Long id) {
return itemCatMapper.selectById(id);
}
}
2.4.5 页面效果展现
在这里插入图片描述
2.5 关于common.js导入说明
2.5.1 问题说明
京淘后台js是如何导入到项目中的.
导入过程: index.jsp中
在这里插入图片描述
导入common.js
在这里插入图片描述
2.6 商品分类树形结构展现
2.6.1 弹出框效果
在这里插入图片描述
2.6.2 商品分类数据结构展现
/查询一级商品分类信息/
SELECT * FROM tb_item_cat WHERE parent_id=0
/查询二级商品分类信息/
SELECT * FROM tb_item_cat WHERE parent_id=1
/查询三级商品分类信息/
SELECT * FROM tb_item_cat WHERE parent_id=2
2.6.3 树形结构控件
$("#tree").tree({
url:“tree.json”, //加载远程JSON数据
method:“get”, //请求方式 POST
animate:false, //表示显示折叠端口动画效果
checkbox:true, //表述复选框
lines:true, //表示显示连接线
dnd:true, //是否拖拽
onClick:function(node){ //添加点击事件
//控制台
console.info(node);
}
});
2.6.4 树形结构数据展现
发现 最外层是数组[], 数组中的每个元素都是一个对象 {id,text,state}
在这里插入图片描述
2.6.5 封装树形结构节点
package com.jt.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class EasyUITree {
private Long id; //节点编号
private String text; //节点名称
private String state; //节点状态 open打开 closed关闭
}
2.6.6 树形控件JS分析
在这里插入图片描述
2.6.7 关于异步树形控件的说明
树控件读取URL。子节点的加载依赖于父节点的状态。当展开一个封闭的节点,如果节点没有加载子节点,它将会把节点id的值作为http请求参数并命名为’id’,通过URL发送到服务器上面检索子节点。
在这里插入图片描述
说明: 如果用户初始化时,没有点击节点时 不会传递ID.所以需要默认值
2.6.7 编辑ItemCatController
/**
* 查询商品分类树形结构控件
* 1.url地址: http://localhost:8091/item/cat/list
* 2.参数: 暂时没有
* 3.返回值结果: List
* 4.实现数据传递 id: xxxx
*/
@RequestMapping("/item/cat/list")
public List findItemCatList(Long id){
//查询商品分类信息 1级菜单
//如果用户没有点击按钮 将不会传递Id值,应该设定默认值
long parentId = (id==null?0:id);
return itemCatService.findItemCatList(parentId);
}
2.6.7 编辑ItemCatService
/**
* 1.根据parentId查询商品分类列表信息 一级商品分类信息
* 2.将商品分类列表转化为List对象
* 3.返回vo的list集合
* @param parentId
* @return
*/
@Override
public List findItemCatList(long parentId) {
//1.根据父级id查询子级的信息
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.eq(“parent_id”, parentId);
List itemCatList = itemCatMapper.selectList(queryWrapper);
//2.将itemCat对象 转化为VO对象
List<EasyUITree> voList = new ArrayList<>(itemCatList.size());
for (ItemCat itemCat : itemCatList){
long id = itemCat.getId();
String text = itemCat.getName();
//如果是父级则闭合,否则打开
String state = itemCat.getIsParent() ? "closed" : "open";
EasyUITree tree = new EasyUITree(id,text, state);
voList.add(tree);
}
return voList;
}
3.后台商品CURD操作
3.1 商品新增
3.1.1 页面URL分析
1.请求路径
在这里插入图片描述
2.请求参数
在这里插入图片描述
3.1.2 检查页面JS
在这里插入图片描述
3.1.3 系统返回值SysResult对象
由于是系统返回值变量,所以应该定义到jt-common中.
package com.jt.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
//通过SysResult对象 实现前后端数据交互的载体
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class SysResult {
private Integer status; //如果后端服务器运行正常 返回200 否则返回201 表示失败
private String msg; //服务器返回提示
private Object data; //服务器返回业务数据.
public static SysResult fail(){
return new SysResult(201, "服务器异常请求稍后", null);
}
public static SysResult success(){
return new SysResult(200, "服务器执行成功", null);
}
public static SysResult success(Object data){
return new SysResult(200, "服务器执行成功", data);
}
public static SysResult success(String msg,Object data){
return new SysResult(200, msg ,data);
}
}
3.1.4 编辑ItemController
/**
* 业务说明: 商品新增
* URL地址: http://localhost:8091/item/save
* 请求参数: form表单 item对象接收
* 返回值: SysResult对象
*/
@RequestMapping("/save")
public SysResult saveItem(Item item){
try {
itemService.saveItem(item);
return SysResult.success();
}catch (Exception e){
e.printStackTrace();
return SysResult.fail();
}
}
3.1.5 编辑ItemService
@Transactional //标记方式使用事务控制
@Override
public void saveItem(Item item) {
item.setStatus(1) //设定启动状态
.setCreated(new Date())
.setUpdated(item.getCreated());
itemMapper.insert(item);
}
3.2 全局异常处理
说明: 在jt-common中添加全局异常处理机制.
package com.jt.aop;
import com.jt.vo.SysResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
//spring中的通知 核心原理:Spring AOP机制
@RestControllerAdvice //只对Controller代码层级有效.
public class SysResultException {
//当程序发生异常时, 如果没有try-catch则直接向上抛出异常.
//该注解只拦截运行时异常.
@ExceptionHandler({RuntimeException.class})
public SysResult exception(Exception e){
e.printStackTrace();
return SysResult.fail();
}
}
3.3 MP自动填充实现
3.3.1 业务说明
说明: 由于入库时需要手动的完成时间字段的操作,但是该操作比较通用,任何一张表的入库/更新都需要操作时间.
需求: 能否简化代码
3.3.2 标识属性
说明: 将需要自动填充的属性 进行标识 由于是系统设置,所以在jt-common中编辑
//pojo基类,完成2个任务,2个日期,实现序列化
@Data
@Accessors(chain=true)
public class BasePojo implements Serializable{
@TableField(fill = FieldFill.INSERT)
private Date created; //新增操作有效
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updated; //新增和更新操作有效
}
3.3.3 编辑配置类
package com.jt.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//新增入库时,需要维护 created/updated
@Override
public void insertFill(MetaObject metaObject) {
Date date = new Date();
this.setFieldValByName("created", date, metaObject);
this.setFieldValByName("updated", date, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updated", new Date(), metaObject);
}
}