Day03-基于FastDFS+Nginx+Kinkeditor实现商品新增

一 文件的上传-commons-fileupload配置

1 服务器中启动FastDFS和Nginx

cd  /usr/local/soft/nginx/sbin/nginx

2 文件上传访问流程图

3 ego-manage中加入文件上传的依赖

<!-- 文件上传依赖 -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

4 在ego-manage-WebConfiguration中配置全局解释器

@Bean(name = "multipartResolver")//注意事项,上传解释器的对象名必须为这个,固定的
public CommonsMultipartResolver multipartResolver(){
    CommonsMultipartResolver resolver=new CommonsMultipartResolver();
    resolver.setMaxUploadSize(200000000);//最大文件上传大小 大约200m
    resolver.setDefaultEncoding("UTF-8");
    return resolver;
}

5 ego-manage新建图片控制器PicController

@RestController
@Slf4j
public class PicController {

    @PostMapping("/pic/upload")
  public Map<String,Object>update(MultipartFile uploadFile){
      log.debug("原始文件名:"+uploadFile.getOriginalFilename());
      return null;
  }
}

6 ego-manage-webConfiguration中新增“增加商品”路径

registry.addViewController("/item-add").setViewName("item-add");

7 启动项目,配置完成!

二 文件的上传-FastDFS的上传

1 commons加入FastDFS的依赖

<!--FastDFS依赖-->
<dependency>
    <groupId>cn.bestwu</groupId>
    <artifactId>fastdfs-client-java</artifactId>
    <version>1.27</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.10</version>
</dependency>

2 commons-util中增加FastDFS工具类

/**
 * FastDFS分布式文件系统操作客户端.
 */
public class FastDFSClient {
    // private static final String CONF_FILENAME = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";
    private static final String CONF_FILENAME = "fdfs_client.conf";
    private static StorageClient storageClient = null;
    /**
     * 只加载一次.
     */
    static {
        try {
            ClientGlobal.init(CONF_FILENAME);
            TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
            TrackerServer trackerServer = trackerClient.getConnection();
            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            storageClient = new StorageClient(trackerServer, storageServer);
        } catch (Exception e) {
            e.printStackTrace();}}
    /**
     * @param inputStream 上传的文件输入流
     * @param fileName    上传的文件原始名
     * @return
     */
    public static String[] uploadFile(InputStream inputStream, String fileName) {
        try {
            // 文件的元数据
            NameValuePair[] meta_list = new NameValuePair[2];
            // 第一组元数据,文件的原始名称
            meta_list[0] = new NameValuePair("file name", fileName);
            // 第二组元数据
            meta_list[1] = new NameValuePair("file length", inputStream.available() + "");
            // 准备字节数组
            byte[] file_buff = null;
            if (inputStream != null) {
                // 查看文件的长度
                int len = inputStream.available();
                // 创建对应长度的字节数组
                file_buff = new byte[len];
                // 将输入流中的字节内容,读到字节数组中。
                inputStream.read(file_buff);}
            // 上传文件。参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),元数据
            String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
            return fileids;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;}}
    /**
     * @param file     文件
     * @param fileName 文件名
     * @return 返回Null则为失败
     */
    public static String[] uploadFile(File file, String fileName) {
        FileInputStream fis = null;
        try {
            NameValuePair[] meta_list = null; // new NameValuePair[0];
            fis = new FileInputStream(file);
            byte[] file_buff = null;
            if (fis != null) {
                int len = fis.available();
                file_buff = new byte[len];
                fis.read(file_buff);}
            String[] fileids = storageClient.upload_file(file_buff, getFileExt(fileName), meta_list);
            return fileids;
        } catch (Exception ex) {
            return null;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace(); }}}}
    /**
     * 根据组名和远程文件名来删除一个文件
     * @param groupName      例如 "group1" 如果不指定该值,默认为group1
     * @param remoteFileName 例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg"
     * @return 0为成功,非0为失败,具体为错误代码
     */
    public static int deleteFile(String groupName, String remoteFileName) {
        try {
            int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
            return result;
        } catch (Exception ex) {
            return 0;
        }
    }
    /**
     * 修改一个已经存在的文件
     *
     * @param oldGroupName 旧的组名
     * @param oldFileName  旧的文件名
     * @param file         新文件
     * @param fileName     新文件名
     * @return 返回空则为失败
     */
    public static String[] modifyFile(String oldGroupName, String oldFileName, File file, String fileName) {
        String[] fileids = null;
        try {
            // 先上传
            fileids = uploadFile(file, fileName);
            if (fileids == null) {
                return null;
            }
            // 再删除
            int delResult = deleteFile(oldGroupName, oldFileName);
            if (delResult != 0) {
                return null;
            }
        } catch (Exception ex) {
            return null;
        }
        return fileids;
    }

    /**
     * 文件下载
     *
     * @param groupName      卷名
     * @param remoteFileName 文件名
     * @return 返回一个流
     */
    public static InputStream downloadFile(String groupName, String remoteFileName) {
        try {
            byte[] bytes = storageClient.download_file(groupName, remoteFileName);
            InputStream inputStream = new ByteArrayInputStream(bytes);
            return inputStream;
        } catch (Exception ex) {
            return null;
        }
    }

    public static NameValuePair[] getMetaDate(String groupName, String remoteFileName) {
        try {
            NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
            return nvp;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * 获取文件后缀名(不带点).
     *
     * @return 如:"jpg" or "".
     */
    private static String getFileExt(String fileName) {
        if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
            return "";
        } else {
            return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
        }
    }
}

