在pom.xml文件中添加:
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
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("F:/XiaoYuanShangPu/xiaohuangren.jpg"))
//输出图片的长和宽
.size(800, 600)
//给图片添加水印,三个参数
.watermark( //水印位置
Positions.BOTTOM_RIGHT,
//水印图片的路径
ImageIO.read(new File(basePath + "watermark.jpg")),
//水印透明度
0.75f)
//压缩80%
.outputQuality(0.8f)
//输出添加水印后图片的位置
.toFile("F:/XiaoYuanShangPu/xiaohuangrennew.jpg");
}
}
总共涉及到三个文件路径:
要处理的图片路径:
水印图片路径:
加完水印后新的图片的输出路径:
需要说明的是:项目名称不能有中文名称,否则无法读取水印图片
封装图片文件路径:
public class PathUtil {
private static String seperator = System.getProperty("file.separator");
//根据不同的操作系统,设置储存图片文件不同的根目录
public static String getImgBasePath() {
String os =System.getProperty("os.name");
String basePath = "";
if(os.toLowerCase().startsWith("win")) {
basePath = "F:/XiaoYuanShangPu/image/";//根据自己的实际路径进行设置
}else {
basePath = "/home/o2o/image/";//根据自己的实际路径进行设置
}
//linux为/,windows为\
basePath = basePath.replace("/", seperator);
return basePath;
}
//根据shopId返回项目图片相对路径
public static String getShopImagePath(long shopId) {
String imagePath = "upload/item/shop/"+ shopId + "/";//自动生成此路径,图片的相对路径
return imagePath.replace("/", seperator);
}
}
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class ImageUtil {
private static final Logger logger = LoggerFactory.getLogger(ImageUtil.class);
//获取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 thumbnailInputStream 用户上传的图片文件流
* @param fileName 图片文件
* @param targetAddr 新的文件存储在targetAddr目录中
* @return 处理缩略图,并返回新生成图片的相对值路径
*/
public static String generateThumbnail(InputStream thumbnailInputStream,String fileName, String targetAddr) {
//获取文件的随机名称
String realFileName = getRandomFileName();
//获取用户上传的文件的扩展名称(文件后缀)
String extension = getFileExtension(fileName);
//创建图片的存储目录(这个目录包括根目录加上相对目录)
makeDirPath(targetAddr);
//图片的相对目录
String relativeAddr = targetAddr +realFileName + extension;
logger.debug("图片的相对路径:"+relativeAddr);
//图片的绝对目录
File dest = new File(PathUtil.getImgBasePath() + relativeAddr);
logger.debug("图片完整路径:"+dest.getAbsolutePath());
try {
//可以传入文件,也可以传入图片流
Thumbnails.of(thumbnailInputStream).size(200, 200)
.watermark(Positions.BOTTOM_RIGHT,ImageIO.read(new File(basePath + "watermark.jpg")),0.25f)
.outputQuality(0.8f).toFile(dest);
}catch (IOException e) {
logger.error(e.toString());
e.printStackTrace();
}
return relativeAddr;
}
/**
* 创建目标路径所涉及到的目录
* 如:upload/item/shop/xxx.jpg,那么upload,item,shop这三个文件夹都得自动创建
* @param targetAddr
*/
private static void makeDirPath(String targetAddr) {
String realFileParentPath = PathUtil.getImgBasePath()+targetAddr;
File dirPath = new File(realFileParentPath);
if(!dirPath.exists()) {
dirPath.mkdirs();
}
}
/**
* 生成随机文件名,当前年月日小时分钟秒+五位随机数
*/
public static String getRandomFileName() {
//获取随机的五位数
int rannum = r.nextInt(89999) + 10000;
//获取当前的年月日时分秒
String nowTimeStr = sDateFormat.format(new Date());
//随机文件名
return nowTimeStr+rannum;
}
/**
* 获取输入文件的扩展名
* @throws IOException
*/
private static String getFileExtension(String fileName) {
return fileName.substring(fileName.lastIndexOf("."));
}
public static void main(String[] args) throws IOException {
//获取Classpath的路径
String basePath = Thread.currentThread()
.getContextClassLoader()
.getResource("").getPath();
System.out.println(basePath);
//要处理的图片
Thumbnails.of(new File("F:/XiaoYuanShangPu/xiaohuangren.jpg"))
//输出图片的长和宽
.size(800, 600)
//给图片添加水印,三个参数
.watermark( //水印位置
Positions.BOTTOM_RIGHT,
//水印图片的路径
ImageIO.read(new File(basePath + "watermark.jpg")),
//水印透明度
0.75f)
//压缩80%
.outputQuality(0.8f)
//输出添加水印后图片的位置
.toFile("F:/XiaoYuanShangPu/xiaohuangrennew.jpg");
}
}
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;
}
/**
* 根据传入的state返回相应的enum值
*/
public static ShopStateEnum stateOf(int state){
for(ShopStateEnum stateEnum:values()){
if(stateEnum.getState()==state){
return stateEnum;
}
}
return null;
}
public int getState() {
return state;
}
public String getStateInfo() {
return stateInfo;
}
}
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;
}
}
import com.imooc.o2o.dto.ShopExecution;
import com.imooc.o2o.entity.Shop;
import java.io.InputStream;
public interface ShopService {
ShopExecution addShop(Shop shop, InputStream shopImgInputStream,String fileName);
}
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.InputStream;
import java.util.Date;
@Service
public class ShopServiceImpl implements ShopService {
@Autowired
private ShopDao shopDao;
/**
*
* @param shop 创建的店铺
* @param shopImgInputStream 图片文件流
* @param fileName 图片文件
* @return 返回状态信息结果
* @throws ShopOperationException
* 后面两个传入参数都是与图片处理有关,用于向店铺中添加shopImg信息
*/
@Transactional//事务,方法需要事务支持
public ShopExecution addShop(Shop shop, InputStream shopImgInputStream,String fileName) throws ShopOperationException {
//空值判断
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 (shopImgInputStream != null) {
//判断传入的文件流是否为空,如果不为空就将图片存储到对应的目录中
try {
//根据shopId获取图片存储的相对路径
//根据相对路径给图片添加水印,并且存储在绝对路径中
addShopImg(shop,shopImgInputStream,fileName);//存储图片
} 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, InputStream shopImgInputStream,String fileName) {
//根据shopId获取店铺图片的相对路径
String dest = PathUtil.getShopImagePath(shop.getShopId());
//给图片添加水印并将图片存储在绝对值路径中,返回图片的相对值路径
String shopImgAddr = ImageUtil.generateThumbnail(shopImgInputStream,fileName, dest);
shop.setShopImg(shopImgAddr);
}
}
public class ShopOperationException extends RuntimeException {
public ShopOperationException(String msg){
super(msg);
}
}
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.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Date;
import static org.junit.Assert.assertEquals;
public class ShopServiceTest extends BaseTest {
@Autowired
private ShopService shopService;
@Test
public void testAddShop() throws FileNotFoundException {
Shop shop = new Shop();
PersonInfo owner = new PersonInfo();
Area area = new Area();
ShopCategory shopCategory = new ShopCategory();
owner.setUserId(2L);
area.setAreaId(2);
shopCategory.setShopCategoryId(1L);
shop.setOwner(owner);
shop.setArea(area);
shop.setShopCategory(shopCategory);
shop.setShopName("咖啡店");
shop.setShopDesc("出售咖啡");
shop.setShopAddr("北京");
shop.setPhone("7632554");
shop.setCreateTime(new Date());
shop.setEnableStatus(ShopStateEnum.CHECK.getState());
shop.setAdvice("审核中");
//要传入的文件
File shopImg = new File("F:/XiaoYuanShangPu/xiaohuangren.jpg");
//将图片文件封装为文件流
InputStream is = new FileInputStream(shopImg);
//添加图片信息
ShopExecution shopException = shopService.addShop(shop,is,shopImg.getName());
assertEquals(ShopStateEnum.CHECK.getState(),shopException.getState());
}
}