先前的代码可能会实现不了,现在改造,最后实现结果了
package com.imooc.o2o.util;
import javax.servlet.http.HttpServletRequest;
public class HttpServletRequestUtil {
//转换成整型
public static int getInt(HttpServletRequest request,String key){
try {
//将key对应的参数值转换成整型
return Integer.decode(request.getParameter(key));
} catch (Exception e) {
return -1;
}
}
//转换成长整型
public static long getLong(HttpServletRequest request,String key){
try {
//将key对应的参数值转换成长整型
return Long.valueOf(request.getParameter(key));
} catch (Exception e) {
return -1;
}
}
//转换成浮点型
public static Double getDouble(HttpServletRequest request,String key){
try {
//将key对应的参数值转换成浮点型
return Double.valueOf(request.getParameter(key));
} catch (Exception e) {
return -1d;
}
}
//转换成布尔类型
public static boolean getBoolean(HttpServletRequest request,String key){
try {
//将key对应的参数值转换成布尔类型
return Boolean.valueOf(request.getParameter(key));
} catch (Exception e) {
return false;
}
}
//转换成String类型
public static String getString(HttpServletRequest request,String key){
try {
//将key对应的参数值转换成String
String result=request.getParameter(key);
if (result != null) {
result=result.trim();
}
if("".equals(result)){
result=null;
}
return result;
} catch (Exception e) {
return null;
}
}
}
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.o2o.dto.ShopExecution;
import com.imooc.o2o.entity.PersonInfo;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.enums.ShopStateEnum;
import com.imooc.o2o.service.ShopService;
import com.imooc.o2o.util.HttpServletRequestUtil;
import com.imooc.o2o.util.ImageUtil;
import com.imooc.o2o.util.PathUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopService shopService;
/**
* @param request 前端传进来的客户端的请求(Http请求头中的所有信息都封装在这个对象中)
* @return
*/
@RequestMapping(value="/registershop",method = RequestMethod.POST)
@ResponseBody//将返回的信息Map键值对自动转换为json
private Map<String,Object> registerShop(HttpServletRequest request) {
Map<String,Object> modelMap = new HashMap<>();
//1.接收并转化相应的参数,包括店铺信息和图片信息
String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
ObjectMapper mapper = new ObjectMapper();
Shop shop = null;
try{
shop = mapper.readValue(shopStr,Shop.class);
} catch (Exception e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
return modelMap;
}
//接收图片文件
CommonsMultipartFile shopImg = null;
CommonsMultipartResolver commonsMultipartResolver
= new CommonsMultipartResolver(request.getSession().getServletContext());
if(commonsMultipartResolver.isMultipart(request)){
MultipartHttpServletRequest multipartHttpServletRequest
= (MultipartHttpServletRequest)request;
shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");
}else{
modelMap.put("success",false);
modelMap.put("errMsg","上传图片不能为空");
return modelMap;
}
//2.注册店铺
if(shop !=null && shopImg !=null){
PersonInfo owner = new PersonInfo();
owner.setUserId(1L);
shop.setOwner(owner);
File shopImgFile = new File(PathUtil.getImgBasePath()+ ImageUtil.getRandomFileName());
try {
shopImgFile.createNewFile();
} catch (IOException e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
return modelMap;
}
try {
inputStreamToFile(shopImg.getInputStream(),shopImgFile);
} catch (IOException e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
return modelMap;
}
ShopExecution se = shopService.addShop(shop,shopImgFile);
if(se.getState() == ShopStateEnum.CHECK.getState()){
modelMap.put("success",true);
modelMap.put("errMsg","注册成功");
}else {
modelMap.put("success",false);
modelMap.put("errMsg",se.getStateInfo());
}
return modelMap;
}else{
modelMap.put("success",false);
modelMap.put("errMsg","请输入店铺信息");
return modelMap;
}
}
private static void inputStreamToFile(InputStream ins, File file){
FileOutputStream os = null;
try{
os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = ins.read())!=-1){
os.write(buffer,0,bytesRead);
}
} catch (Exception e) {
throw new RuntimeException("调用InputStreamToFile产生异常"+e.getMessage());
}finally {
try{
if(os!=null){
os.close();
}
if(ins!=null){
ins.close();
}
} catch (IOException e) {
throw new RuntimeException("inputStreamToFile关闭io产生异常"+e.getMessage());
}
}
}
}
在Controller层,处理图片的环节,接收前端传递过来的图片类型CommonsMultipartFile,而我们之前为了方便Service层的单元测试,addShop接口的定义如下:
ShopExecution addShop(Shop shop, File shopFile);
所以,Controller在调用Servie层的时候,需要将CommonsMultipartFile转换为File,这里我们换个思路,因为CommonsMultipartFile可以获取InputStream,Thumbnailator又可以直接处理输入流,因为InputStream中我们无法得到文件的名称,而thumbnail中需要根据文件名来获取扩展名,所以还要再加一个参数String类型的fileName。
既然第二个和第三个参数都是通过shopImg获取的,为什么不直接传入一个shopImg呢?主要是为了service层单元测测试的方便,因为service层很难实例化出一个CommonsMultipartFile类型的实例
package com.imooc.o2o.web.shopadmin;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.o2o.dto.ShopExecution;
import com.imooc.o2o.entity.PersonInfo;
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.HttpServletRequestUtil;
import com.imooc.o2o.util.ImageUtil;
import com.imooc.o2o.util.PathUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopService shopService;
/**
* @param request 前端传进来的客户端的请求(Http请求头中的所有信息都封装在这个对象中)
* @return
*/
@RequestMapping(value="/registershop",method = RequestMethod.POST)
@ResponseBody//将返回的信息Map键值对自动转换为json
private Map<String,Object> registerShop(HttpServletRequest request)throws ShopOperationException {
Map<String,Object> modelMap = new HashMap<>();
//1.接收并转化相应的参数,包括店铺信息和图片信息
String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
ObjectMapper mapper = new ObjectMapper();
Shop shop = null;
try{
shop = mapper.readValue(shopStr,Shop.class);
} catch (Exception e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
return modelMap;
}
//接收图片文件
CommonsMultipartFile shopImg = null;
CommonsMultipartResolver commonsMultipartResolver
= new CommonsMultipartResolver(request.getSession().getServletContext());
if(commonsMultipartResolver.isMultipart(request)){
MultipartHttpServletRequest multipartHttpServletRequest
= (MultipartHttpServletRequest)request;
shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");
}else{
modelMap.put("success",false);
modelMap.put("errMsg","上传图片不能为空");
return modelMap;
}
//2.注册店铺
if(shop !=null && shopImg !=null){
PersonInfo owner = new PersonInfo();
owner.setUserId(1L);
shop.setOwner(owner);
ShopExecution se = null;
try {
se = shopService.addShop(shop,shopImg.getInputStream(),shopImg.getOriginalFilename());
if(se.getState() == ShopStateEnum.CHECK.getState()){
modelMap.put("success",true);
modelMap.put("errMsg","注册成功");
}else {
modelMap.put("success",false);
modelMap.put("errMsg",se.getStateInfo());
}
} catch (ShopOperationException e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
}catch (IOException e){
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
}
return modelMap;
}else{
modelMap.put("success",false);
modelMap.put("errMsg","请输入店铺信息");
return modelMap;
}
}
}
package com.imooc.o2o.service;
import com.imooc.o2o.dto.ShopExecution;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.exceptions.ShopOperationException;
import java.io.InputStream;
public interface ShopService {
//fileName文件名,InputStream得不到文件名,所以加上第三个参数
ShopExecution addShop(Shop shop, InputStream shopImg,String fileName) throws ShopOperationException;
}
ShopServiceImpl
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.io.InputStream;
import java.util.Date;
@Service
public class ShopServiceImpl implements ShopService {
@Autowired
private ShopDao shopDao;
/**
* @param shop 创建的店铺
* @param shopImgInputStream 用户上传的店铺图片文件
* @return 添加店铺的结果信息
*/
@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获取shop图片目录的相对值路径(带shopId),不带图片的名称xxx.jpg
//如"upload/item/shop/"+ shopId + "/"
String dest = PathUtil.getShopImagePath(shop.getShopId());
//给图片添加水印并将图片存储在绝对值路径中,返回图片的相对值路径
String shopImgAddr = ImageUtil.generateThumbnail(shopImgInputStream,fileName, dest);
shop.setShopImg(shopImgAddr);
}
}
ImageUtil
package com.imooc.o2o.util;
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.io.InputStream;
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 thumbnailInputStream 用户上传的文件
* @param targetAddr 新的文件存储在targetAddr目录中,如"upload/item/shop/"+ shopId + "/"
* @return 返回门面照和小图
*/
public static String generateThumbnail(InputStream thumbnailInputStream,String fileName, String targetAddr) {
//获取文件的随机名称 xxx
String realFileName = getRandomFileName();
//获取用户上传的文件的扩展名称(文件后缀)如.jpg
String extension = getFileExtension(fileName);
//创建图片的存储目录(这个目录包括根目录加上相对目录)
makeDirPath(targetAddr);
//图片的相对目录:如"upload/item/shop/"+ shopId + "/" + xxx + . jpg
String relativeAddr = targetAddr +realFileName + extension;
//图片的绝对目录
File dest = new File(PathUtil.getImgBasePath() + relativeAddr);
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) {
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();
}
}
/**
* 生成随机文件名,当前年月日小时分钟秒+五位随机数
*/
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("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");
}
}
package com.imooc.o2o.service;
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(1L);
area.setAreaId(2);
shopCategory.setShopCategoryId(1L);
shop.setOwner(owner);
shop.setArea(area);
shop.setShopCategory(shopCategory);
shop.setShopName("测试的店铺2");
shop.setShopDesc("test2");
shop.setShopAddr("test2");
shop.setPhone("test2");
shop.setCreateTime(new Date());
shop.setEnableStatus(ShopStateEnum.CHECK.getState());
shop.setAdvice("审核中");
File shopImg = new File("E:/JAVA/JAVA1/javaEE/xiaoyuanshangpu/xiaohuangren.jpg");
InputStream is = new FileInputStream(shopImg);
ShopExecution shopException = shopService.addShop(shop, is,shopImg.getName());
assertEquals(ShopStateEnum.CHECK.getState(),shopException.getState());
}
}