3 在commons-resourece中加入配置文件

  fdfs_client.conf

4 新建一个vo类UploadResult
专门用来出来文件上传的返回

/**
 * 问题:上传返回的参数名是谁决定的
 * 答:使用前台的KingEditor控件决定的
 */
@Data
public class UploadResult {
    private int error;
    private String url;
    private String message;

    public static UploadResult ok(String url){
        UploadResult result=new UploadResult();
        result.setError(0);//成功错误码为0
        result.setUrl(url);
        result.setMessage(null);
        return result;
    }
    public static UploadResult error(String message){
        UploadResult result=new UploadResult();
        result.setError(1);//失败错误码为1
        result.setUrl(null);
        result.setMessage(message);
        return result;
    }
}

5 ego-manage新建接口

public interface PicService {
    /**
     * 文件上传
     * @param file spring MVC上传对象
     */
    UploadResult update(MultipartFile file) throws IOException;
}

6 ego-manage接口PicService 实现类
6.1前提
需要一个获取生成图片名或商品id的工具类

/**
 * 各种id生成策略
 * @version 1.0
 */
public class IDUtils {

   /**
    * 图片名生成
    */
   public static String genImageName() {
      //取当前时间的长整形值包含毫秒
      long millis = System.currentTimeMillis();
      //long millis = System.nanoTime();
      //加上三位随机数
      Random random = new Random();
      int end3 = random.nextInt(999);
      //如果不足三位前面补0
      String str = millis + String.format("%03d", end3);
      return str;
   }
   
   /**
    * 商品id生成
    */
   public static long genItemId() {
      //取当前时间的长整形值包含毫秒
      long millis = System.currentTimeMillis();
      //long millis = System.nanoTime();
      //加上两位随机数
      Random random = new Random();
      int end2 = random.nextInt(99);
      //如果不足两位前面补0
      String str = millis + String.format("%02d", end2);
      long id = new Long(str);
      return id;
   }
   
   public static void main(String[] args) {
      for(int i=0;i< 100;i++)
      System.out.println(genItemId());
   }
}

6.2编写PicServiceImp

@Service
@Slf4j
public class PicServiceImp implements PicService {


    @Value("${ego.upload.base.path}")
    private String basePath;


    @Override
    public UploadResult update(MultipartFile file) throws IOException {
        //输入流
        //文件名 自定义一个不重复的文件名
        String imageName = IDUtils.genImageName();
        String originalFilename = file.getOriginalFilename();
        String fileName=imageName+originalFilename.substring(originalFilename.lastIndexOf("."));

        String[] strings = FastDFSClient.uploadFile(file.getInputStream(), fileName);

        log.debug(Arrays.toString(strings));

        //构建访问路径格式: http://192.168.56.100/组名/文件名
        log.debug("基础路径:"+basePath);
        String url=basePath+"/"+strings[0]+"/"+strings[1];
        log.debug("图片访问路径:"+url);
        return UploadResult.ok(url);
    }
}

7 编辑PicController

@RestController
@Slf4j
public class PicController {

