SSM框架项目【米米商城】38-54商品更新功能

开始时间:2022-03-03
课程链接:米米商城

新增商品分析

在这里插入图片描述
我们下一步需要测试新增商品按钮
在这里插入图片描述
这里有一个类别的添加,这是需要读取我们的数据库,查看我们有多少

商品类别的开发

这里不是用controller,而是使用监听器

package listener;

import BUPT.pojo.ProductType;
import BUPT.service.ProductTypeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.util.List;

@WebListener
public class ProductTypeListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 获取所有商品类型的列表,controller中是依赖注入的方式获取
        //但这里是在监听器中,而spring框架的注册也是以监听器的形式注册的
        //执行的接口都是同一个,没办法保证是这里的监听器先实现还是spring的注册先实现
        //所以不能使用spring容器的依赖注入,只能手工取出
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_*.xml");
        ProductTypeService productTypeService = (ProductTypeService) context.getBean("ProductTypeServiceImpl");
        List<ProductType> typeList = productTypeService.getAll();
        //放入全局应用作用域中,供新增页面,修改页面,前台的查询功能提供全部商品类别集合
        sce.getServletContext().setAttribute("typeList", typeList);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}

然后还是在service里面搞实现类
接口

package BUPT.service;

import BUPT.pojo.ProductType;

import java.util.List;

public interface ProductTypeService {
    List<ProductType> getAll();
}

实现类

package BUPT.service.impl;

import BUPT.mapper.ProductTypeMapper;
import BUPT.pojo.ProductType;
import BUPT.pojo.ProductTypeExample;
import BUPT.service.ProductTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("ProductTypeServiceImpl")
public class ProductTypeServiceImpl implements ProductTypeService {

    //在业务逻辑层中,一定会有数据访问层的对象,Spring来new出来
    @Autowired
    ProductTypeMapper productTypeMapper;

    @Override
    public List<ProductType> getAll() {
        return productTypeMapper.selectByExample(new ProductTypeExample());
    }
}

找到对应的addproject.jsp
写上对应的语句

<tr>
    <td class="one">类别</td>
    <td>
        <select name="typeId">
<%--监听器里面setAttribute放的是什么就是什么,这里就是typeList--%>
            <c:forEach items="${typeList}" var="type">
                <option value="${type.typeId}">${type.typeName}</option>
            </c:forEach>
        </select>
    </td>
</tr>

此时启动Tomcat,发现成功加载

异步Ajax图片上传分析

当我们选择了图片后,需要将其回显到图片介绍页里面
在这里插入图片描述
然后还要标注出我们选择图片的名称
在ProductInfoAction中,继续完善功能
因为上传到服务器,为了防止同名文件造成对前面文件的覆盖
我们需要给上传到服务器的文件名进行重命名
也是跟之前加密密文一样的类似操作
添加一个工具类FileNameUtil

package BUPT.utils;

import java.util.UUID;

public class FileNameUtil {
	//根据UUID生成文件名
	public static String getUUIDFileName() {
		UUID uuid = UUID.randomUUID();
		return uuid.toString().replace("-", "");
	}
	//从请求头中提取文件名和类型
	public static String getRealFileName(String context) {
		// Content-Disposition: form-data; name="myfile"; filename="a_left.jpg"
		int index = context.lastIndexOf("=");
		String filename = context.substring(index + 2, context.length() - 1);
		return filename;
	}
	//根据给定的文件名和后缀截取文件名
	public static String getFileType(String fileName){
		//9527s.jpg
		int index = fileName.lastIndexOf(".");
		return fileName.substring(index);
	}
}

