【校园商铺 4章】:店铺注册--Service层的实现(后期还要改造,先前没实现)

1.Thumbnailator图片处理

1.1引入图片处理jar包

<dependency>
	<groupId>net.coobird</groupId>
	<artifactId>thumbnailator</artifactId>
	<version>0.4.8</version>
</dependency>

1.2.Thumbnailator图片处理
要加水印的图片位置:E:/JAVA/JAVA1/javaEE/xiaoyuanshangpu/xiaohuangren.jpg
水印图片的位置要在:src/main/resources下,这样便于访问到,如果不放在对应java的resources下,不能访问到。
在这里插入图片描述

2. 编写工具类:ImageUtil和PathUtil

ImageUtil.java

public class ImageUtil {
    public static void main(String[] args) throws IOException {
        //获取Classpath的路径
        String basePath = Thread.currentThread()
                .getContextClassLoader()
                .getResource("").getPath();
        System.out.println(basePath);
        //要处理的图片
        Thumbnails.of(new File("E:/JAVA/JAVA1/javaEE/xiaoyuanshangpu/xiaohuangren.jpg"))
                //输出图片的长和宽
                .size(800,600)
                //给图片添加水印,三个参数
                .watermark(                        //水印位置
                        Positions.BOTTOM_RIGHT,
                        //水印图片的路径
                        ImageIO.read(new File(basePath+"watermark.jpg")),
                        //水印透明度
                        0.75f)
                //压缩80%
                .outputQuality(0.8f)
                //输出添加水印后图片的位置
                .toFile("E:/JAVA/JAVA1/javaEE/xiaoyuanshangpu/xiaohuangrennew.jpg");
    }
}

结果展示:在E:/JAVA/JAVA1/javaEE/xiaoyuanshangpu/文件夹下
在这里插入图片描述
注意:最好把路径都设为英文名称,如果项目名称为中文名称,水印图片无法读取

PathUtil.java

package com.imooc.o2o.util;
public class PathUtil {
    //本系统的分隔符
    private static String seperator=System.getProperty("file.separator");
    //根据不同的操作系统,设置储存图片文件不同的根目录(根路径),不带图片的名称xxx.jpg
    public static String getImgBasePath(){
        String os=System.getProperty("os.name");
        String basePath="";
        if (os.toLowerCase().startsWith("win")){
            basePath="E:/JAVA/JAVA1/javaEE/xiaoyuanshangpu/image";//根据自己的实际路径进行设置根目录
        }else {
            basePath = "/home/o2o/image";//根据自己的实际路径进行设置
        }
        //linux为/,windows为\,通过代替语法将本系统分隔符代替
        basePath=basePath.replace("/",seperator);
        return basePath;
    }
    //根据shopId返回项目图片相对路径(子路径),不带图片的名称xxx.jpg
    public static String getShopImagePath(long shopId){
        String imagePath = "/upload/item/shop/"+ shopId + "/";//自动生成此路径
        return imagePath.replace("/",seperator);
    }
}

完善ImageUtil.java

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class ImageUtil {
    //classpath路径
    private static String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
    private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
    private static final Random r = new Random();

    /**
     * 处理缩略图,并返回新生成图片的相对值路径
     * @param thumbnail 用户上传的文件
     * @param targetAddr 新的文件存储在targetAddr目录中
     * @return 返回门面照和小图
     */
    public static String generateThumbnail(File thumbnail,String targetAddr) {
        //获取文件的随机名称
        String realFileName = getRandomFileName();
        //获取用户上传的文件的扩展名称(文件后缀)
        String extension = getFileExtension(thumbnail);

        //创建图片的存储目录(这个目录包括根目录加上相对目录)
        makeDirPath(targetAddr);
        //图片的目录
        String relativeAddr = targetAddr +realFileName + extension;
        File dest = new File(PathUtil.getImgBasePath() + relativeAddr);
        try {
            Thumbnails.of(thumbnail).size(200, 200)
                    .watermark(Positions.BOTTOM_RIGHT,ImageIO.read(new File(basePath + "watermark.jpg")),0.25f)
                    .outputQuality(0.8f).toFile(dest);
        }catch (IOException e) {
            e.printStackTrace();
        }

        return relativeAddr;
    }

    /**
     * 创建目标路径所涉及到的目录,即/home/work/o2o/xxx.jpg,
     * 那么 home work o2o 这三个文件夹都得自动创建
     * @param targetAddr
     */
    private static void makeDirPath(String targetAddr) {
        String realFileParentPath = PathUtil.getImgBasePath()+targetAddr;
        File dirPath = new File(realFileParentPath);
        if(!dirPath.exists()) {
            dirPath.mkdirs();
        }
    }

    /**
     * 生成随机文件名,当前年月日小时分钟秒+五位随机数
     */
    private static String getRandomFileName() {
        //获取随机的五位数
        int rannum = r.nextInt(89999) + 10000;
        //获取当前的年月日时分秒
        String nowTimeStr = sDateFormat.format(new Date());
        //随机文件名
        return nowTimeStr+rannum;
    }
    /**
     * 获取输入文件流的扩展名
     * @throws IOException
     */
    private static String getFileExtension(File thumbnail) {
        String originalFileName = thumbnail.getName();
        return originalFileName.substring(originalFileName.lastIndexOf("."));
    }
}