    @Autowired
    private PicService picService;
    @PostMapping("/pic/upload")
    public UploadResult update(MultipartFile uploadFile){
        try {
            log.debug("原始文件名:"+uploadFile.getOriginalFilename());
            return picService.update(uploadFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return UploadResult.error("上传失败");
    }
}

8 启动项目,上传图片
8.1上传成功
在这里插入图片描述

8.2 http访问到

在这里插入图片描述

三 类目的选择-异步树的实现

1 导入ItemCat的pojo和mapper

@Data
@TableName("tb_item_cat")
public class ItemCat implements Serializable {

  @TableId(type = IdType.AUTO)
  private Long id;
  private Long parentId;
  private String name;
  private Integer status;
  private Integer sortOrder;
  private Integer isParent;
  private Date created;
  private Date updated;
}
public interface ItemCatMapper extends BaseMapper<ItemCat> {
}

2 commons新建ItemCatDubboService

public interface ItemCatDubboService {
    /**
     * 根据父id查询所有子类目
     * @param pid 父id
     * @return 所有子类目
     */
    List<ItemCat> selectByPid(Long pid);
}

3 ItemCatDubboServiceImp实现

@DubboService
public class ItemCatDubboServiceImp implements ItemCatDubboService {
    @Autowired
    private ItemCatMapper itemCatMapper;

    @Override
    public List<ItemCat> selectByPid(Long pid) {
        QueryWrapper<ItemCat> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", pid);
        wrapper.eq("status", 1);
        List<ItemCat> itemCats = itemCatMapper.selectList(wrapper);
        return itemCats;
    }
}

4 新增异步树的vo实现类EasyUITree

/**
 * 树节点
 */
@Data
public class EasyUITree {
    private Long id;
    private String text;
    private String state;
}

4 ego-manage的服务层调用
ItemCatService

public interface ItemCatService {
    /**
     * 显示树状菜单
     *
     * @param pid 父id
     * @return 所有子菜单
     */
    List<EasyUITree> showTree(Long pid) ;

}

ItemCatServiceImp

@Service
public class ItemCatServiceImp implements ItemCatService {
    @DubboReference
    private ItemCatDubboService itemCatDubboService;

    @Override
    public List<EasyUITree> showTree(Long pid) {
        //第一步 获取返回对象
        List<EasyUITree> nodes = new ArrayList<>();
        // 第二步 获得数据
        List<ItemCat> tbItemCats = itemCatDubboService.selectByPid(pid);
        // 第三步 封装数据
        for (ItemCat tbItemCat : tbItemCats) {
            EasyUITree node = new EasyUITree();
            node.setId(tbItemCat.getId());
            node.setText(tbItemCat.getName());
            //默认情况下,需要折叠,异步树的实现机制
            //数据库里有一个is_parent 是父节点,表示该节点是根节点或枝节点,不然为叶节点
            //根据分析,叶节点都没有子节点了,所以展开
            //根和枝节点 有子节点,所以需要折叠
            if (tbItemCat.getIsParent() == 1) {
                node.setState("closed");//折叠 EasyUI确定的字符串,表示折叠
            } else {
                node.setState("open");//打开
            }
            nodes.add(node);
        }
        return nodes;
    }
}

5 新建ItemCatController

@RestController
@RequestMapping(value = "/item/cat")
public class ItemCatController {
    @Autowired
    private ItemCatService itemCatService;
    @PostMapping(value = "/list")
    public List<EasyUITree> showTree(@RequestParam(defaultValue = "0")Long id){
        return itemCatService.showTree(id);
    }
}

6 启动项目 查看类目列表
在这里插入图片描述

四 新增商品

前提须知
新增商品时,新增商品的数据其实是insert到tb_item 和 tb_item_desc两张表的

1 导入tb_item_desc表的pojo和mapper

@Data
@TableName("tb_item_desc")
public class ItemDesc implements Serializable {
  @TableId(type = IdType.INPUT)
  private Long itemId;
  private String itemDesc;
  private Date created;
  private Date updated;
}
public interface ItemDescMapper extends BaseMapper<ItemDesc> {
}

2 ItemDubboService 新增插入方法

/**
 * 新增商品
 */
int insert(Item item, ItemDesc itemDesc) throws DaoException;

3 provider- ItemDubboServiceImp实现

@Override
public int insert(Item item, ItemDesc itemDesc) throws DaoException {
    //第一步 插入商品表数据
    Long itemId = IDUtils.genItemId();
    item.setId(itemId);
    item.setUpdated(new Date());
    item.setCreated(item.getUpdated());
    item.setStatus(1);
    itemMapper.insert(item);
    System.out.println(itemId);
    //第二步 插入商品详情
    itemDesc.setItemId(itemId);
    itemDesc.setUpdated(item.getUpdated());
    itemDesc.setCreated(item.getCreated());
    itemDescMapper.insert(itemDesc);
    return 1;
}

4 manage服务层远程调用
ItemService

/**
 * 保存商品信息
 */
EgoResult save(Item item, String  tbItemDesc) throws DaoException;

ItemServiceImp

@Override
public EgoResult save(Item item, String tbItemDesc) throws DaoException {
    ItemDesc itemDescObject=new ItemDesc();
    itemDescObject.setItemDesc(tbItemDesc);
    int insert = itemDubboService.insert(item, itemDescObject);
    if (insert==1){
        return EgoResult.ok();
    }
    return EgoResult.error("增加商品失败");
}

5 编写ItemController

/**
 * 增加商品
 */
@PostMapping("/save")
public EgoResult insert(Item item, String desc){
    try {
        return itemService.save(item,desc);
    } catch (DaoException e) {
        e.printStackTrace();
    }
    return EgoResult.error("增加商品失败");
}

6 启动项目,实现商品新增
在这里插入图片描述

数据库可以查询到
在这里插入图片描述

五 实现商品的编辑

1 编辑跳转路径
在item-list页面修改编辑跳转的路径为”item-edit”

<div id="itemEditWindow" class="easyui-window" title="编辑商品" data-options="modal:true,closed:true,iconCls:'icon-save',href:'/item-edit'" style="width:80%;height:80%;padding:10px;">

2 WebConfiguration新增编辑路径

registry.addViewController("/item-edit").setViewName("item-edit");

3 新建ItemDescDubboService

public interface ItemDescDubboService {
    /**
     * 根据商品编号查询商品详细信息
     * @param id
     * @return
     */
    ItemDesc selectById(Long id);
}

4 provider实现ItemDescDubboService

@DubboService
public class ItemDescDubboServiceImp implements ItemDescDubboService {
    @Autowired
    private ItemDescMapper itemDescMapper;

    @Override
    public ItemDesc selectById(Long id) {
        return itemDescMapper.selectById(id);
    }
}

5 manage服务层调用
ItemDescService

public interface ItemDescService {
    /**
     * 通过编号查询指定商品描述
     * @param id
     * @return
     */
    EgoResult selectById(Long id);
}

ItemDescServiceImp

@Service
public class ItemDescServiceImp implements ItemDescService {
    @DubboReference
    private ItemDescDubboService itemDescDubboService;
    @Override
    public EgoResult selectById(Long id) {
        ItemDesc itemDesc = itemDescDubboService.selectById(id);
        return EgoResult.ok(itemDesc);
    }
}

6 在item-list页面修改获取商品详细信息的路径
在这里插入图片描述

7 新建ItemDescController

@RestController
@RequestMapping("/item/desc")
public class ItemDescController {

    /**
     * 根据商品编号显示详细内容
     */
    @Autowired
    private ItemDescService itemDescService;

    @GetMapping("/{id}")
    public EgoResult showDesc(@PathVariable Long id){
        return itemDescService.selectById(id);
    }
}

8 ItemDubboService 商品更新方法

/**
 * 商品更新
 */
int update(Item item, ItemDesc itemDesc) throws DaoException;

9 ItemDubboServiceImp实现更新方法

@Override
public int update(Item item, ItemDesc itemDesc) throws DaoException {
    //第一步 更新商品表数据
    item.setUpdated(new Date());
    item.setCreated(item.getUpdated());
    itemMapper.updateById(item);
    //第二步 插入商品详情
    itemDesc.setUpdated(item.getUpdated());
    itemDesc.setCreated(item.getCreated());
    itemDescMapper.updateById(itemDesc);
    return 1;
}

10 manage服务层远程调用
ItemService

/**
 * 更新商品信息
 */
EgoResult update(Item item, String  itemDesc) throws DaoException;

ItemServiceImp

@Override
public EgoResult update(Item item, String itemDesc) throws DaoException {
    ItemDesc tbItemDescObject=new ItemDesc();
    tbItemDescObject.setItemId(item.getId());
    tbItemDescObject.setItemDesc(itemDesc);
    int insert = itemDubboService.update(item, tbItemDescObject);
    if (insert==1){
        return EgoResult.ok();
    }
    return EgoResult.error("编辑商品失败");
}

11 在 item-edit页面修改编辑跳转路径

$.post("/item/update",$("#itemeEditForm").serialize(), function(data){

12 编辑ItemController

/**
 * 编辑商品
 */
@PostMapping("/update")//更新使用POST方法
public EgoResult update(Item item,String desc) {
    try {
        return itemService.update(item,desc);
    } catch (DaoException e) {
        e.printStackTrace();
    }
    return EgoResult.error("编辑失败");
}

13 启动项目 编辑成功

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值