ProductInfoAction中进行补充

    //异步Ajax文件上传处理
    @ResponseBody
    @RequestMapping("/ajaxImg")
    //文件上传url的定位url: '${pageContext.request.contextPath}/prod/ajaxImg.action
    //这里就只需要写上ajaxImg
    public Object ajaxImg(MultipartFile pimage, HttpServletRequest request) {
        //实现上传功能

        //提取生成文件名UUID+图片后缀名
        String saveFileName = FileNameUtil.getUUIDFileName() + FileNameUtil.getFileType(pimage.getOriginalFilename());
        //得到项目图片存储的路径
        String path = request.getServletContext().getRealPath("/image_big");

        //拿到的saveFileName是b641bd46ce6c476182f98224d758bc6d.jpg
        //拿到的path是F:\编程学习\Java-Study\mimi_SSM\target\mimi_SSM-1.0-SNAPSHOT\image_big
        
        //前两步拿到了文件名和所在原始路径,第三步转存,转存到我们上面写的这个路径里面去
        //File.separator是为了动态获取文件分隔符,不同操作系统可能会不一样
        //存放到F:\编程学习\Java-Study\mimi_SSM\image_big\XXX.jpg
        try {
            pimage.transferTo(new File(path + File.separator + saveFileName));
        } catch (IOException e) {
            e.printStackTrace();
        }

        //返回客户端JSON对象,封装图片的路径,为了在页面实现立即回显
        JSONObject object = new JSONObject();
        object.put("imgurl", saveFileName);
        return object.toString();
    }

这里要再和前端界面进行对接
addproject.jsp中补充,实现Ajax异步请求

<script type="text/javascript">
    function fileChange() {//注意:此处不能使用jQuery中的change事件,因此仅触发一次,因此使用标签的:onchange属性

        $.ajaxFileUpload({
            url: '${pageContext.request.contextPath}/prod/ajaxImg.action',//用于文件上传的服务器端请求地址
            secureuri: false,//一般设置为false
            fileElementId: 'pimage',//文件上传控件的id属性  <input type="file" id="pimage" name="pimage" />
            dataType: 'json',//返回值类型 一般设置为json
            success: function (obj) //服务器成功响应处理函数
            {
                $("#imgDiv").empty();  //清空原有数据
                //创建img 标签对象
                var imgObj = $("<img>");
                //给img标签对象追加属性
                //回显也是从/image_big/往外取
				//这里记得要补充上/mimi_SSM这个Tomcat发布的项目地址,不然回显找不到地址的
                imgObj.attr("src", "/mimi_SSM/image_big/" + obj.imgurl);

                imgObj.attr("width", "100px");
                imgObj.attr("height", "100px");
                //将图片img标签追加到imgDiv末尾
                $("#imgDiv").append(imgObj);
                //将图片的名称(从服务端返回的JSON中取得)赋值给文件本框
                //$("#imgName").html(data.imgName);
            },
            error: function (e)//服务器响应失败处理函数
            {
                alert(e.message);
            }
        });
    }
</script>

在这里插入图片描述

商品新增功能的开发

观察我们需要的数据
在这里插入图片描述
与数据库作为对比
在这里插入图片描述
可以发现除了p_date不能获取,其他都是可以直接从表单中得到的

我们在service包下的ProductInfoService接口中新增一个方法

    int save(ProductInfo info);

并在实现类中进行实现
完成insert操作

    @Override
    public int save(ProductInfo info) {
        return productInfoMapper.insert(info);
    }

进一步在controller包下的ProductInfoAction进行save.action的书写

