文章目录
Dao层开发
ShopDao接口
com.imooc.o2o.dao.ShopDao.java 新增查询接口
/**
*
*
* @Title: selectShopById
*
* @Description: 根据shopId查询shop
*
* @param shopId
* @return
*
* @return: Shop
*/
Shop selectShopById(long shopId);
ShopDao映射文件
/o2o/src/main/resources/mapper/ShopDao.xml
<resultMap id="shopMap" type="com.artisan.o2o.entity.Shop">
<id column="shop_id" property="shopId"/>
<!-- property对应实体类中的属性名 column 对应库表中的字段名 -->
<result column="shop_name" property="shopName"/>
<result column="shop_desc" property="shopDesc"/>
<result column="shop_addr" property="shopAddr"/>
<result column="phone" property="phone"/>
<result column="shop_img" property="shopImg"/>
<result column="priority" property="priority"/>
<result column="create_time" property="createTime"/>
<result column="last_edit_time" property="lastEditTime"/>
<result column="enable_status" property="enableStatus"/>
<result column="advice" property="advice"/>
<!-- 复合对象 -->
<!-- property对应实体类中的属性名 column 对应库表中的字段名 -->
<association property="owner" column="owner_id" javaType="com.artisan.o2o.entity.PersonInfo">
<id column="user_id" property="userId"/>
<result column="name" property="name"/>
</association>
<association property="area" column="area_id" javaType="com.artisan.o2o.entity.Area">
<id column="area_id" property="areaId"/>
<result column="area_name" property="areaName"/>
</association>
<association property="shopCategory" column="shop_category_id" javaType="com.artisan.o2o.entity.ShopCategory">
<id column="shop_category_id" property="shopCategoryId"/>
<result column="shop_category_name" property="shopCategoryName"/>
</association>
</resultMap>
单元测试
@Test
public void testSelectShopById() {
long shopId=1;
Shop shop=shopDao.queryByShopId(shopId);
System.out.println("areaId:"+shop.getArea().getAreaId());
System.out.println("AreaName:"+shop.getArea().getAreaName());
}
Service层
既然是商铺编辑,肯定要根据入参shopId获取shop信息,然后用户在客户端修改店铺信息后,提交到后台更新商铺信息。
所以同样的对于Service层来讲 有2个方法 (DAO层也有对应的两个方法,只不过updateShop我们复用了)
-
Shop getShopById(long shopId);
-
ShopExecution modifyShop(Shop shop, InputStream shopFileInputStream, String fileName) throws ShopOperationException;
结构
Service层接口及其实现类
com.imooc.o2o.service.ShopService 接口新增两个接口方法如下
/**
*
*
* @Title: getShopById
*
* @Description: 根据shopId查询商铺
*
* @param shopId
* @return
*
* @return: Shop
*/
Shop getShopById(long shopId);
/**
*
*
* @Title: modifyShop
*
* @Description: 编辑商铺信息
*
* @param shop
* @param shopFileInputStream
* @param fileName
* @return
*
* @return: ShopExecution
*/
ShopExecution modifyShop(Shop shop, InputStream shopFileInputStream, String fileName) throws ShopOperationException;
com.imooc.o2o.service.impl.ShopServiceImpl.java实现类
@Override
public Shop getShopById(long shopId) {
return shopDao.selectShopById(shopId);
}
@Override
@Transactional
public ShopExecution modifyShop(Shop shop, InputStream shopFileInputStream, String fileName) throws ShopOperationException {
if (shop == null || shop.getShopId() == null) {
return new ShopExecution(ShopStateEnum.NULL_SHOP_INFO);
}else{
try {
// 1. 判断是否需要处理图片
if (shopFileInputStream != null && fileName != null && !"".equals(fileName)) {
// 1.1 删除掉旧的图片
// 查询入参shop对应数据库表中的shopImg路径
Shop tempShop = shopDao.selectShopById(shop.getShopId());
if (tempShop != null) {
// 删除就的缩略图
ImageUtil.deleteStorePath(tempShop.getShopImg());
}
// 1.2 用新的图片生成缩略图
addShopImg(shop, shopFileInputStream, fileName);
}
// 2. 更新店铺信息
// 2.1 更新一些必要属性
shop.setLastEditTime(new Date());
// 2.2 更新店铺
int effectedNum = shopDao.updateShop(shop);
if (effectedNum <= 0) {
throw new ShopOperationException(ShopStateEnum.INNER_ERROR.getStateInfo());
}
return new ShopExecution(ShopStateEnum.SUCCESS, shop);
} catch (Exception e) {
e.printStackTrace();
throw new ShopOperationException("modify shop error:" + e.getMessage());
}
}
}
因为用户有可能更新图片,其中为了删除旧的文件或者目录,com.imooc.o2o.util.ImageUtil.java 新增了工具类
/**
*
*
* @Title: deleteStorePath
*
* @Description: 判断storePath是否为目录,为目录的话删掉目录下的所有文件,否则删掉文件
*
* @param storePath
*
* @return: void
*/
public static void deleteStorePath(String storePath) {
File fileOrMenu = new File(FileUtil.getImgBasePath() + storePath);
if (fileOrMenu != null) {
if (fileOrMenu.isDirectory()) {
File[] files = fileOrMenu.listFiles();
for (int i = 0; i < files.length; i++) {
files[i].delete();
}
}
fileOrMenu.delete();
}
}
单元测试
@Test
public void testModifyShop() {
Shop shop = new Shop();
Area area = new Area();
ShopCategory shopCategory = new ShopCategory();
shop.setShopId(28L);
area.setAreaId(2);
shopCategory.setShopCategoryId(2L);
shop.setArea(area);
shop.setShopCategory(shopCategory);
shop.setShopName("Modify咖啡店");
shop.setShopDesc("Modify小工匠的咖啡店");
shop.setShopAddr("Modify-NanJing");
shop.setPhone("123456");
shop.setPriority(78);
File shopFile = new File("D:/o2o/artisan.jpg");
ShopExecution se = null;
InputStream ins = null;
try {
ins = new FileInputStream(shopFile);
se = shopService.modifyShop(shop, ins, shopFile.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Assert.assertEquals(ShopStateEnum.SUCCESS.getState(), se.getState());
}
Controller层
按照需求设计,我们希望商铺管理者
-
店铺名称不能修改
-
店铺类别不能修改
-
其余信息可编辑修改
分为两步,
- 第一步前端传入shopId到后台获取商铺信息,前端展示
- 第二步修改商铺信息,提交到后台,更新商铺
ShopController
com.imooc.o2o.web.shopadmin.ShopController.java
ShopController#getShopInfoById
/**
*
*
* @Title: getShopInfoById
*
* @Description: 根据shopId获取shop信息, 接收前端的请求,获取shopId ,所以入参为HttpServletRequest
* @ResponseBody 不需要VIEW展现层模块,直接显示到客户端的内容。 将内容或对象作为 HTTP 响应正文返回
*
* @param request
*
* @return: Map<String,Object>
*/
@RequestMapping(value = "/getshopinfobyId", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> getShopInfoById(HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
// shopId 为和前端约定好的变量
int shopId = HttPServletRequestUtil.getInt(request, "shopId");
try {
if (shopId >= 0) {
// 查询 ,按照设计,我们希望前端页面下拉列表中可以修改区域信息,所以需要查询出来全量的区域列表
// 对已ShopCategory而言,我们DAO层的SQL已经将shop_category_id和
// shop_category_name 查询出来,前端设置到对应的属性上即可。没有必要全部查询出来。
Shop shop = shopService.getShopById(shopId);
List<Area> areaList = areaservice.getAreaList();
modelMap.put("success", true);
modelMap.put("shop", shop);
modelMap.put("areaList", areaList);
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "shopId不合法");
}
} catch (Exception e) {
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
}
return modelMap;
}
测试
启动tomcat,访问 http://localhost:8080/o2o/shopadmin/getshopinfobyId?shopId=1
返回的数据如下:
检查数据,符合预期。
ShopController#modifyShop方法
/**
*
*
* @Title: modifyshop
*
* @Description:
*
* @param request
* 因为是接收前端的请求,而前端的信息都封装在HttpServletRequest中,
* 所以需要解析HttpServletRequest,获取必要的参数
*
* 1. 接收并转换相应的参数,包括shop信息和图片信息 2.修改店铺 3. 返回结果给前台
* @return
*
* @return: Map<String,Object>
*/
@RequestMapping(value = "/modifyshop", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> modifyshop(HttpServletRequest request) {
Map<String, Object> modelMap = new HashMap<String, Object>();
// 0. 验证码校验
if (!VerifyCodeUtil.verifyCode(request)) {
modelMap.put("success", false);
modelMap.put("errMsg", "验证码不正确");
return modelMap;
}
// 1. 接收并转换相应的参数,包括shop信息和图片信息
// 1.1 shop信息
// shopStr 是和前端约定好的参数值,后端从request中获取request这个值来获取shop的信息
String shopStr = HttPServletRequestUtil.getString(request, "shopStr");
// 使用jackson-databind 将json转换为pojo
ObjectMapper mapper = new ObjectMapper();
Shop shop = null;
try {
// 将json转换为pojo
shop = mapper.readValue(shopStr, Shop.class);
} catch (Exception e) {
e.printStackTrace();
// 将错误信息返回给前台
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
return modelMap;
}
// 1.2 图片信息 基于Apache Commons FileUpload的文件上传 ( 修改商铺信息 图片可以不更新)
// Spring MVC中的 图片存在CommonsMultipartFile中
CommonsMultipartFile shopImg = null;
// 从request的本次会话中的上线文中获取图片的相关内容
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
if (commonsMultipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// shopImg是和前端约定好的变量名
shopImg = (CommonsMultipartFile) multipartRequest.getFile("shopImg");
}
// 2. 修改店铺
if (shop != null && shop.getShopId() != null) {
// Session 部分的 PersonInfo 修改商铺是不需要的设置的。
// 修改店铺
ShopExecution se = null;
try {
if (shopImg != null) {
se = shopService.modifyShop(shop, shopImg.getInputStream(), shopImg.getOriginalFilename());
} else {
se = shopService.modifyShop(shop, null, null);
}
// 成功
if (se.getState() == ShopStateEnum.SUCCESS.getState()) {
modelMap.put("success", true);
modelMap.put("errMsg", "修改成功");
} else {
modelMap.put("success", false);
modelMap.put("errMsg", se.getStateInfo());
}
} catch (Exception e) {
e.printStackTrace();
modelMap.put("success", false);
modelMap.put("errMsg", "ModifyShop Error");
}
} else {
// 将错误信息返回给前台
modelMap.put("success", false);
modelMap.put("errMsg", "ShopId不合法");
}
return modelMap;
}
Controller层的单元测试,待我们完成前端页面一起联调。
注册商铺的session部分的完善
同时 完善下 注册商铺的session部分,之前是写死的person ,现在需要从session中获取, 具体看注释部分。
// 2. 注册店铺
if (shop != null && shopImg != null) {
// Session
// 店主persionInfo的信息,肯定要登录才能注册店铺。
// 所以这部分信息我们从session中获取,尽量不依赖前端,这里暂时时不具备条件,后续改造,先硬编码,方便单元测试
// PersonInfo personInfo = new PersonInfo();
// personInfo.setUserId(1L);
// 注册店铺之前登录,登录成功后,约定好将user这个key 设置到session中,
// 这里通过key就可以取到PersonInfo的信息
PersonInfo personInfo = (PersonInfo) request.getSession().getAttribute("user");
shop.setOwner(personInfo);