3.dto:ShopException和enums:ShopStateEnum

3.1枚举类:ShopStateEnum

package com.imooc.o2o.enums;
/**结果的状态和状态标识*/
public enum ShopStateEnum {
    CHECK(0,"审核中"),
    OFFLINE(-1,"非法店铺"),
    SUCCESS(1,"操作成功"),
    PASS(2,"通过认证"),
    INNER_ERROR(-1001,"内部程序错误"),
    NULL_SHOPID(-1002,"ShopId为空"),
    NULL_SHOP(-1003,"shop信息为空");

    private int state;
    private String stateInfo;

    private ShopStateEnum(int state,String stateInfo){
        this.state = state;
        this.stateInfo =  stateInfo;
    }

    /**
     * 相当于key=state; value=stateInfo
     * 根据传入的state返回相应的enum值,即状态标识:stateInfo
     * values()指的是stateInfo数组
     */
    public static ShopStateEnum stateOf(int state){
        for(ShopStateEnum stateEnum:values()){
            //获取状态结果state
            if(stateEnum.getState()==state){
                return stateEnum;//返回状态标识
            }
        }
        return null;
    }

    public int getState() {
        return state;
    }

    public String getStateInfo() {
        return stateInfo;
    }
}

3.2 dto包的返回值类型:shop

package com.imooc.o2o.dto;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.enums.ShopStateEnum;
import java.util.List;
/**
 * 添加店铺的返回类型
 */
public class ShopExecution {
    //结果的状态
    private int state;

    //状态标识
    private String stateInfo;

    //店铺数量
    private int count;

    //操作的店铺(增删改店铺的时候用到)
    private Shop shop;

    //shop列表(查询店铺的时候用到)
    private List<Shop> shopList;

    public ShopExecution() {
    }

    //店铺操作失败时使用的构造器
    public ShopExecution(ShopStateEnum stateEnum){
        this.state = stateEnum.getState();
        this.stateInfo = stateEnum.getStateInfo();
    }

    //店铺操作成功时使用的构造器
    public ShopExecution(ShopStateEnum stateEnum, Shop shop){
        this.state = stateEnum.getState();
        this.stateInfo = stateEnum.getStateInfo();
        this.shop = shop;
    }

    //店铺操作成功时使用的构造器
    public ShopExecution(ShopStateEnum stateEnum, List<Shop> shopList){
        this.state = stateEnum.getState();
        this.stateInfo = stateEnum.getStateInfo();
        this.shopList = shopList;
    }