@RequestMapping("/save")
    public String save(ProductInfo info, HttpServletRequest request) {
        info.setpImage(saveFileName);
        info.setpDate(new Date());
        int num=-1;
        try {
            num=productInfoService.save(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(num>0){
            request.setAttribute("msg","添加成功");
        }else {
            request.setAttribute("msg","添加失败");
        }

        //增加成功后需要重新访问数据库
        return "forward:/prod/split.action";
    }

再在addproduct.jsp中补充

<form action="${pageContext.request.contextPath}/prod/save.action" enctype="multipart/form-data"
              method="post" id="myform">

看一看效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

商品更新功能

完成更新功能,首先要实现一个商品回显的功能
在这里插入图片描述
也就是说能在单击编辑时,得到更新商品页的所有数据的回显
在这里插入图片描述

需要在service中补充按主键获取对象的接口
ProductInfoService

    //按主键ID查询的方法
    ProductInfo getByID(int pid);

ProductInfoServiceImpl

    @Override
    public ProductInfo getByID(int pid) {
        return productInfoMapper.selectByPrimaryKey(pid);
    }

在controller中添加方法

//实现编辑功能时能加载该字段所有的数据,进行初始化,实现数据的呈现
    @RequestMapping("/myupdate")
    public String myshow(int pid, HttpServletRequest request) {
    //清空之前的saveFileName
		saveFileName = "";
        //获取商品信息
        ProductInfo info = productInfoService.getByID(pid);
        //作用域名称用prod,是为了和前端对应
        request.setAttribute("prod", info);
        return "update";
    }

将数据返回给update.jsp

我们发现这里涉及到了一个类型的复选框,怎么来实现选中某类商品,该商品的类型,复选框对应到其类型呢?
在update.jsp中,我们写上

<tr>
    <td class="one">类别</td>
    <td>
        <select name="typeId">
            <%--这里的typeList是和监听器的那里一致--%>
            <c:forEach items="${typeList}" var="type">
                <option value="${type.typeId}"
                    <%--读取所有的typeId和我们传过来的pro.typeId进行比较--%>
                    <%--当两者一致时,将复选框标为选中状态--%>
                        <c:if test="${type.typeId==prod.typeId}">
                            selected="selected"
                        </c:if>
                >${type.typeName}</option>

            </c:forEach>
        </select>
    </td>
</tr>

我们还要在product.jsp中,实现回显功能的提交

<td>
    <button type="button" class="btn btn-info "
            onclick="one(${p.pId},${info.pageNum})">编辑
    </button>
    <button type="button" class="btn btn-warning" id="mydel"
            onclick="del(${p.pId})">删除
    </button>
</td>

通过单击编辑按钮,跳转到编辑页面

function one(pid, ispage) {
//实现,点击”编辑“按钮时,向服务器提交请求,传递商品id,这里的pid是我们前面ProductInfoAction中写的参数名
location.href = "${pageContext.request.contextPath}/prod/myupdate.action?pid=" + pid + "&page=" + ispage;
}

此时我们就能正确得到预期的结果了
在这里插入图片描述

商品更新

service里面添加接口中的方法,并在ProductInfoServiceImpl新增实现方法

   @Override
    public int update(ProductInfo info) {
        return productInfoMapper.updateByPrimaryKey(info);
    }

controller里面新增一个update方法
当saveFileName不为空时,也就是说我们有过修改图片,那么就要更新info对象

    @RequestMapping("/update")
    public String update(ProductInfo info, HttpServletRequest request) {
        //如果Ajax有过异步图片上传,则saveFileName里有上传来的图片的名称
        //如果没有上传过,则saveFileName为空
        //实体类info使用隐藏表单域提供pImage原始图片名称
        // (我们已经在上面/save的末尾清空了saveFileName)
        if (!saveFileName.equals("")) {
            //说明有过异步上传的处理,有过上传肯定这里就读取了文件名
            info.setpImage(saveFileName);
        }
        int num = -1;
        try {
            num = productInfoService.update(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (num > 0) {
            //此时更新成功
            request.setAttribute("msg", "更新成功");
        } else {
            request.setAttribute("msg", "更新失败");
        }
        
        //当返回的地址存在forward或redirect关键字时,自动屏蔽视图解析器,所以这里要写完整
        return "forward:/prod/split.action";
    }

对应前端update.jsp中的核心代码为

<div id="nav">
        <p>商品管理>更新商品</p>
    </div>
    <script type="text/javascript">
        function fileChange() {//注意:此处不能使用jQuery中的change事件,因此仅触发一次,因此使用标签的:onchange属性

            $.ajaxFileUpload({
                url: '${pageContext.request.contextPath}/prod/ajaxImg.action',//用于文件上传的服务器端请求地址
                secureuri: false,//一般设置为false
                fileElementId: 'pimage',//文件上传控件的id属性  <input type="file" id="pimage" name="pimage" />
                dataType: 'json',//返回值类型 一般设置为json
                success: function (obj) //服务器成功响应处理函数
                {

                    $("#imgDiv").empty();  //清空原有数据
                    //创建img 标签对象
                    var imgObj = $("<img>");
                    //给img标签对象追加属性
                    imgObj.attr("src", "/mimi_SSM/image_big/" + obj.imgurl);
                    imgObj.attr("width", "100px");
                    imgObj.attr("height", "100px");
                    //将图片img标签追加到imgDiv末尾
                    $("#imgDiv").append(imgObj);
                    //将图片的名称(从服务端返回的JSON中取得)赋值给文件本框
                    //$("#imgName").html(data.imgName);
                },
                error: function (e)//服务器响应失败处理函数
                {
                    alert(e.message);
                }
            });
        }
    </script>

这里和添加数据一样,实现图片回显

结束时间:2022-03-05

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值