1.创建jt项目
聚合工程项目打包方式。
聚合工程的目录结构说明,注意事项。
父类实现序列化,子类不需要实现序列化接口。
阿里数据源说明,配置项目启动项,避免404问题。
2.京淘后台业务说明
默认访问路径
EasyUI介绍
3.京淘后台商品业务实现(查询)
resful通用页面跳转说明
EasyUI中表格数据展现形式,参数要求,说明:使用别人的框架,就必须要满足别人的请求。
json串说明。
商品查询列表具体实现.
前端页面具体分析.
普通方式实现查询分页。
mp方式实现分页(添加配置类)。
商品分类查询信息回显说明。
价格缩小100倍回显,状态码回显,叶子类目回显。
一般数据库中的tinyint(1)类型用Boolean来接收,数据库会进行转换,注意是包装类型。
叶子类目的ajax嵌套问题。
通用的js文件引入。
4.端口号占用问题。
1.什么是聚合工程 一个大型项目中包含了多个小型项目. 通过打包方式进行定义!!
2.常见打包方式: 1.jar包 2.war包 3.pom包(聚合工程)
3.京淘项目创建说明
父级项目jt 打包类型:pom
工具API项目 jt-common 打包类型:jar包
业务项目 jt-manage 打包类型:jar/war包.
注意:分布式父级项目一般用Maven形式,springboot的方式创建(即用插件的方式)一般创建的是里面的子系统。
父级工程不写java代码不会识别,它最小的单位是jar,主要是起jar包的管理作用。所以说只需要编辑pom文件即可,不用写java代码,也不用编辑配置文件,主启动类。
Parent:当前项目的父级项目,没有则为None.
Name:项目名。
下面的是当前项目的坐标,最好放在指定的包路径下。
Groupid:公司域名。
Artifaciid:项目名
注意:1.需要在pom文件标识此项目为父级工程项目。2.不需要引入build标签。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jt</groupId>
<artifactId>jt</artifactId>
<version>1.0-SNAPSHOT</version>
<!--我是父级工程,是聚合项目可以包含子项目-->
<packaging>pom</packaging>
<!--1.引入springBoot 父级项目-->
<!--parent标签作用: 定义了SpringBoot中所有关联项目的版本号信息.-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--2.引入属性的配置-->
<properties>
<java.version>1.8</java.version>
<!--项目打包时,跳过测试类打包-->
<skipTests>true</skipTests>
</properties>
<!--3.在父级项目中添加jar包文件-->
<!--开箱即用:SpringBoot项目只需要引入少量的jar包及配置,即可拥有其功能.
spring-boot-starter 拥有开箱即用的能力.
maven项目中依赖具有传递性.
A 依赖 B 依赖 C项目 导入A bc会自动依赖
-->
<dependencies>
<!--直接依赖web springMVC配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<!--springBoot-start SpringBoot启动项 -->
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot重构了测试方式 可以在测试类中 直接引入依赖对象-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--支持热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--引入插件lombok 自动的set/get/构造方法插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--引入数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--springBoot数据库连接 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--spring整合mybatis-plus 只导入MP包,删除mybatis包 。注意这个mb或mp的版本需要自己添加-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!--springBoot整合JSP添加依赖 -->
<!--servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!--jstl依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!--使jsp页面生效 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!--添加httpClient jar包(远程调用) -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!--引入dubbo配置 ,将来用到了Dubbo框架-->
<!--<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>-->
<!--添加Quartz的支持 -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>-->
<!-- 引入aop支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--spring整合redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
</dependencies>
<!--build标签只有添加了主启动类的java文件才需要 jt是父级工程只做jar包的定义.父级工程只是项目的管理者不会在其中编辑代码 所以不要添加build-->
</project>
注意:
1.在父级项目上右键进行创建子项目,工具API项目不需要像springboot项目一样使用Tomact启动。所以还是要用普通的Maven创建的方式创建项目。
2.不写默认就是jar包文件的打包方式。
3.只需要创建项目就行和(编写或引入)工具api即可,pom文件不需要添加依赖。
课前资料的src直接复制过来,原先的直接右键delete.
里面是2个pojo类。
package com.jt.pojo;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import lombok.experimental.Accessors;
//pojo基类,完成2个任务,2个日期,实现序列化
@Data
@Accessors(chain=true)
public class BasePojo implements Serializable{
private Date created; // 创建时间
private Date updated; //修改时间
}
注意只要是父级实现了序列化接口,子集继承也实现了序列化接口,子类不需要在实现Serializable。
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.experimental.Accessors;
@JsonIgnoreProperties(ignoreUnknown=true) //表示JSON转化时忽略未知属性
@TableName("tb_item")
@Data
@Accessors(chain=true)
public class Item extends BasePojo{
@TableId(type=IdType.AUTO)
private Long id; //商品id
private String title; //商品标题
private String sellPoint; //商品卖点信息
private Long price; //商品价格 Long > dubbo
private Integer num; //商品数量
private String barcode; //条形码
private String image; //商品图片信息 1.jpg,2.jpg,3.jpg
private Long cid; //表示商品的分类id
private Integer status; //1正常,2下架
//为了满足页面调用需求,添加get方法
public String[] getImages(){
return image.split(",");
}
}
1.子类项目知道父级项目是谁:在子集项目commom里的parent标签的原先是< artifactId> spring-boot-starter-parent< /artifactId>,现在变为< artifactId> jt< /artifactId>.
2.父级项目知道子类是谁:有一个子集项目就会自动生成一行module标签。
注意:将来如果改了子类项目只是改了项目名,它父级的这行标签不会随之更改,需要进行手动更改modules标签。
说明:因为这个地方复制的是课前资料的所以直接创建普通maven项目即可。
注意:用普通maven方式创建,这个地方有主启动类,所以在进行手写一些配置。这些配置直接复制了课前资料里面的。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>jt-manage</artifactId>
<!--设定打包类型,不写默认就是jar包-->
<packaging>war</packaging>
<!--添加继承依赖和插件-->
<parent>
<artifactId>jt</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<!--添加依赖 工具api的jar包-->
<dependencies>
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--添加插件 解释在上一个笔记-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
注意:这里面的pojo没有放在manage项目,而是放在了common工具api里面是因为:如果2个子系统用的都是同一个pojo只需要放在common工具api项目中,其它的项目想要使用只需要添加依赖就行了。
1.数据源说明:不写默认的是spring框架内置的数据源,放开后是阿里的数据源(当然想用还需要添加jar包)
2.驱动说明:新版本不用配置驱动程序,它会根据你的依赖会自动加载驱动程序,加上也不错。加上这句话,如果数据库驱动高低版本不匹配会报错需要添加字母cj,所以最好还是注释掉.
server:
port: 8091
servlet:
context-path: /
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource 阿里的数据源用到了放开就行
#driver-class-name: com.mysql.cj.jdbc.Driver 数据库驱动
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
首先找到manage项目的主启动类启动项目,然后再进行编辑.(不先启动项目,编辑的可能是错的项目。)
问题说明: 为什么通过8091网址访问可以直接跳转到系统首页呢??
说明: web.xml 其中有一项配置叫做默认欢迎页面.
2.模板引入
3.调用规则
SpringBoot内部通过默认引擎 发送一个index请求,但是该请求不需要通过Controller进行接收.会自己拼接视图解析器的前缀和后缀 完成页面跳转. /WEB-INF/views/index.jsp
注意事项:
当使用SpringBoot程序时,可以通过缺省值访问,但是系统的首页的名称必须为index.xxxx 。
easyui是一种基于jQuery、Angular.、Vue和React的用户界面插件集合。
easyui为创建现代化,互动,JavaScript应用程序,提供必要的功能。
使用easyui你不需要写很多代码,你只需要通过编写一些简单HTML标记,就可以定义用户界面。
easyui是个完美支持HTML5网页的完整框架。
easyui节省您网页开发的时间和规模。
easyui很简单但功能强大的。
学习方式 复制 黏贴 EasyUI(有中文网站)
<!--引入jquery的js,EasyUI的执行需要依赖于jQuery -->
<script type="text/javascript"
src="/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<!--easyUI的js主文件 -->
<script type="text/javascript"
src="/js/jquery-easyui-1.4.1/jquery.easyui.min.js"></script>
<!--国际化的js文件 -->
<script type="text/javascript"
src="/js/jquery-easyui-1.4.1/locale/easyui-lang-zh_CN.js"></script>
<!--引入easyUI的样式 -->
<link rel="stylesheet" type="text/css"
href="/js/jquery-easyui-1.4.1/themes/icon.css" />
<link rel="stylesheet" type="text/css"
href="/js/jquery-easyui-1.4.1/themes/default/easyui.css" />
<body>
<!--easyUI入门案例 只要引入特定的样式就可以有对应的功能-->
<div class="easyui-draggable">拖动DIV</div>
<div class="easyui-draggable">测试div</div>
</body>
<body class="easyui-layout">
<-- data-options 是UI框架的特定的属性 -->
<div data-options="region:'west',title:'菜单',split:true" style="width:25%;"></div>
<div data-options="region:'center',title:'首页'"></div>
</body>
<ul class="easyui-tree">
<li>
<span>商品管理</span>
<ul>
<li>商品查询</li>
<li>商品新增</li>
<li>商品编辑</li>
<li>
<span>三级标题</span>
<ul>
<li>11</li>
<li>22</li>
<li>33</li>
</ul>
</li>
</ul>
</li>
</ul>
function addTab(title, url){
if ($('#tt').tabs('exists', title)){
$('#tt').tabs('select', title);
} else {
//iframe 画中画的效果
var url2 = "https://map.baidu.com/search/%E5%85%A8%E5%9B%BD/@12959219.601961922,4825334.624608941,5z?querytype=s&wd=%E5%85%A8%E5%9B%BD&c=1&provider=pc-aladin&pn=0&device_ratio=1&da_src=shareurl";
var content = 'url2+'" style="width:100%;height:100%;">';
$('#tt').tabs('add',{
title:title,
content:content,
closable:true
});
}
}
create table tb_item
(
id bigint(10) not null auto_increment comment '商品ID,也是商品编号',
title varchar(100),
sell_point varchar(150),
price bigint(20) comment '单位为:分',
num int(10),
barcode varchar(30),
image varchar(500) comment '最多5张图片',
cid bigint(10),
status int(1) default 1 comment '默认值为1,可选值:1正常,2下架,3删除',
created datetime,
updated datetime comment '列表排序时按修改时间排序,所以在新增时需要设置此值。',
primary key (id)
);
@JsonIgnoreProperties(ignoreUnknown=true) //表示JSON转化时忽略未知属性
@TableName("tb_item")
@Data
@Accessors(chain=true)
public class Item extends BasePojo{
@TableId(type=IdType.AUTO)
private Long id; //商品id
private String title; //商品标题
private String sellPoint; //商品卖点信息
//价格一般是小数为什么用long类型而不是double,因为小数可能会出现精读溢出问题,为了避免这种问题,在数据库存数据时把数据 *100变为整数,取出来时给用户展现数据时在除以100变为小数
private Long price; //商品价格 0.98 * 100 = 98 /100 = 0.98
private Integer num; //商品数量
private String barcode; //条形码
//数据库如何储存图片呢?实际上是储存的是图片的url地址,而不是二进制数据。多张图片是怎么存地址呢? 多张地址用 ','分割,想要展现第一章图可以用 ','进行拆分成数组在用下标进行取值。
private String image; //商品图片信息 1.jpg,2.jpg,3.jpg
private Long cid; //表示商品的分类id
private Integer status; //1正常,2下架
//为了满足页面调用需求,添加get方法
public String[] getImages(){
return image.split(",");
}
}
说明:当用户发起请求时其中有3个请求都是类似的功能.能否利用一个Controller方法实现通用的页面跳转.
<ul>
<li data-options="attributes:{'url':'/page/item-add'}">新增商品</li>
<li data-options="attributes:{'url':'/page/item-list'}">查询商品</li>
<li data-options="attributes:{'url':'/page/item-param-list'}">规格参数</li>
</ul>
item:商品。
package com.jt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class IndexController {
/**
* 关于通用页面跳转的说明
* url地址: /page/item-add
* url地址: /page/item-list
* url地址: /page/item-param-list
* 按照常规: 1个请求对应的1个controller方法
* 需求: 能否利用一个方法实行页面的通用的跳转.
* 想法: 能否动态的接收url中的参数呢??
*
* restFul风格实现1:
* 1.参数与参数之间使用/分隔
* 2.参数使用{}形式包裹
* 3.参数接收时需要使用 @PathVariable 获取
* @RequestMapping("/page/{moduleName}")
*
* restFul风格实现2:
* 可以利用请求的类型,指定业务功能.
* TYPE="GET" 查询业务
* TYPE="POST" 新增业务
* TYPE="PUT" 更新业务
* TYPE="DELETE" 删除业务
*
* 总结1: 如果需要获取url地址中的参数时,则可以使用RestFul风格实现.
* 总结2: 可以按照类型执行特定的功能.
*/
//@RequestMapping(value = "/page/{moduleName}",method = RequestMethod.GET)
//但是这种写法太麻烦,mvc进行了简化
@GetMapping("/page/{moduleName}")
/*@PutMapping
@DeleteMapping
@PostMapping*/
//这个注解是把上面的接收的值动态赋值给标识的参数
public String itemAdd(@PathVariable String moduleName){
//目的:跳转页面 item-add
return moduleName;
}
}
因为这个表格用的是EasyUI框架的表格,这个表格如何使用,在这里做了一个入门案例测试。
在UI框架中看到url属性时,在背后一定会发起ajax请求,这是UI框架的形式。
<table class="easyui-datagrid" style="width:500px;height:300px" data-options="url:'datagrid_data.json',method:'get',fitColumns:true,singleSelect:true,pagination:true">
<thead>
<tr>
<th data-options="field:'code',width:100">Code</th>
<th data-options="field:'name',width:100">Name</th>
<th data-options="field:'price',width:100,align:'right'">Price</th>
</tr>
</thead>
</table>
核心知识点: 如果需要展现UI框架中特定的格式,则返回的数据必须满足其要求.框架才会自动的完成解析.(这个地方查询完数据,把数据封装成特定的格式返回到页面会自动帮你解析回显数据,也不像之前把查询到的数据返回给前端后,在自己手动的for循环拼接解析到页面上。)
说明:使用别人的框架,就必须要满足别人的请求。
这个是EasyUI中url地址所需的参数形式。
这个所需要提供的参数形式。
参数形式具体说明:
total:控制分页的数量。
rows:控制整个表格数据。
对象的属性要和页面的标识符一致
最外层是个{,说明是个对象。里面有2个属性 total和rows.
rows是个[ 所以里面是个list集合,里面是{说明存的是数据库对象数据。
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。
例子: {"id":"1","name":"tomcat猫"}
{"id":"1","name":"tomcat猫","hobby":["吃汉堡","喝果汁","玩游戏","游戏十连胜","看美女",{"身高":"172","腿长":"110","肤色":"白里透红"}]}
点击查询实现在查询页面商品列表的展现。(上面哪个是入门案例分析。)
数据库里面的数据和页面要求展现的数据格式不一样,与页面数据交互的对象的封装称为VO对象。
VO是给页面展现数据用的。 PO是用于和数据库交互用的。
json转化为对象
package com.jt.vo;
import com.jt.pojo.Item;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
@Data
@Accessors(chain = true)
@NoArgsConstructor //无参构造
@AllArgsConstructor //有参构造
// 当服务之间字节数组(对象)传递时,必须实现序列化接口.
// json的本质就是字符串可以直接传递. 有无序列化都行
public class EasyUITable implements Serializable{
private Integer total;
private List<Item> rows; //rows分页查询的结果信息
}
业务说明: 当用户点击列表按钮时.跳转到item-list.jsp页面中.会解析其中的EasyUI表格数据.发起请求url:’/item/query’
要求返回值必须满足特定的JSON结构,所以采用EasyUITable方法进行数据返回.(JSON数据不能手动封装,所以转换一下,返回特定的VO就能数据的正常展现,发请求返回的就是VO对象转化后的JSON)
即:在index.jsp页面点击查询跳转到tem-list.jsp页面,在发送ajax请求,请求url为url:’/item/query’。
<table class="easyui-datagrid" id="itemList" title="商品列表"
data-options="singleSelect:false,fitColumns:true,collapsible:true,pagination:true,url:'/item/query',method:'get',pageSize:20,toolbar:toolbar">
<thead>
<tr>
<th data-options="field:'ck',checkbox:true"></th>
<th data-options="field:'id',width:60">商品ID</th>
<th data-options="field:'title',width:200">商品标题</th>
<th data-options="field:'cid',width:100,align:'center',formatter:KindEditorUtil.findItemCatName">叶子类目</th>
<th data-options="field:'sellPoint',width:100">卖点</th>
<th data-options="field:'price',width:70,align:'right',formatter:KindEditorUtil.formatPrice">价格</th>
<th data-options="field:'num',width:70,align:'right'">库存数量</th>
<th data-options="field:'barcode',width:100">条形码</th>
<th data-options="field:'status',width:60,align:'center',formatter:KindEditorUtil.formatItemStatus">状态</th>
<th data-options="field:'created',width:130,align:'center',formatter:KindEditorUtil.formatDateTime">创建日期</th>
<th data-options="field:'updated',width:130,align:'center',formatter:KindEditorUtil.formatDateTime">更新日期</th>
</tr>
</thead>
</table>
请求路径: /item/query
参数: page=1 当前分页的页数. rows = 20 当前分页的行数.
当使用分页操作时,那么会自动的拼接2个参数.进行分页查询.
说明: 用户发起Ajax请求,之后通过ItemController返回 EasyUITable的JSON串.
package com.jt.controller;
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 //由于AJax的调用返回值都是JSON数据,所以使用这个注解
@RequestMapping("/item")
public class ItemController {
@Autowired
private ItemService itemService;
/**
* 业务需求:商品信息的分页查询.
* url地址: http://localhost:8091/item/query?page=1&rows=50
* 请求参数: page 页数 , rows 行数
* 返回值结果: EasyUITable
* 开发顺序: mapper~~service~~~controller~~页面 自下而上的开发
* 京淘开发顺序: 分析页面需求~~~~Controller~~~~Service~~~Mapper 自上而下的开发
*
* */
@RequestMapping("/query")
public EasyUITable findItemByPage(Integer page,Integer rows){
return itemService.findItemByPage(page,rows);
}
}
package com.jt.service;
import com.jt.pojo.Item;
import com.jt.vo.EasyUITable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jt.mapper.ItemMapper;
import java.util.List;
@Service
public class ItemServiceImpl implements ItemService { //eclipse alt+shift+p
//alt +insert
//快捷键作用:它可以用来生成构造函数、setter和getter,或者重写父类的方法。
@Autowired
private ItemMapper itemMapper;
/**
* 自己手写分页的查询实现数据返回
* Sql: select * from tb_item limit 起始位置,展现行数;
* 查询第一页 20条
* Sql: select * from tb_item limit 0,20; [0-19] (它是数组结构,从0开始)
*查询第二页 20条
* Sql: select * from tb_item limit 20,20; [20-39]
* 查询第三页 20条
* Sql: select * from tb_item limit 40,20;
* @param page
* @param rows
* @return
*/
@Override
public EasyUITable findItemByPage(Integer page, Integer rows) {
//1.计算起始位置 0 20 40等差数列 (n-1)*20
//分页查询,查询的是起始位置,而不是具体的页数
int startIndex = (page-1)*rows;
//2.数据库记录
List<Item> itemList = itemMapper.findItemByPage(startIndex,rows);
//3.查询数据库总记录数 (这里用的是mp的写法)
int total = itemMapper.selectCount(null);
//4.将数据库记录 封装为VO对象(用户需要的是VO对象在转化为json)
return new EasyUITable(total,itemList);
}
}
package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.Item;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface ItemMapper extends BaseMapper<Item>{
//查询一般是查的是最新的数据,所以说先进行降序排序(按照更新时间的字段),这样前面显示的都是新数据,在进行分页。注意在公司不要用*
@Select("select * from tb_item order by updated desc limit #{startIndex},#{rows}")
List<Item> findItemByPage(int startIndex, Integer rows);
}
pojo,mapper层复制课前资料里面已经用mp标识过了,所以这里只需要修改service层,添加配置类。
@Service
public class ItemServiceImpl implements ItemService { //eclipse alt+shift+p
//alt +insert
@Autowired
private ItemMapper itemMapper;
/**
* 在进行分页查询时,MP必须添加配置类
* 利用MP机制,实现商品查询
* @param page
* @param rows
* @return
*/
@Override
public EasyUITable findItemByPage(Integer page, Integer rows) {
//查询条件根据更新时间进行排序.
QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("updated");
//当用户将参数传递之后,MP会自己执行分页操作后,将需要的数据进行封装.
//定义分页对象 页数 条数
IPage<Item> iPage = new Page<>(page,rows);
//根据分页对象执行数据库查询,之后获取其其他分页数据. mp分页的方法。
iPage = itemMapper.selectPage(iPage,queryWrapper);
//获取总记录数
int total = (int)iPage.getTotal();
//获取分页后的结果
List<Item> itemList = iPage.getRecords();
//封装返回值 返回
return new EasyUITable(total,itemList);
}
}
@Configuration //标识我是一个配置类
public class MybatisPlusConfig {
//MP-Mybatis增强工具
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
}
分析:数据库的价格数据为了防止在计算时因为小数导致精度溢出问题,在向数据库存数据时都是先乘以100,在页面回显的时候除以100。
在页面是如何缩小100倍呢?
在item-list.jsp页面通过formatter关键字调用KindEditorUtil.formatPrice函数,这个函数在commom.js文件里面。
1).页面属性说明
当数据在进行展现时,会通过formatter关键字进行数据格式化调用.具体的函数KindEditorUtil.formatPrice函数。
<th data-options="field:'price',width:70,align:'right',formatter:KindEditorUtil.formatPrice">价格</th>
// 格式化价格 val="数据库记录" 展现的应该是缩小100倍的数据。toFixed(2):表示精确到2位小数。
formatPrice : function(val,row){
return (val/100).toFixed(2);
},
1).页面标识
<th data-options="field:'status',width:60,align:'center',formatter:KindEditorUtil.formatItemStatus">状态</th>
2).页面js分析
// 格式化商品的状态
formatItemStatus : function formatStatus(val,row){
if (val == 1){
return '正常';
} else if(val == 2){
return '下架';
} else {
return '未知';
}
},
叶子类目在数据库中存的是cid字段。把formatter函数去掉就会显示数字了。
1).页面分析
说明:根据页面标识,要在列表页面中展现的是商品的分类信息.后端数据库只传递了cid的编号.我们应该展现的是商品分类的名称,方便用户使用。
解决:根据查询数据库的cid在进行一次发送ajax请求,查询对应的商品分类名称。这和上面的状态码不一样,状态码只有2个,而这对应的商品分类名称不确定只能在进行一次查询。
<th data-options="field:'cid',width:100,align:'center',formatter:KindEditorUtil.findItemCatName">叶子类目</th>
//格式化名称 val=cid 返回商品分类名称
findItemCatName : function(val,row){
var name;
$.ajax({
type:"get",
url:"/item/cat/queryItemName",
data:{itemCatId:val},
cache:true, //缓存
async:false, //表示同步 默认的是异步的true
dataType:"text",//表示返回值参数类型
success:function(data){
name = data;
}
});
return name;
},
放在common工具api模块。
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)
//一般pojo不需要添加构造方法。
public class ItemCat extends BasePojo{
@TableId(type = IdType.AUTO)
private Long id;
private Long parentId; // 父级ID
private String name; //分类名称
private Integer status; //状态信息
private Integer sortOrder; //排序号
private Boolean isParent; //是否为父级. 一般数据库中的tinyint(1)类型用Boolean来接收,数据库会进行转换,注意是包装类型。
}
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("/item/cat") //请求业务名称
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
/**
* 分析业务: 通过itemCatId获取商品分类的名称
* 1.url地址: url:"/item/cat/queryItemName",
* 2.参数: {itemCatId:val},
* 3.返回值: 商品分类名称 String
*/
@RequestMapping("/queryItemName")
public String findItemCatName(Long itemCatId){
//根据商品分类id查询商品分类对象
ItemCat itemCat=itemCatService.findItemCatNameById(itemCatId);
return itemCat.getName();//返回商品分类对象的名称
}
}
package com.jt.service;
import com.jt.pojo.ItemCat;
public interface ItemCatService {
ItemCat findItemCatNameById(Long itemCatId);
}
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 findItemCatNameById(Long itemCatId) {
return itemCatMapper.selectById(itemCatId);
}
}
package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.ItemCat;
public interface ItemCatMapper extends BaseMapper<ItemCat> {
}
商品的列表中发起2次ajax请求,因为都是异步,所以外面的第一次的ajax请求返回数据时把数据直接渲染到页面上,同时在发送第二次ajax请求返回数据,但这时已经渲染完页面了,且页面只会刷新一次。这时第二次请求的的返回值渲染不到页面导致查询为空白。
如果设置了第二次请求为同步,则第一次请求解析返回值在发送第二次请求得到返回值后再进行页面渲染,就正确显示了。
第一次:
data-options="singleSelect:false,fitColumns:true,collapsible:true,pagination:true,url:'/item/query',method:'get',pageSize:20,toolbar:toolbar">
说明: 一般条件的下ajax嵌套会将内部的ajax设置为同步的调用.不然可能会由于url调用的时间差导致数据展现不完全的现象.
这里也没有用到script标签引入js,那么item-list.jsp中的函数怎们用到commom.js文件里面的方法呢?
首先: 整个页面分为2部分:访问localhost:8091和(比如)查询显示的页面。
点击查询时,url前面的地址也没有发生变化,只要在外面大的部分页面(index.jsp)引入common.js,则小的部分(item-list.jsp)也会引入common.js.
之后:如果每个页面都需要引入大量的js css等,每个页面都要写这样的引入标签代码太麻烦。把这些需要引入js css文件的标签统一写在一个文件里(common-js.jsp),在需要引入的jsp文件(index.jsp)里通过include标签直接引入这个通用的文件((common-js.jsp)就行了。
说明:一般会将整个页面的JS通过某个页面进行标识,之后被其他的页面引用即可… 方便以后的JS的切换.
步骤:
1).引入xxx.jsp页面