Dao層新增店鋪
src/main/java/com.imooc.o2o.dao 目錄下新建 ShopDao.java接口。
package com.imooc.o2o.dao;
import com.imooc.o2o.entity.Shop;
public interface ShopDao {
/**
* 新增店鋪
* @param shop
* @return
*/
int insertShop(Shop shop);
}
src/main/resources/mapper路徑下創建ShopDao.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.o2o.dao.ShopDao">
<insert id="insertShop" useGeneratedKeys="true" keyColumn="shop_id"
keyProperty="shopId">
INSERT INTO
tb_shop(owner_id,area_id,shop_category_id,shop_name,shop_desc,shop_addr,
phone,shop_img,priority,create_time,last_edit_time,enable_status,advice)
VALUSE
(#{owner.userId},#{area.areaId},#{shopCategory.shopCategoryId},#{shopName},
#{shopDesc},#{shopAddr},#{phone},#{shopImg},#{priority},#{createTime},
#{lastEditTime},#{enableStatus},#{advice})
</insert>
</mapper>
數據庫添加測試數據
insert into `o2o`.`tb_shop_category` ( `shop_category_name`, `shop_category_desc`, `shop_category_img`, `priority`) values ( '咖啡奶茶', '咖啡奶茶', 'test', '1')
insert into `o2o`.`tb_person_info` ( `name`, `profile_img`, `email`, `gender`, `enable_status`, `user_type`) values ( '測試', 'test', 'test', '1', '1', '2')
com.imooc.o2o.dao目錄下創建ShopDaoTest.java進行單元測試
package com.imooc.o2o.dao;
import static org.junit.Assert.assertEquals;
import java.util.Date;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.imooc.o2o.BaseTest;
import com.imooc.o2o.entity.Area;
import com.imooc.o2o.entity.PersonInfo;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.entity.ShopCategory;
public class ShopDaoTest extends BaseTest{
@Autowired
private ShopDao shopDao;
@Test
public void testInsertShop() {
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("測試的店鋪");
shop.setShopDesc("test");
shop.setShopAddr("test");
shop.setPhone("test");
shop.setShopImg("test");
shop.setCreateTime(new Date());
shop.setEnableStatus(1);
shop.setAdvice("審覈中");
int effectedNum = shopDao.insertShop(shop);
assertEquals(1, effectedNum);
}
}
Dao層之更新店鋪
src/main/java/com.imooc.o2o.dao目錄下ShopDao.java新增代碼
/**
* 更新店鋪信息
*/
int updateShop(Shop shop);
src/main/resources/mapper目錄下ShopDao.xml新增代碼
<update id="updateShop" parameterType="com.imooc.o2o.entity.Shop">
update tb_shop
<set>
<if test="shopName != null">shop_name=#{shopName},</if>
<if test="shopDesc != null">shop_desc=#{shopDesc},</if>
<if test="shopAddr != null">shop_addr=#{shopAddr},</if>
<if test="phone != null">phone=#{phone},</if>
<if test="shopImg != null">shop_img=#{shopImg},</if>
<if test="priority != null">priority=#{priority},</if>
<if test="lastEditTime != null">last_edit_time=#{lastEditTime},</if>
<if test="enableStatus != null">enable_status=#{enableStatus},</if>
<if test="advice != null">advice=#{advice},</if>
<if test="area != null">area_id=#{area.areaId},</if>
<if test="shopCategory != null">shop_category_id=#{shopCategory.shopCategoryId}</if>
</set>
where shop_id=#{shopId}
</update>
src/test/java/com.imooc.o2o.dao目錄下ShopDaoTest.java添加代碼
@Test
public void testUpdateShop() {
Shop shop = new Shop();
shop.setShopId(1L);
shop.setShopDesc("測試描述");
shop.setShopAddr("測試地址");
int effectedNum = shopDao.updateShop(shop);
assertEquals(1, effectedNum);
}
testInsertShop方法上面添加@Ignore標籤,JUnit則不會觸發testInsertShop方法了。
Run As執行測試。沒發現錯誤就ok了。
Thumbnailator圖片處理和封裝Util
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
在src/main/java/com.imooc.o2o.util路徑下新建ImageUtil.java類
在src/main/resources路徑下放置一張圖片
在/Users/mac/Downloads/luoto.png 存入另外一張圖片。爲此圖片添加上面圖片的水印。
package com.imooc.o2o.util;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
public class ImageUtil {
public static void main(String[] args) throws IOException {
String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
Thumbnails.of(new File("/Users/mac/Downloads/luoto.png")).size(200, 200)
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath + "/jingyu.png")), 0.25f)
.outputQuality(0.8f).toFile("/Users/mac/Downloads/luotonew.png");
}
}
運行main函數,我們發現在/Users/mac/Downloads路徑下多出一張luotonew.png的水印圖片。
src/main/java/com.imooc.o2o.util路徑下創建PathUtil.java類
package com.imooc.o2o.util;
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 = "D:/projectdev/image/"; //根據自己的實際路徑進行設置
}else {
basePath = "/home/o2o/image/";//根據自己的實際路徑進行設置
}
basePath = basePath.replace("/", seperator);
return basePath;
}
//根據不同的業務需求返回不同的子路徑
public static String getShopImagePath(long shopId) {
String imagePath = "/upkoad/item/shop/"+ shopId + "/";
return imagePath.replace("/", seperator);
}
}
修改ImageUtil.java類
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.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class ImageUtil {
private static String basePath = Thread.currentThread()
.getContextClassLoader().getResource("").getPath();
private static final SimpleDateFormat sDateFormat =
new SimpleDateFormat("yyyyMMddHHmmss");
private static final Random r = new Random();
/**
* 處理縮略圖,並返回新生成圖片的相對值路徑
*/
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.png")), 0.25f)
.outputQuality(0.8f).toFile(dest);
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
//返回圖片存儲路徑
return relativeAddr;
}
/**
* 創建目標路徑所涉及到的目錄,即/home/work/o2o/xxx.jpg,
* 那麼 home work o2o 這三個文件夾都得自動創建
*
* @param targetAddr
*/
private static void makeDirPath(String targetAddr) {
// TODO Auto-generated method stub
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;
}
/**
* 獲取輸入文件流的擴展名
*/
private static String getFileExtension(File thumbnail) {
String originalFileName = thumbnail.getName();
return originalFileName.substring(originalFileName.lastIndexOf("."));
}
public static void main(String[] args) throws IOException {
Thumbnails.of(new File("/Users/mac/Downloads/luoto.png")).size(200, 200)
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath + "/jingyu.png")), 0.25f)
.outputQuality(0.8f).toFile("/Users/mac/Downloads/luotonew.png");
}
}
Dto之ShopExecution的實現
src/main/java/com.imooc.o2o.dto路徑下創建ShopExecution.java類
package com.imooc.o2o.dto;
import java.util.List;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.enums.ShopStateEnum;
public class ShopExecution {
// 結果狀態
private int state;
// 狀態標識
private String stateInfo;
// 店鋪數量
private int count;
// 操作的shop(增刪改店鋪的時候用到)
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 void setState(int state) {
this.state = state;
}
public String getStateInfo() {
return stateInfo;
}
public void setStateInfo(String stateInfo) {
this.stateInfo = stateInfo;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Shop getShop() {
return shop;
}
public void setShop(Shop shop) {
this.shop = shop;
}
public List<Shop> getShopList() {
return shopList;
}
public void setShopList(List<Shop> shopList) {
this.shopList = shopList;
}
}
創建枚舉類型文件
package com.imooc.o2o.enums;
public enum ShopStateEnum {
CHECK(0, "審覈中"), OFFLINE(-1, "非法店鋪"), SUCCESS(1, "操作成功"), PASS(2, "通過認證"), INNER_ERROR(-1001, "內部系統錯誤"),
NULL_SHOPID(-1002,"ShopId爲空"),
ULL_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;
}
}
店鋪註冊之Service層的實現
Service層需要事務的管理
創建com.imooc.o2o.exceptions包,ShopOperationException.java類文件
package com.imooc.o2o.exceptions;
public class ShopOperationException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 2361446884822298905L;
public ShopOperationException(String msg) {
super(msg);
}
}
ShopServiceImpl.java
@Service
public class ShopServiceImpl implements ShopService{
@Autowired
private ShopDao shopDao;
@Override
@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 {
addShopImg(shop, shopImg);
}catch (Exception e) {
// TODO: handle exception
throw new ShopOperationException("addShopImg error"+e.getMessage());
}
//更新店鋪的圖片地址
effectedNum = shopDao.updateShop(shop);
if(effectedNum <=0) {
throw new ShopOperationException("更新圖片地址失敗");
}
}
}
}catch (Exception e) {
// TODO: handle exception
throw new ShopOperationException("addShop error:"+e.getMessage());
}
return new ShopExecution(ShopStateEnum.CHECK,shop);
}
private void addShopImg(Shop shop, File shopImg) {
// 獲取shop圖片目錄的相對值路徑
String dest = PathUtil.getShopImagePath(shop.getShopId());
String shopImgAddr = ImageUtil.generateThumbnail(shopImg,dest);
shop.setShopImg(shopImgAddr);
}
}
src/test/java/com.imooc.o2o.service目錄下創建ShopServiceTest.java文件
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("/Users/mac/Downloads/luoto.png");
ShopExecution se = shopService.addShop(shop, shopImg);
assertEquals(ShopStateEnum.CHECK.getState(), se.getState());
}
}
Controller層的實現
util/HttpServletRequestUtil
public class HttpServletRequestUtil {
public static int getInt(HttpServletRequest request,String name){
try {
/*decode適合用來分析數字
8進:010=>分析後爲 8 10進:10=>分析後爲 10 16進:#10|0X10|0x10=>分析後是 16
而valueof 只能分析純數字的String
像 010 這樣的8進制 他會解析成 =>10
parseInt(s,int radix)
若想獲得Integer:
String 爲十進制. 採用valueof(String)合適. 非十進制,採用decode(String)
想要獲得int
String 爲十進制. 採用parseInt(String )合適. 非十進制,採用parseInt(String ,int)
*/
return Integer.decode(request.getParameter(name));
} catch (NumberFormatException e) {
return -1;
}
}
public static long getLong(HttpServletRequest request, String name){
try {
return Long.valueOf(request.getParameter(name));
} catch (NumberFormatException e) {
return -1;
}
}
public static Double getDouble(HttpServletRequest request,String name){
try {
return Double.valueOf(request.getParameter(name));
} catch (NumberFormatException e) {
return -1d;
}
}
public static Boolean getBoolean(HttpServletRequest request,String name){
try {
return Boolean.valueOf(request.getParameter(name));
} catch (Exception e) {
return false;
}
}
public static String getString(HttpServletRequest request,String name){
try {
String result = request.getParameter(name);
if (result!=null){
result =result.trim();
}
if ("".equals(result)){
result =null;
}
return result;
} catch (Exception e) {
return null;
}
}
}
ShopManagementController.java
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopService shopService;
@RequestMapping(value = "/registershop", method = RequestMethod.POST)
@ResponseBody
private Map<String, Object> listShop(HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
//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());
}
//接受圖片信息
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());
e.printStackTrace();
}
try {
inputStreamToFile(shopImg.getInputStream(),shopImgFile);
} catch (IOException e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
e.printStackTrace();
}
ShopExecution se = shopService.addShop(shop,shopImgFile);
if(se.getState()== ShopStateEnum.CHECK.getState()){
modelMap.put("success",true);
}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(buffer))!=-1){
os.write(buffer,0,bytesRead);
}
} catch (IOException 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層的改造
ShopManagementController
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopService shopService;
@RequestMapping(value = "/registershop", method = RequestMethod.POST)
@ResponseBody
private Map<String, Object> listShop(HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
//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());
}
//接受圖片信息
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();
//Session TODO
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);
}else {
modelMap.put("success",false);
modelMap.put("errMsg",se.getStateInfo());
}
} catch (IOException e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
e.printStackTrace();
}
return modelMap;
}else {
modelMap.put("success",false);
modelMap.put("errMsg","請輸入店鋪信息");
return modelMap;
}
}
}
更改shopService
public interface ShopService {
public ShopExecution addShop(Shop shop, InputStream shopImgInputStream,
String fieName);
}
更改shopServiceImpl
@Service
public class ShopServiceImpl implements ShopService {
@Autowired
private ShopDao shopDao;
@Transactional //需要事務支持
public ShopExecution addShop(Shop shop, InputStream shopImgInputStream,
String fileName){
//空值判斷
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 {
addShopImg(shop, shopImgInputStream,fileName);
}catch (Exception e) {
// TODO: handle exception
throw new ShopOperationException("addShopImg error"+e.getMessage());
}
//更新店鋪的圖片地址
effectedNum = shopDao.updateShop(shop);
if(effectedNum <=0) {
throw new ShopOperationException("更新圖片地址失敗");
}
}
}
}catch (Exception e) {
// TODO: handle exception
throw new ShopOperationException("addShop error:"+e.getMessage());
}
return new ShopExecution(ShopStateEnum.CHECK,shop);
}
private void addShopImg(Shop shop, InputStream shopImgInputStream,
String fileName) {
// 獲取shop圖片目錄的相對值路徑
String dest = PathUtil.getShopImagePath(shop.getShopId());
String shopImgAddr = ImageUtil.generateThumbnail(shopImgInputStream,
fileName,dest);
shop.setShopImg(shopImgAddr);
}
}
更改ImageUtil.java
public class ImageUtil {
private static String basePath = Thread.currentThread()
.getContextClassLoader().getResource("").getPath();
private static final SimpleDateFormat sDateFormat =
new SimpleDateFormat("yyyyMMddHHmmss");
private static final Random r = new Random();
/**
* 處理縮略圖,並返回新生成圖片的相對值路徑
*/
public static String generateThumbnail(InputStream thumbnailInputStream,
String fileName,
String targetAddr) {
//隨機文件名,當前年月日小時分鐘秒+五位隨機數
String realFileName = getRandomFileName();
//文件的擴展名
String extension = getFileExtension(fileName);
//創建目標路徑所涉及到的目錄
makeDirPath(targetAddr);
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 + "cat.jpg")),
0.25f)
.outputQuality(0.8f).toFile(dest);
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
//返回圖片存儲路徑
return relativeAddr;
}
/**
* 創建目標路徑所涉及到的目錄,即/home/work/o2o/xxx.jpg,
* 那麼 home work o2o 這三個文件夾都得自動創建
*
* @param targetAddr
*/
private static void makeDirPath(String targetAddr) {
// TODO Auto-generated method stub
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;
}
/**
* 獲取輸入文件流的擴展名
*/
private static String getFileExtension(String fileName) {
return fileName.substring(fileName.lastIndexOf("."));
}
}
前端設計
使用SUI Mobile
使用模板改造shopoperation.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>商店信息</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">
<link rel="stylesheet"
href="//g.alicdn.com/msui/sm/0.6.2/css/sm-extend.min.css">
</head>
<body>
<header class="bar bar-nav">
<h1 class="title">商店信息</h1>
</header>
<div class="content">
<div class="list-block">
<ul>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-name"></i>
</div>
<div class="item-inner">
<div class="item-title label">商鋪名稱</div>
<div class="item-input">
<input type="text" id="shop-name"
placeholder="商鋪名稱">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">商鋪分類</div>
<div class="item-input">
<select id="shop-category">
</select>
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">所屬區域</div>
<div class="item-input">
<select id="area">
</select>
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">詳細地址</div>
<div class="item-input">
<input type="text" id="shop-addr"
placeholder="詳細地址">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">聯繫電話</div>
<div class="item-input">
<input type="tel" id="shop-phone"
placeholder="聯繫電話">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">縮略圖</div>
<div class="item-input">
<input type="file" id="shop-img" placeholder="聯繫電話">
</div>
</div>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<div class="item-title label">店鋪簡介</div>
<div class="item-input">
<textarea placeholder="店鋪簡介"
id="shop-desc"></textarea>
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="content-block">
<div class="row">
<div class="col-50">
<a href="/myo2o/shop/shopmanage"
class="button button-big button-fill button-danger">返回</a>
</div>
<div class="col-50">
<a href="#" class="button button-big button-fill"
id="submit">提交</a>
</div>
</div>
</div>
</div>
<script type='text/javascript'
src='//g.alicdn.com/sj/lib/zepto/zepto.js' charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js'
charset='utf-8'></script>
<script type='text/javascript'
src='//g.alicdn.com/msui/sm/0.6.2/js/sm-extend.min.js'
charset='utf-8'></script>
<script type="text/javascript"
src="../resources/js/shop/shopoperation.js"></script>
</body>
</html>
店鋪註冊之js實現
resources/js/shop/shopoperation.js
$(function () {
var initUrl='/o2o/shopadmin/getshopinitinfo';
//註冊店鋪
var regidterShopUrl ='/o2o/shopadmin/registershop';
alert(initUrl);
//調用getShopInitInfo
getShopInitInfo();
function getShopInitInfo() {
$.getJSON(initUrl,function (data) {
if(date.success){
var tempHtml="";
//獲取區域信息
var tempAreaHtml="";
//後臺獲取的店鋪分類列表,遍歷
data.shopCategoryList.map(function (item,index) {
tempHtml+='<option data-id="'+item.shopCategoryId+'">'+item.shopCategoryName+'</option>'
});
//區域信息
data.areaList.map(function (item,index) {
tempAreaHtml+='<option data-id="'+item.areaId+'">'+item.areaName+'</option>';
});
$('#shop-category').html(tempHtml);
$('#area').html(tempAreaHtml);
}
});
//點擊提交後的響應
$('#submit').click(function () {
var shop ={};
//從控件中獲取信息
shop.shopName=$('#shop-name').val();
shop.shopAddr=$('#shop-addr').val();
shop.phone=$('#shop-phone').val();
shop.shopDesc=$('#shop-desc').val();
//獲取列表中的數據
shop.shopCategory={
shopCategoryId:$('#shop-category').find('option').not(function(){
return !this.selected;
}).data('id')
};
shop.area = {
areaId:$('#area').find('option').not(function () {
return !this.selected;
}).data('id')
};
var shopImg =$('#shop-img')[0].files[0];
var formData = new FormData();
formData.append('shopImg',shopImg);
formData.append('shopStr',JSON.stringify(shop));
$.ajax({
url:regidterShopUrl,
type:'POST',
data:formData,
contentType:false,
proceesData:false,
cache:false,
success:function (data) {
if(data.success){
$.toast('提交成功');
}else{
$.toast('提交失敗'+data.errMsg);
}
}
});
});
}
})
店鋪類別區域信息的獲取
shopCategoryDao
public interface ShopCategoryDao {
List<ShopCategory> queryShopCategory(@Param("shopCategoryCondition") ShopCategory shopCategoryCondition);
}
shopCategoryDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.o2o.dao.ShopCategoryDao">
<select id="queryShopCategory"
resultType="com.imooc.o2o.entity.ShopCategory">
select
shop_category_id,
shop_category_name,
shop_category_desc,
shop_category_img,
priority,
create_time,
last_edit_time,
parent_id
FROM
tb_shop_category
<where>
<if test="shopCategoryCondition!=null">
and parent_id is not null
</if>
<if test="shopCategoryCondition.parent!=null">
and parent_id = #{shopCategoryCondition.parent.shopCategoryId}
</if>
</where>
order by
priority desc
</select>
</mapper>
測試
package com.imooc.o2o.dao;
import com.imooc.o2o.BaseTest;
import com.imooc.o2o.entity.ShopCategory;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import static org.junit.Assert.*;
public class ShopCategoryDaoTest extends BaseTest {
@Autowired
private ShopCategoryDao shopCategoryDao;
@Test
public void queryShopCategory() {
List<ShopCategory> shopCategoryList=
shopCategoryDao.queryShopCategory(new ShopCategory());
assertEquals(2,shopCategoryList.size());
ShopCategory testCategory = new ShopCategory();
ShopCategory parentCategory = new ShopCategory();
parentCategory.setShopCategoryId(1L);
testCategory.setParent(parentCategory);
shopCategoryList = shopCategoryDao.queryShopCategory(testCategory);
assertEquals(1,shopCategoryList.size());
System.out.println(shopCategoryList.get(0).getShopCategoryName());
}
}
ShopCategoryService
package com.imooc.o2o.service;
import com.imooc.o2o.entity.ShopCategory;
import java.io.IOException;
import java.util.List;
public interface ShopCategoryService {
List<ShopCategory> getShopCategoryList(ShopCategory shopCategoryCondition) throws IOException;
}
ShopCategoryServiceImpl
package com.imooc.o2o.service.impl;
import com.imooc.o2o.dao.ShopCategoryDao;
import com.imooc.o2o.entity.ShopCategory;
import com.imooc.o2o.service.ShopCategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
@Service
public class ShopCategoryServiceImpl implements ShopCategoryService {
@Autowired
private ShopCategoryDao shopCategoryDao;
@Override
public List<ShopCategory> getShopCategoryList(ShopCategory shopCategoryCondition) throws IOException {
return shopCategoryDao.queryShopCategory(shopCategoryCondition);
}
}
在ShopManagementController中加入getShopInitInfo()
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopService shopService;
@Autowired
private ShopCategoryService shopCategoryService;
@Autowired
private AreaService areaService;
@RequestMapping(value = "/getshopinitinfo",method = RequestMethod.GET)
@ResponseBody
private Map<String,Object> getShopInitInfo(){
Map<String,Object> modelMap = new HashMap<String,Object>();
List<ShopCategory> shopCategoryList = new ArrayList<ShopCategory>();
List<Area> areaList = new ArrayList<Area>();
try{
shopCategoryList=
shopCategoryService.getShopCategoryList(new ShopCategory());
areaList=areaService.getAreaList();
modelMap.put("shopCategoryList",shopCategoryList);
modelMap.put("areaList",areaList);
modelMap.put("success",true);
} catch (IOException e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
}
return modelMap;
}
...
}
運行
引入kaptcha實現驗證碼
在pom中加入
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
在web.xml中加入
<servlet>
<!-- 生成圖片的Servlet -->
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<!-- 是否有邊框 -->
<init-param>
<param-name>kaptcha.border</param-name>
<param-value>no</param-value>
</init-param>
<!-- 字體顏色 -->
<init-param>
<param-name>kaptcha.textproducer.font.color</param-name>
<param-value>red</param-value>
</init-param>
<!-- 圖片寬度 -->
<init-param>
<param-name>kaptcha.image.width</param-name>
<param-value>135</param-value>
</init-param>
<!-- 使用哪些字符生成驗證碼 -->
<init-param>
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>ACDEFHKPRSTWX345679</param-value>
</init-param>
<!-- 圖片高度 -->
<init-param>
<param-name>kaptcha.image.height</param-name>
<param-value>50</param-value>
</init-param>
<!-- 字體大小 -->
<init-param>
<param-name>kaptcha.textproducer.font.size</param-name>
<param-value>43</param-value>
</init-param>
<!-- 干擾線的顏色 -->
<init-param>
<param-name>kaptcha.noise.color</param-name>
<param-value>black</param-value>
</init-param>
<!-- 字符個數 -->
<init-param>
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>4</param-value>
</init-param>
<!-- 使用哪些字體 -->
<init-param>
<param-name>kaptcha.textproducer.font.names</param-name>
<param-value>Arial</param-value>
</init-param>
</servlet>
<!-- 映射的url -->
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/Kaptcha</url-pattern>
</servlet-mapping>
引入驗證碼到html
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-form-email"></i>
</div>
<div class="item-inner">
<label for="j_captcha" class="item-title label">驗證碼</label> <input
id="j_captcha" name="j_captcha" type="text"
class="form-control in" placeholder="驗證碼" />
<div class="item-input">
<img id="captcha_img" alt="點擊更換" title="點擊更換"
οnclick="changeVerifyCode(this)" src="../Kaptcha" />
</div>
</div>
</div>
</li>
實現changeVerifyCode
在resources/js/common中創建commonutil.js
function changeVerifyCode(img) {
img.src="../Kaptcha?"+Math.floor(Math.random()*100);
}
並在HTML引入
<script type='text/javascript'
src='../resources/js/common/commonutil.js' charset='utf-8'></script>
shopoperation.js
$(function () {
var initUrl='/shopadmin/getshopinitinfo';
//註冊店鋪
var regidterShopUrl ='/shopadmin/registershop';
//調用getShopInitInfo
getShopInitInfo();
function getShopInitInfo() {
$.getJSON(initUrl,function (data) {
if(data.success){
var tempHtml="";
//獲取區域信息
var tempAreaHtml="";
//後臺獲取的店鋪分類列表,遍歷
data.shopCategoryList.map(function (item,index) {
tempHtml+='<option data-id="'+item.shopCategoryId+'">'+item.shopCategoryName+'</option>'
});
//區域信息
data.areaList.map(function (item,index) {
tempAreaHtml+='<option data-id="'+item.areaId+'">'+item.areaName+'</option>';
});
$('#shop-category').html(tempHtml);
$('#area').html(tempAreaHtml);
}
});
//點擊提交後的響應
$('#submit').click(function () {
var shop ={};
//從控件中獲取信息
shop.shopName=$('#shop-name').val();
shop.shopAddr=$('#shop-addr').val();
shop.phone=$('#shop-phone').val();
shop.shopDesc=$('#shop-desc').val();
//獲取列表中的數據
shop.shopCategory={
shopCategoryId:$('#shop-category').find('option').not(function(){
return !this.selected;
}).data('id')
};
shop.area = {
areaId:$('#area').find('option').not(function () {
return !this.selected;
}).data('id')
};
var shopImg =$('#shop-img')[0].files[0];
var formData = new FormData();
formData.append('shopImg',shopImg);
formData.append('shopStr',JSON.stringify(shop));
var verifyCodeActual=$('#j_captcha').val();
if(!verifyCodeActual){
$.toast('請輸入驗證碼!');
return;
}
formData.append('verifyCodeActual',verifyCodeActual);
$.ajax({
url:regidterShopUrl,
type:'POST',
data:formData,
contentType:false,
proceesData:false,
cache:false,
success:function (data) {
if(data.success){
$.toast('提交成功');
}else{
$.toast('提交失敗'+data.errMsg);
}
$('#captcha_img').click();
}
});
});
}
})
在util中創建CodeUtil.java
package com.imooc.o2o.util;
import com.google.code.kaptcha.Constants;
import javax.servlet.http.HttpServletRequest;
public class CodeUtil {
public static boolean checkVerifyCode(HttpServletRequest request){
String verifyCodeExpected =
(String)request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
String verifyCodeActual= HttpServletRequestUtil.getString(request,
"verifyCodeActual");
if(verifyCodeActual==null||!verifyCodeActual.equals(verifyCodeExpected)){
return false;
}
return true;
}
}
shopManagementController.java中驗證驗證碼
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopService shopService;
@RequestMapping(value = "/registershop", method = RequestMethod.POST)
@ResponseBody
private Map<String, Object> listShop(HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
//驗證碼
if(!CodeUtil.checkVerifyCode(request)){
modelMap.put("success",false);
modelMap.put("errMsg","輸入了錯誤的驗證碼");
return modelMap;
}
//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());
}
//接受圖片信息
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();
//Session TODO
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);
}else {
modelMap.put("success",false);
modelMap.put("errMsg",se.getStateInfo());
}
} catch (IOException e) {
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
e.printStackTrace();
}
return modelMap;
}else {
modelMap.put("success",false);
modelMap.put("errMsg","請輸入店鋪信息");
return modelMap;
}
}
}
前後端聯調驗證整體模塊功能
按F10一步一步調試
spring-web.xml加入
<!-- 文件上傳解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<!--1024x1024x20 20M-->
<property name="maxUploadSize" value="10485760000"></property><!-- 最大上傳文件大小 -->
<property name="maxInMemorySize" value="10960"></property>
</bean>
pom.xml
引入文件上傳的jar包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>