    public int getState() {
        return state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

    public int getCount() {
        return count;
    }

    public Shop getShop() {
        return shop;
    }

    public List<Shop> getShopList() {
        return shopList;
    }

    public void setState(int state) {
        this.state = state;
    }

    public void setStateInfo(String stateInfo) {
        this.stateInfo = stateInfo;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public void setShop(Shop shop) {
        this.shop = shop;
    }

    public void setShopList(List<Shop> shopList) {
        this.shopList = shopList;
    }
}

4. Service层的实现(店铺注册)

ShopServiceImpl.java

package com.imooc.o2o.service.Impl;
import com.imooc.o2o.dao.ShopDao;
import com.imooc.o2o.dto.ShopExecution;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.enums.ShopStateEnum;
import com.imooc.o2o.exceptions.ShopOperationException;
import com.imooc.o2o.service.ShopService;
import com.imooc.o2o.util.ImageUtil;
import com.imooc.o2o.util.PathUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.util.Date;
@Service
public class ShopServiceImpl implements ShopService {
    @Autowired
    private ShopDao shopDao;

    /**
     * @param shop 创建的店铺
     * @param shopImg 用户上传的店铺图片文件
     * @return 添加店铺的结果信息
     */
    @Transactional//事务,方法需要事务支持
    public ShopExecution addShop(Shop shop, File shopImg) {
        //空值判断
        if (shop == null) {
            return new ShopExecution(ShopStateEnum.NULL_SHOP);
        }
        try {
            //给店铺信息赋初始值
            shop.setEnableStatus(0);//审核中,未上架
            shop.setCreateTime(new Date());
            shop.setLastEditTime(new Date());
            int effectedNum = shopDao.insertShop(shop);//添加店铺信息
            if (effectedNum <= 0) {
                throw new ShopOperationException("店铺创建失败");//事务终止并回滚
            } else {//店铺创建成功
                if (shopImg != null) { //判断传入的文件是否为空,如果不为空就将图片存储到对应的目录中
                    try {
                        //根据shopId获取图片存储的相对路径
                        //根据相对路径给图片添加水印,并且存储在绝对路径中
                        addShopImg(shop, shopImg);//存储图片
                    } catch (Exception e) {
                        throw new ShopOperationException("addShopImg error" + e.getMessage());
                    }
                    //添加店铺的时候数据库中并没有添加店铺的图片地址,因此需要更新店铺信息
                    effectedNum = shopDao.updateShop(shop);//更新店铺的图片地址
                    if (effectedNum <= 0) {
                        throw new ShopOperationException("更新图片地址失败");
                    }
                }
            }
        } catch (Exception e) {
            throw new ShopOperationException("addShop error:" + e.getMessage());
        }
        return new ShopExecution(ShopStateEnum.CHECK, shop);
    }

    private void addShopImg(Shop shop, File shopImg) {
        //根据shopId获取店铺图片的相对路径
        String dest = PathUtil.getShopImagePath(shop.getShopId());
        //给图片添加水印并将图片存储在绝对值路径中,返回图片的相对值路径
        String shopImgAddr = ImageUtil.generateThumbnail(shopImg, dest);
        shop.setShopImg(shopImgAddr);
    }
}

为什么对添加店铺的方法添加事务?
添加店铺的方法中有三个步骤:添加店铺信息,存储图片,更新店铺信息
三个步骤中的任何一个步骤出现了问题,都希望事务进行回滚,不要将店铺信息进行添加

自己定义的异常

public class ShopOperationException extends RuntimeException {
    public ShopOperationException(String msg){
        super(msg);
    }
}

5. 测试添加店铺

ShopServiceTest.java

import com.imooc.o2o.BaseTest;
import com.imooc.o2o.dto.ShopExecution;
import com.imooc.o2o.entity.Area;
import com.imooc.o2o.entity.PersonInfo;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.entity.ShopCategory;
import com.imooc.o2o.enums.ShopStateEnum;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.util.Date;
import static org.junit.Assert.assertEquals;
public class ShopServiceTest extends BaseTest {
    @Autowired
    private ShopService shopService;

    @Test
    public void testAddShop(){
        Shop shop = new Shop();
        PersonInfo owner = new PersonInfo();
        Area area = new Area();
        ShopCategory shopCategory = new ShopCategory();
        owner.setUserId(1L);
        area.setAreaId(2);
        shopCategory.setShopCategoryId(1L);
        shop.setOwner(owner);
        shop.setArea(area);
        shop.setShopCategory(shopCategory);

        shop.setShopName("测试的店铺1");
        shop.setShopDesc("test1");
        shop.setShopAddr("test1");
        shop.setPhone("test1");
        shop.setCreateTime(new Date());
        shop.setEnableStatus(ShopStateEnum.CHECK.getState());
        shop.setAdvice("审核中");
        File shopImg = new File("E:/JAVA/JAVA1/javaEE/xiaoyuanshangpu/xiaohuangren.jpg");
        ShopExecution shopExecution = shopService.addShop(shop, shopImg);
        assertEquals(ShopStateEnum.CHECK.getState(), shopExecution.getState());
    }
}

说明:需要将watermark.jpg文件放在src/test/resources目录下,才能读取到水印图片。同src/main/resources一样要与java对应
在这里插入图片描述
绝对路径下生成的图片,带shopId 24
E:\JAVA\JAVA1\javaEE\xiaoyuanshangpu\image\upload\item\shop\24
在这里插入图片描述
在这里插入图片描述

6.本service实现的目录

在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值