文章目录
-
- 1. 店铺信息编辑之Dao层实现
-
- 1. ShopDao接口
- 2. ShopDao.xml实现类
- 3. ShopDaoTest
- 2. 店铺信息编辑之Service层的实现
-
- 1. ShopService接口
- 2. ShopServiceImpl实现类
- 3. ShopServiceTest测试类
- 3. 店铺信息编辑之Controller层的实现
- 4. 店铺信息编辑之View层实现
- 5. 前后端联调测试
1. 店铺信息编辑之Dao层实现
店铺信息的编辑主要包括:更新店铺信息和展示店铺信息
在dao层中更新店铺信息前面已完成,因此在dao层中主要完成店铺信息的获取
在Shop实体类中有三个pojo对象,
表现为在数据库中tb_shop表通过三个外键与三张表相关联:
1. ShopDao接口
在ShopDao接口中增加根据shopId查询店铺信息方法:
/**
* 查询店铺信息
* @param shopId
* @return Shop
*/
Shop queryByShopId(long shopId);
2. ShopDao.xml实现类
在ShopDao.xml文件中增加:
<resultMap id="shopMap" type="com.imooc.o2o.entity.Shop">
<id column="shop_id" property="shopId"/>
<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"/>
<association property="area" column="area_id" javaType="com.imooc.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.imooc.o2o.entity.ShopCategory">
<id column="shop_category_id" property="shopCategoryId"/>
<result column="shop_category_name" property="shopCategoryName"/>
</association>
<association property="owner" column="owner_id" javaType="com.imooc.o2o.entity.PersonInfo">
<id column="user_id" property="userId"/>
<result column="name" property="name"/>
</association>
</resultMap>
<select id="queryByShopId" resultMap="shopMap" parameterType="Long">
select
s.shop_id,
s.shop_name,
s.shop_desc,
s.shop_addr,
s.phone,
s.shop_img,
s.priority,
s.create_time,
s.last_edit_time,
s.enable_status,
s.advice,
a.area_id,
a.area_name,
sc.shop_category_id,
sc.shop_category_name
from
tb_shop s,
tb_area a,
tb_shop_category sc
where
s.area_id=a.area_id
and
s.shop_category_id=sc.shop_category_id
and
s.shop_id=#{shopId}
</select>
3. ShopDaoTest
在 ShopDaoTest方法中增加一个测试方法:
@Test
public void testQueryShopById(){
long shopId = 143;
Shop shop = shopDao.queryByShopId(shopId);
System.out.println("areaId:"+shop.getArea().getAreaId());
System.out.println("areaName:"+shop.getArea().getAreaName());
}
2. 店铺信息编辑之Service层的实现
在service中也要完成两个方法:店铺信息的获取,更新店铺信息
1. ShopService接口
/**
* 通过店铺Id获取店铺信息
* @param shopId
* @return
*/
Shop getByShopId(long shopId);
/**
* 更新店铺信息,包括对图片的处理
* @param shop
* @param shopImgInputStream
* @param fileName
* @return
* @throws ShopOperationException
*/
ShopExecution modifyShop(Shop shop,InputStream shopImgInputStream,String fileName) throws ShopOperationException;
2. ShopServiceImpl实现类
在ImageUtil工具类中编写删除图片的方法:
/**
* storePath是文件路径还是目录路径
* 如果storePath是文件路径就删除该文件
* 如果storePath是目录路径就删除该目录下面的所有文件
* @param storePath
*/
public static void deleteFileOrPath(String storePath){
File fileOrPath = new File(PathUtil.getImgBasePath()+storePath);
if(fileOrPath.exists()){
//判断文件是否为目录
if(fileOrPath.isDirectory()){
File files[] = fileOrPath.listFiles();
//递归删除目录下面的文件
for(int i=0;i<files.length;i++){
files[i].delete();
}
}
fileOrPath.delete();
}
}
在ShopServiceImpl方法中添加:
@Override
public Shop getByShopId(long shopId) {
return shopDao.queryByShopId(shopId);
}
@Override
public ShopExecution modifyShop(Shop shop, InputStream shopImgInputStream, String fileName) throws ShopOperationException{
if(shop==null || shop.getShopId()==null){
return new ShopExecution(ShopStateEnum.NULL_SHOP);
}else{
try {
//1.判断是否需要处理图片(更换店铺的图片)
if(shopImgInputStream!=null && fileName!=null &&!"".equals(fileName)){
Shop tempShop = shopDao.queryByShopId(shop.getShopId());
//先判断店铺图片存不存在,如果存在就删除
if(tempShop.getShopImg()!=null){
ImageUtil.deleteFileOrPath(tempShop.getShopImg());
}
//生成新的店铺图片
addShopImg(shop,shopImgInputStream,fileName);
}
//2.更新店铺信息
shop.setLastEditTime(new Date());
int effectedNum = shopDao.updateShop(shop);
if(effectedNum<=0){
return new ShopExecution(ShopStateEnum.INNER_ERROR);
}else {
shop=shopDao.queryByShopId(shop.getShopId());
return new ShopExecution(ShopStateEnum.SUCCESS,shop);
}
} catch (Exception e) {
throw new ShopOperationException("modifyShop error:"+e.getMessage());
}
}
}
3. ShopServiceTest测试类
@Test
public void testModifyShop() throws ShopOperationException,FileNotFoundException{
Shop shop = new Shop();
shop.setShopId(143L);
shop.setShopName("修改后的店铺名称:");
//要传入的文件
File shopImg = new File("F:/XiaoYuanShangPu/dabai.jpg");
//将图片文件封装为文件流
InputStream is = new FileInputStream(shopImg);
//更改图片信息
ShopExecution shopExecution = shopService.modifyShop(shop,is,shopImg.getName());
System.out.println(shopExecution.getShop().getShopImg());
}
3. 店铺信息编辑之Controller层的实现
在ShopManagementController类中加入:
@RequestMapping(value = "/getshopbyid",method = RequestMethod.GET)
@ResponseBody
private Map<String,Object> getShopById(HttpServletRequest request){
Map<String,Object> modelMap = new HashMap<>();
Long shopId=HttpServletRequestUtil.getLong(request,"shopId");
System.out.println(shopId);
if(shopId>-1){
try {
//根据id获取店铺信息
Shop shop = shopService.getByShopId(shopId);
//获取区域列表的信息
List<Area> areaList = areaService.getAreaList();
modelMap.put("shop",shop);
modelMap.put("areaList",areaList);
modelMap.put("success",true);
} catch (Exception e) {//保险起见,加一个try/catch
modelMap.put("success", false);
modelMap.put("errMsg", e.toString());
}
}else {
modelMap.put("success", false);
modelMap.put("errMsg", "empty shopId");
}
return modelMap;
}
启动tomcat输出下面的请求路径和参数:
完成controller层的修改店铺信息,同时更改店铺注册:
/**
* @Title: modifyshop
* @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 (!CodeUtil.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;
}
/**
* 店铺注册
* @param request
* @return
*/
@RequestMapping(value="/registshop",method = RequestMethod.POST)
@ResponseBody
private Map<String,Object> registerShop(HttpServletRequest request){
Map<String,Object> modelMap=new HashMap<String,Object>();
//先判断验证码是否正确
if (!CodeUtil.verifyCode(request)){//当验证码错误时
modelMap.put("success",false);
modelMap.put("errMsg","输入了错误的验证码");
return modelMap;
}
//1.接受转换相应的参数,包括店铺信息和店铺图片信息
String shopStr = HttpServletRequestUtil.getString(request,"shopStr");//通过转换工具类将前端传来的数据转为字符串
ObjectMapper mapper=new ObjectMapper();//获取处理json的对象
//定义一个Shop实体类来接收起前端传来的信息
Shop shop=null;
try{
shop=mapper.readValue(shopStr,Shop.class);//将传入的shopStr转为Shop对象并完成赋值
}catch (Exception e){//出错后输出错误信息
modelMap.put("success",false);
modelMap.put("errMsg",e.getMessage());
return modelMap;
}
//操作添加图片
CommonsMultipartFile shopImg=null;//spring自带
CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver(
request.getSession().getServletContext()
);//解析request传来的文件的,通过本次会话的上下文获取相关文件上传的内容
if (commonsMultipartResolver.isMultipart((request))) {//如果有上传的文件流
MultipartHttpServletRequest multipartHttpServletRequest= (MultipartHttpServletRequest) request;//这样就能提取出request中的文件流了
shopImg=(CommonsMultipartFile)multipartHttpServletRequest.getFile("shopImg");//(这个字符串"shopImg"是前端传来的),得到文件
}else {//如果不具备图片
modelMap.put("success",false);
modelMap.put("errMsg","上传图片不能为空");
return modelMap;
}
// 2.注册店铺
if (shop!=null&&shopImg!=null) {//如果接受完相应的参数
PersonInfo owner=(PersonInfo)request.getSession().getAttribute("user");//owner的信息可以通过session获取
shop.setOwner(owner);
ShopExecution shopExecution= null;//不能直接传文件,因为CommonsMultipartFile和File不能直接转换
try {
shopExecution = shopService.addShop(shop,shopImg.getInputStream(),shopImg.getOriginalFilename());
if (shopExecution.getState()== ShopStateEnum.CHECK.getState()){//如果操作成功
modelMap.put("success",true);
List<Shop> shopList = (List<Shop>)request.getSession().getAttribute("shopList");
if(shopList==null||shopList.size()==0){
shopList = new ArrayList<Shop>();
}
shopList.add(shopExecution.getShop());
request.getSession().setAttribute("shopList",shopList);
}else {
modelMap.put("success",false);
modelMap.put("errMsg",shopExecution.getStateInfo());
return modelMap;
}
} catch (IOException e) {
e.printStackTrace();
}
return modelMap;
}else{
modelMap.put("success",false);
modelMap.put("errMsg","请输入店铺信息");
return modelMap;
}
}
4. 店铺信息编辑之View层实现
/o2o/src/main/webapp/resources/js/shop/shopoperation.js文件中增加两个url:
// 通过shopId获取商铺信息的URL
var getShopInfoByShopId = '/o2o/shopadmin/getshopbyid?shopId=' + shopId;
// 修改商铺的URL
var modifyShopUrl = '/o2o/shopadmin/modifyshop';
shopId 如何获取呢?
/o2o/src/main/webapp/resources/js/common/common.js中写个公共方法
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) {
return decodeURIComponent(r[2]);
}
return '';
}
在shopoperation.js 调用即可,同时根据请求的URL来判断是注册还是编辑商铺。
// 通过url是否含有shopId来判断是注册还是编辑商铺
var shopId = getQueryString('shopId');
// shopId非空返回true,空者返回false
var isEdit = shopId ? true :false;
// 根据isEdit 来判断 是注册商品还是修改商铺
if(!isEdit){
// 调用getShopInitInfo,注册店铺用
getShopInitInfo();
}else{
// 调用getShopInfoById,修改店铺用
getShopInfoById(shopId);
}
编写getShopInfoById(shopId);
/**
* 通过shopId获取shop信息
*/
function getShopInfoById(shopId){
$.getJSON(getShopInfoByShopId,function(data){
if(data.success){
// 将后台返回的shop通过shop变量接收,方便赋值
var shop = data.shop;
// 赋值 要和shop实体类中的属性名保持一致
$('#shop-name').val(shop.shopName);
$('#shop-name').attr('disabled','disabled');
$('#shop-addr').val(shop.shopAddr);
$('#shop-phone').val(shop.phone);
$('#shop-desc').val(shop.shopDesc);
// 商品目录进行赋值 商品目录仅仅加载对应的目录,且不可编辑
var shopCategory = '<option data-id="'
+shop.shopCategory.shopCategoryId + '" selected>'
+shop.shopCategory.shopCategoryName +'</option>';
$('#shop-category').html(shopCategory);
// 设置为不可编辑
$('#shop-category').attr('disabled','disabled');
// 区域进行赋值 区域可以进行编辑,并且初始设置为后台对应的区域
var tempShopAreaHtml = '';
data.areaList.map(function(item, index) {
tempShopAreaHtml += '<option data-id="' + item.areaId
+ '">' + item.areaName + '</option>';
});
$('#shop-area').html(tempShopAreaHtml);
//初始设置为后台对应的区域
$("#shop-area option[data-id='"+shop.area.areaId+"']").attr("selected","selected");
}else{
$.toast(data.errMsg);
}
});
};
修改submit:
//添加:如果是编辑,需要传入shopId
if(isEdit){
shop.shopId=shopId;
}
..... 省略
// 利用ajax提交
$.ajax({
// 修改url
url:isEdit ? modifyShopUrl:registerShopUrl,
..... 省略
});
完整shopoperation.js文件:
$(function() {
// 通过url是否含有shopId来判断是注册还是编辑商铺
var shopId = getQueryString('shopId');
// shopId非空返回true,空者返回false
var isEdit = shopId ? true :false;
// 获取基本信息的URL
var initUrl = '/o2o/shopadmin/getshopinitinfo';
// 注册店铺的URL
var registerShopUrl = '/o2o/shopadmin/registshop';
// 通过shopId获取商铺信息的URL
var getShopInfoByShopId = '/o2o/shopadmin/getshopbyid?shopId=' + shopId;
// 修改商铺的URL
var modifyShopUrl = '/o2o/shopadmin/modifyshop';
// 根据isEdit 来判断 是注册商品还是修改商铺
if(!isEdit){
// 调用getShopInitInfo,注册店铺用
getShopInitInfo();
}else{
// 调用getShopInfoById,修改店铺用
getShopInfoById(shopId);
}
/**
* 通过shopId获取shop信息
*/
function getShopInfoById(shopId){
$.getJSON(getShopInfoByShopId,function(data){
if(data.success){
// 将后台返回的shop通过shop变量接收,方便赋值
var shop = data.shop;
// 赋值要和shop实体类中的属性名保持一致
$('#shop-name').val(shop.shopName);
$('#shop-name').attr('disabled','disabled');
$('#shop-addr').val(shop.shopAddr);
$('#shop-phone').val(shop.phone);
$('#shop-desc').val(shop.shopDesc);
// 商品目录进行赋值商品目录仅仅加载对应的目录,且不可编辑
var shopCategory = '<option data-id="'
+shop.shopCategory.shopCategoryId + '" selected>'
+shop.shopCategory.shopCategoryName +'</option>';
$('#shop-category').html(shopCategory);
// 设置为不可编辑
$('#shop-category').attr('disabled','disabled');
// 区域进行赋值 区域可以进行编辑,并且初始设置为后台对应的区域
var tempShopAreaHtml = '';
data.areaList.map(function(item, index) {
tempShopAreaHtml += '<option data-id="' + item.areaId
+ '">' + item.areaName + '</option>';
});
$('#shop-area').html(tempShopAreaHtml);
//初始设置为后台对应的区域
$("#shop-area option[data-id='"+shop.area.areaId+"']").attr("selected","selected");
}else{
$.toast(data.errMsg);
}
});
};
/**
* 从后台加载获取下拉菜单的值
*/
function getShopInitInfo() {
$.getJSON(initUrl, function(data) {
if (data.success) {
var tempShopCategoryHtml = '';
var tempShopAreaHtml = '';
data.shopCategoryList.map(function(item, index) {
tempShopCategoryHtml += '<option data-id="'
+ item.shopCategoryId + '">' + item.shopCategoryName
+ '</option>';
});
data.areaList.map(function(item, index) {
tempShopAreaHtml += '<option data-id="' + item.areaId
+ '">' + item.areaName + '</option>';
});
// 获取html中对应标签的id 赋值
$('#shop-category').html(tempShopCategoryHtml);
$('#shop-area').html(tempShopAreaHtml)
}else{
$.toast(data.errMsg);
}
});
};
/**
* submit按钮触发的操作
*/
$('#submit').click(function() {
// 获取页面的值
var shop = {};
// 如果是编辑,需要传入shopId
if(isEdit){
shop.shopId=shopId;
}
// 注意: 这个地方的变量名称要和Shop实体类中的属性保持一致,因为后台接收到shopStr后,会将Json转换为实体类,如果不一致会抛出异常
// com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
shop.shopName = $('#shop-name').val();
shop.shopAddr = $('#shop-addr').val();
shop.phone = $('#shop-phone').val();
shop.shopDesc = $('#shop-desc').val();
// 选择id,双重否定=肯定
shop.shopCategory = {
// 这里定义的变量要和ShopCategory.shopCategoryId保持一致,否则使用databind转换会抛出异常
shopCategoryId:$('#shop-category').find('option').not(function(){
return !this.selected;
}).data('id')
};
shop.area = {
// 这里定义的变量要和Area.areaId属性名称保持一致,否则使用databind转换会抛出异常
areaId:$('#shop-area').find('option').not(function(){
return !this.selected;
}).data('id')
};
// 图片
var shopImg = $('#shop-img')[0].files[0];
// 验证码
var verifyCodeActual =$('#j_kaptcha').val();
console.log('verifyCodeActual:'+verifyCodeActual);
if(!verifyCodeActual){
$.toast('请输入验证码');
return;
}
// 接收数据
var formData = new FormData();
// 和后端约定好,利用shopImg和 shopStr接收 shop图片信息和shop信息
formData.append('shopImg',shopImg);
// 转成JSON格式,后端收到后将JSON转为实体类
formData.append('shopStr',JSON.stringify(shop));
// 将数据封装到formData发送到后台
formData.append('verifyCodeActual',verifyCodeActual);
// 利用ajax提交
$.ajax({
url:isEdit ? modifyShopUrl:registerShopUrl,
type:'POST',
data:formData,
contentType:false,
processData:false,
cache:false,
success:function(data){
if(data.success){
$.toast('提示信息:'+data.errMsg);
}else{
$.toast('提示信息:' + data.errMsg);
}
// 点击提交后 不管成功失败都更换验证码,防止重复提交
$('#kaptcha_img').click();
}
});
});
});
5. 前后端联调测试
以debug方式打开tomcat,打开后加上断点,重新加载页面,
加载页面后,在后端代码上加上断点: