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>