@Mapper 接口交给Spring容器管理
也可以在主启动类上添加@MapperScan(" ")
1.实现商品详情的展现
1.1业务说明
一般用户查询商品时,只需要展现商品想关信息即可,如果用户点击某个商品时点击详情才会显示商品详情信息,因为商品详情属于大字段信息,检索相对较慢,浪费性能
表设计说明:
1.tb_item商品表
2.tb_item_desc商品详情表
1.1.1编辑商品详情pojo对象:
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Accessors(chain =true)
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_item_desc")
public class ItemDesc extends BasePojo{
/**
* 商品id需要与item的id有对应关系,不能随意自增
* */
@TableId
private Long itemId; //商品ID
private String itemDesc; //商品详情
}
1.2富文本编辑器
1.2.1入门案例
底层实现
1.2.2新增商品及商品详情
controller
/**
* 商品d的新增业务的实现 * */
@RequestMapping("/save")
public SysResult doSaveObject(Item item, ItemDesc itemDesc){
itemService.saveItem(item,itemDesc);
return SysResult.success();
/* try{
itemService.saveItem(item,itemDesc);
return SysResult.success();
}catch(Exception e){
e.printStackTrace();
return SysResult.fail();
}
*/
} ```
```java
@Override
@Transactional
public void saveItem(Item item , ItemDesc itemDesc) {
//Date date=new Date();
item.setStatus(1);//.setCreated(date).setUpdated(date);
//MP用法:如果完成主键自增,自动实现数据的回显
itemMapper.insert(item);
//获取主键的信息
itemDesc.setItemId(item.getId());
itemDescMapper.insert(itemDesc );
}
1.3商品详情信息的回显
//回显数据
var data = $("#itemList").datagrid("getSelections")[0];
data.priceView = KindEditorUtil.formatPrice(data.price);
$("#itemeEditForm").form("load",data);
// 加载商品描述
//_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);
itemEditEditor.html(_data.data.itemDesc);
}
});
1.3.1controller
/**
* 商品详情信息的回显
*
* */
@RequestMapping("/query/item/desc/{itemId}")
public SysResult findItemDescById(@PathVariable Long itemId){
ItemDesc itemDesc=itemService.findItemDescById(itemId);
//业务调用传值到页面
return SysResult.success(itemDesc);
}
itemServiceImpl
@Override
public ItemDesc findItemDescById(Long itemId) {
return itemDescMapper.selectById(itemId);
}
1.4重构商品更新
controller
@RequestMapping("/update")
public SysResult doUpdateItem(Item item,ItemDesc itemDesc){
itemService.updateItem(item,itemDesc);
return SysResult.success();
}
itemServiceImpl
@Override
@Transactional
public void updateItem(Item item,ItemDesc itemDesc) {
itemMapper.updateById(item);
itemDesc.setItemId(item.getId());
itemDescMapper.updateById(itemDesc);
}
1.5商品的删除
ItemController
@RequestMapping("/delete")
public SysResult doDeleteItemByIds(Integer[] ids){
itemService.deleteByIds(ids);
return new SysResult().success();
}
ItemServiceImpl
@Override
@Transactional
public void deleteByIds(Integer[] ids) {
itemMapper.deleteItemByIds(ids);
itemDescMapper.deleteBatchIds(Arrays.asList(ids));
}
2.文件上传
2.1文件上传案例
enctype=“multipart/form-data” 开启多媒体传递,不然只能传递文本
<%@ 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>
package com.jt.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@RestController
public class FileController {
/**
* url地址:http://localhost:8091/file
* 参数: 文件信息fileImage
* 返回值:String
* */
@RequestMapping("/file")
public String file(MultipartFile fileImage) throws IOException {
//1.获取图片的名字
String name =fileImage.getOriginalFilename();
//2.定义文件目录
String fileDirPath="D:/tena/images";
//3.创建目录
File fileDir=new File(fileDirPath);
if(!fileDir.exists()){
fileDir.mkdirs();
}
//4.生成文件的全路径
String filePath=fileDirPath+"/"+name;
File imageFile=new File(filePath);
//5.实现文件的上传
fileImage.transferTo(imageFile);
return "文件上传成功!!!";
}
}
页面url分析:
定义请求的参数和url
返回值JSON结构
{“error”:0,“url”:“图片的保存路径”,“width”:图片的宽度,“height”:图片的高度}
参数说明: 0代表是一张图片,如果是0,前台才可以解析并显示。1代表不是图片,
不显示如果不设置宽度和高度,则默认用图片原来的大小,所以不用设置
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 ImageVo {
private Integer error;//0 表示文件上传成功,1 上传失败
private String url;//图片浏览的网络地址(虚拟地址)
private Integer width;//宽度
private Integer height;//高度
public static ImageVo fail(){
return new ImageVo(1,null,null,null);
}
public static ImageVo success(String url,Integer height,Integer width){
return new ImageVo(0,url,width,height);
}
public static ImageVo success(String url){
return new ImageVo(0,url,null,null);
}
}
package com.jt.service;
import com.jt.vo.ImageVo;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@Service
public class FileServiceImpl implements FileService{
//定义图片类型
private static Set<String> imageTypeSet=new HashSet<>();
private String localDirPath="D:/tena/images";//定义本地磁盘目录
static{
imageTypeSet.add(".jpg");
imageTypeSet.add(".png");
imageTypeSet.add(".gif");
}
/**
* 1.校验文件的有效性
* 2.检验文件是否为恶意程序(木马.exe).jpg
* 3.提高用户检索图片的效率 分目录存储
* 4.为了防止重名图片的提交 自定义文件名称
* 5.实现图片的物理上传 本地磁盘中
* 6.准备一个访问图片的虚拟路径
* @param uploadFile
* @return ImageVo
* */
@Override
public ImageVo upload(MultipartFile uploadFile) {
//1.利用图片类型 利用正则表达式进行校验 利用集合进行校验
//1.1获取图片的名称
String fileName=uploadFile.getOriginalFilename();
fileName=fileName.toLowerCase();//将所有的字母都小写
//1.2获取图片的类型
int index=fileName.lastIndexOf(".");
String fileType=fileName.substring(index);
if(!imageTypeSet.contains(fileType)){//如果类型不匹配
return ImageVo.fail();//图片上传失败
}
//2.如何判断文件是否为恶意程序?文件是否有图片的特有属性
//2.1将上传的文件类型利用图片的API进行转化,如果转化不成功则一定不是图片
try {
BufferedImage bufferedImage= ImageIO.read(uploadFile.getInputStream());
//2.2检验是否有图片的特有属性 高度和宽度
int width=bufferedImage.getWidth();
int height=bufferedImage.getHeight();
//2.3检验宽度和高度是否有值
if(width==0||height==0){
return ImageVo.fail();
}
} catch (IOException e) {
e.printStackTrace();
return ImageVo.fail();
}
//3.实现分目录存储
//方案1:利用hash之后每隔2-3位截取之后拼接
//方案2:以时间为单位进行分割 /yyyy/MM/dd
//3.1利用工具API将时间转化为指定的格式
String datePath=new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
//3.2动态生成文件目录 两部分=根目录+时间目录
String localDir=localDirPath+datePath;
//3.3判断目录是否存在,如果不存在则新建目录
File dirFile=new File(localDir);
if(!dirFile.exists()){
dirFile.mkdirs();//如果不存在则新建目录
}
//4.防止文件重名,需要自定义文件名称
//4.1生成uuid
String uuid= UUID.randomUUID().toString().replace("-", "");
//4.2动态生成文件名称 uuid+.jpg
String uuidFileName=uuid+fileType;
//5.实现文件上传 准备文件全路径 目录+文件名称
String realFilePath=localDir+uuidFileName;
//5.1封装文件真实对象
File imageFile=new File(realFilePath);
try {
uploadFile.transferTo(imageFile);
} catch (IOException e) {
e.printStackTrace();
return ImageVo.fail();
}
//6.暂时使用京东图片代替
//检查文件上传业务调用是否正确
String url="https://img30.360buyimg.com/sku/jfs/t1/128256/32/4631/320177/5ee24409E0057d015/2d30b869688968d2.gif";
return ImageVo.success(url);
}
}
IDEA光标问题
选中代码每一行末尾都有光标:
在代码编辑区用鼠标单击右键把 Column Selection Model 前面的勾去掉就ok了