1.京淘后端业务实现(二)
1.1 商品删除
1.1.1 业务分析
说明:当用户点击删除按钮时,提交多个ID数据信息,之后删除后端服务器数据.
1).页面ajax请求
1.1.2 编辑ItemController
/**
* 补充1: SpringMVC框架 不熟!
* 页面中传递什么样的数据,后端才能接收什么样的数据.
* 要求1: name属性名称必须与参数名称一致.
* 要求2: name属性名称必须与属性名称一致
* 例子1:
* 页面信息 <input type="text" name="id" value="100" />
* 页面信息 <input type="text" name="age" value="19" />
* 页面信息 <input type="text" name="sex" value="男" />
*
* 补充2: SpringMVC底层实现Servlet,数据传输协议https/http 一般传递的数据都是String结构.
* 案例: 页面信息 <input type="text" name="sex" value="男" />
* 页面信息 <input type="text" name="sex" value="男" />
* 页面信息 <input type="text" name="sex" value="男" />
* 如果遇到重名属性提交,则浏览器会自己解析将value进行拼接 sex="男,男,男"
*
* springMVC优化:
* 1.可以自动的根据参数类型进行转化 string转化为具体类型
* 2.如果遇到了重名属性提交,则会自动的转化为数组类型接收.
*
* url:/item/delete
* 参数: ids=id,id,id,id
* 返回值结果: SysResult对象
*/
@RequestMapping("/delete")
public SysResult deleteItems(Long[] ids) {
itemService.deleteItems(ids);
return SysResult.success();
}
1.1.3 编辑ItemService
//参数是数组类型 有多个
@Override
public void deleteItems(Long[] ids) {
//将数组转化为集合类型
List<Long> idList = Arrays.asList(ids);
itemMapper.deleteBatchIds(idList);
//或者自己写sql.
}
1.2 商品上架/下架操作
1.2.1 业务需求说明
说明:商品上架/下架操作修改的是status属性,updated时间.
分析:
1. 下架操作 /item/instock status=2
2. 上架操作 /item/reshelf status=1
restFul优化:
1. 下架操作 /item/updateStatus/2
2. 上架操作 /item/updateStatus/1
1.2.2 修改url地址
优化后的代码
$.messager.confirm('确认','确定下架ID为 '+ids+' 的商品吗?',function(r){
if (r){
var params = {"ids":ids};
$.post("/item/updateStatus/2",params, function(data){
if(data.status == 200){
$.messager.alert('提示','下架商品成功!',undefined,function(){
$("#itemList").datagrid("reload");
});
}
});
}
});
}
$.messager.confirm('确认','确定上架ID为 '+ids+' 的商品吗?',function(r){
if (r){
var params = {"ids":ids};
$.post("/item/updateStatus/1",params, function(data){
if(data.status == 200){
$.messager.alert('提示','上架商品成功!',undefined,function(){
$("#itemList").datagrid("reload");
});
}
});
}
});
1.2.3 编辑ItemController
/**
* url地址: /item/updateStatus/2 /item/updateStatus/1
* 参数: 1.url中 2.ids
* 返回值: SysResult对象
*/
@RequestMapping("/updateStatus/{status}")
public SysResult updateItemStatus(Long[] ids,@PathVariable Integer status) {
//实现商品状态修改
itemService.updateItemStatus(ids,status);
return SysResult.success();
}
1.2.4 编辑ItemService
/**
* MP的更新操作
* 1.entity 要修改的记录
* 2.updateWrapper 修改条件构造器
* Sql: update tb_item set status=#{status},updated = #{updated}
* where id in (id1,id2,id3.....);
* 单表操作 性能损耗可以忽略.
*/
@Override
public void updateItemStatus(Long[] ids, Integer status) {
//1.定义修改数据
Item item = new Item();
item.setStatus(status).setUpdated(new Date());
//2.定义修改的条件
List<Long> idList = Arrays.asList(ids);
UpdateWrapper<Item> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("id", idList);
itemMapper.update(item, updateWrapper);
}
1.2.5 修改成功颜色
1.3 富文本编辑器介绍
1.3.1 富文本入门案例
核心理念: 所见即所得编辑效果
KindEditor是一套开源的HTML可视化编辑器,主要用于让用户在网站上获得所见即所得编辑效果,兼容IE、Firefox、Chrome、Safari、Opera等主流浏览器。
1.3.2 富文本页面JS
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="/js/kindeditor-4.1.10/themes/default/default.css" type="text/css" rel="stylesheet">
<script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/kindeditor-all-min.js"></script>
<script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/lang/zh_CN.js"></script>
<script type="text/javascript" charset="utf-8" src="/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
KindEditor.ready(function(){
KindEditor.create("#editor")
})
})
</script>
</head>
<body>
<h1>富文本编辑器</h1>
<textarea style="width:700px;height:350px" id="editor"></textarea>
</body>
</html>
1.4 商品详情业务说明
1.4.1 表设计
1.4.2 编辑ItemDesc POJO对象
@TableName("tb_item_desc")
@Data
@Accessors(chain = true)
public class ItemDesc extends BasePojo{
@TableId //主键
private Long itemId; //商品id号 itemId既是item表主键,也是itemDesc表的主键 值相同
private String itemDesc; //商品详情信息
}
1.4.3 编辑ItemDescMapper 接口
1.4.3 业务层Service注入Mapper接口
1.5 重构商品入库操作
1.5.1 业务介绍
实现2张表同时入库操作.
1.5.2 页面结构分析
说明:当用户点击商品提交时,会将2张表的数据通过/item/save的请求一起打包提交.
1.5.3 重构ItemController
/**
* 商品新增操作
* url: /item/save
* 参数: form表单数据
* 返回值结果: SysResult对象
*/
@RequestMapping("/save")
public SysResult saveItem(Item item,ItemDesc itemDesc) {
//2张表同时入库
itemService.saveItem(item,itemDesc);
return SysResult.success();
}
1.5.4 重构ItemService
//控制数据库事务
@Transactional
@Override
public void saveItem(Item item,ItemDesc itemDesc) {
//1.商品入库
item.setStatus(1) //
.setCreated(new Date())
.setUpdated(item.getCreated());
itemMapper.insert(item);
//由于主键自增的原因,所以程序入库之后才会有主键信息.
//MP提供业务支持实现数据自动的回显功能!!!! 入库操作之后,会将所有的数据库记录进行映射给对象
//底层实现是Mybatis的主键自动回显功能
//2.商品详情入库 item/itemDesc中的ID的值一致.
itemDesc.setItemId(item.getId())
.setCreated(item.getCreated())
.setUpdated(item.getCreated());
itemDescMapper.insert(itemDesc);
}
1.5 商品详情回显
1.5.1 页面分析
1).url地址
2).页面JS
// 加载商品描述
//_data = SysResult.ok(itemDesc)
$.getJSON('/item/query/item/desc/'+data.id,function(_data){
if(_data.status == 200){
//UM.getEditor('itemeEditDescEditor').setContent(_data.data.itemDesc, false);
//在指定的位置,显示页面html标记信息.
itemEditEditor.html(_data.data.itemDesc);
}
});
1.5.2 编辑ItemController
/**
* 业务需求: 根据itemId查询商品详情信息
* url地址: http://localhost:8091/item/query/item/desc/1474391972
* 参数: 使用restFul方式使用传输传递
* 返回值: SysResult对象,并且需要携带itemDesc数据信息.
*/
@RequestMapping("/query/item/desc/{itemId}")
public SysResult findItemDescById(@PathVariable Long itemId) {
ItemDesc itemDesc = itemService.findItemDescById(itemId);
return SysResult.success(itemDesc);
}
1.5.3 编辑ItemService
@Override
public ItemDesc findItemDescById(Long itemId) {
return itemDescMapper.selectById(itemId);
}
1.5.4 页面效果展现
1.6 商品详情修改
1.6.1编辑ItemController
/**
* 商品修改操作
* url: /item/update
* 参数: form表单数据
* 返回值结果: SysResult对象
*/
@RequestMapping("/update")
public SysResult updateItem(Item item,ItemDesc itemDesc) {
itemService.updateItem(item,itemDesc);
return SysResult.success();
}
1.6.2 编辑ItemService
@Override
@Transactional
public void updateItem(Item item,ItemDesc itemDesc) {
//1.更新商品信息
item.setUpdated(new Date());
itemMapper.updateById(item);
//2.更新商品详情信息
itemDesc.setItemId(item.getId())
.setUpdated(item.getUpdated());
itemDescMapper.updateById(itemDesc);
}
1.7 商品关联删除
1.7.1编辑ItemService
说明:实现商品关联删除
//参数是数组类型 有多个
@Override
@Transactional
public void deleteItems(Long[] ids) {
//1.删除商品信息
//将数组转化为集合类型
List<Long> idList = Arrays.asList(ids);
itemMapper.deleteBatchIds(idList);
//2.删除商品详情信息
itemDescMapper.deleteBatchIds(idList);
}
1.8 文件上传入门案例
1.8.1 入门测试网址
1.8.2 编辑页面html
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>实现文件长传</h1>
<!--enctype="开启多媒体标签" 字节信息 -->
<form action="http://localhost:8091/file" method="post"
enctype="multipart/form-data">
<input name="fileImage" type="file" />
<input type="submit" value="提交"/>
</form>
</body>
</html>
1.8.3 编辑FileController
说明:编辑FileController使用SpringMVC框架的文件上传API.
package com.jt.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController //返回json数据
public class FileController {
/**
* url地址: http://localhost:8091/file
* 参数: File=fileImage
* 返回值: 字符串
*
* 参数说明:MultipartFile 接口, 主要负责实现文件接收
* 常识:
* 1.必须指定文件上传的路径信息 D:\JT-SOFT\images\文件名称.jpg
* 2.将字节信息利用outPutStream进行输出操作
*
* 说明:文件上传默认大小1M=1024*1024
* 具体参见CommonsFileUploadSupport类
*
* @throws IOException
* @throws IllegalStateException
*/
@RequestMapping("/file")
public String file(MultipartFile fileImage) throws IllegalStateException, IOException {
//1.定义文件目录信息
String dirPath = "D:/JT-SOFT/images";
File fileDir = new File(dirPath);
//2.校验图片目录是否存在.
if(!fileDir.exists()) { //如果文件目录不存在,应该创建目录
fileDir.mkdirs(); //创建多级目录
}
//3.获取文件信息. 一般都在上传提交的参数中 a.jpg
String fileName = fileImage.getOriginalFilename();
//4.实现文件上传. 指定文件真实路径
File file = new File(dirPath+"/"+fileName);
//5.利用api实现文件输出.
fileImage.transferTo(file);
return "恭喜你,文件上传成功!!!";
}
}
1.9 文件上传业务实现
1.9.1 文件上传页面分析
1).页面url分析
2).参数提交
3).数据回传的格式要求
查阅富文本的API获取相关信息.
{"error":0,"url":"图片的保存路径","width":图片的宽度,"height":图片的高度}
参数1.error: 正常错误0 ,上传有误1
参数2: 图片的虚拟地址信息
width/height 如果设定则使用用户的,如果不设定这使用默认的. 一般不用修改.
1.9.2 封装文件上传VO–ImageVO
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO {
private Integer error; //错误信息 0正确 1错误
private String url; //url地址
private Integer width; //宽度
private Integer height; //高度
//1.封装失败的方法
public static ImageVO fail() {
return new ImageVO(1, null, null, null);
}
//2.封装成功的方法
public static ImageVO success(String url) {
return new ImageVO(0, url, null, null);
}
public static ImageVO success(String url,Integer width,Integer height) {
return new ImageVO(0, url, width, height);
}
}
1.9.3 编辑FileController
/**
* 业务分析:实现文件上传.
* 1.url地址: http://localhost:8091/pic/upload
* 2.参数: uploadFile 文件上传对象
* 3.返回值: ImageVO对象
*/
@RequestMapping("/pic/upload")
public ImageVO uploadFile(MultipartFile uploadFile) {
return fileService.uploadFile(uploadFile);
}
1.9.4 编辑FileService
package com.jt.service;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.jt.vo.ImageVO;
@Service
public class FileServiceImpl implements FileService {
private String localDir = "D:/JT-SOFT/images";
//bug:漏洞 一般没错 二般情况才会出错 传递特殊参数时报错
//error: 错误
/**
* 1.如何校验上传的信息是图片??????
* 通过后缀进行校验: .jpg,.png,.gif........
* 2.如何保证检索速度更快 ????
* 分目录存储 1).hash 2).时间
* 3.如何防止文件重名???
* 重定义文件名称 uuid.jpg
*/
@Override
public ImageVO uploadFile(MultipartFile uploadFile) {
//1.校验上传的信息 是否为图片
//1.1初始化图片类型集合
Set<String> typeSet = new HashSet<>();
typeSet.add(".jpg");
typeSet.add(".png");
typeSet.add(".gif");
//1.2动态获取用户上传的图片类型 abc.jpg|ABC.JPG
String fileName = uploadFile.getOriginalFilename();
fileName = fileName.toLowerCase(); //将所有的字符转化为小写.
int index = fileName.lastIndexOf(".");
//.jpg
String fileType = fileName.substring(index);
//1.2校验图片类型是否有效
if(!typeSet.contains(fileType)) {
//表示类型不属于图片信息 则终止程序
return ImageVO.fail();
}
//2.准备文件上传的目录结构. 文件上传根目录+动态变化的目录
String dateDir = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
//D:/JT-SOFT/images/2020/7/10/
String dirPath = localDir + dateDir;
File dirFile = new File(dirPath);
if(!dirFile.exists()) {
dirFile.mkdirs(); //如果目录不存在则新建目录.
}
//3.重新指定文件名称
String uuid = UUID.randomUUID().toString();
String realFileName = uuid + fileType;
//4.执行文件上传代码 目录+文件名称
File imageFile = new File(dirPath+realFileName);
try {
uploadFile.transferTo(imageFile);
String url = "https://img14.360buyimg.com/n0/jfs/t1/71310/32/5640/402976/5d3a654eE0489baf9/fd8eafe74ef8779c.jpg";
return ImageVO.success(url);
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
return ImageVO.fail();
}
}
}
1.9.5 页面效果展现
来源:oschina
链接:https://my.oschina.net/u/4386652/blog/4358024