【校园商铺SSM-22】商品添加--Controller+View+前后端联调的实现

文章目录

      • 1. Controller层的实现
      • 2. View层的实现
        • 2.1 productoperation.html
        • 2.2 productoperation.js
        • 2.3 productmanagement.css
        • 2.4 ShopAdminController添加路由
      • 3. 前后端联合调试

1. Controller层的实现

import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.o2o.dto.ImageHolder;
import com.imooc.o2o.dto.ProductExecution;
import com.imooc.o2o.entity.Product;
import com.imooc.o2o.entity.Shop;
import com.imooc.o2o.enums.ProductStateEnum;
import com.imooc.o2o.exceptions.ProductOperationException;
import com.imooc.o2o.service.ProductService;
import com.imooc.o2o.util.CodeUtil;
import com.imooc.o2o.util.HttpServletRequestUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/shopadmin")
public class ProductManagementController {
     
    @Autowired
    private ProductService productService;

    //支持上传商品详情图的最大数量
    private static final int IMAGEMAXCOUNT = 6;
    @RequestMapping(value = "/addproduct",method = RequestMethod.POST)
    @ResponseBody
    private Map<String,Object> addProduct(HttpServletRequest request) throws IOException {
     
        Map<String,Object> modelMap = new HashMap<>();
        //验证码校验
        if(!CodeUtil.verifyCode(request)){
     
            modelMap.put("success",false);
            modelMap.put("errMsg","输入了错误的验证码");
            return modelMap;
        }

        //接收前端参数的变量的初始化,包括商品,缩略图,详情图列表实体类
        //1.图片
        MultipartHttpServletRequest multipartRequest = null;
        ImageHolder thumbnail = null;
        List<ImageHolder> productImgList = new ArrayList<>();
        //从Session中获取文件流
        CommonsMultipartResolver multipartResolver
                = new CommonsMultipartResolver(request.getSession().getServletContext());
        try {
     
            //如果请求中有文件流,那么取出相关的文件(包括缩略图和详情图)
            if(multipartResolver.isMultipart(request)){
     
                multipartRequest = (MultipartHttpServletRequest)request;
                //取出缩略图并构建ImageHolder对象
                CommonsMultipartFile thumbnailFile
                        = (CommonsMultipartFile)multipartRequest.getFile("thumbnail");
                thumbnail
                        = new ImageHolder(thumbnailFile.getOriginalFilename(),thumbnailFile.getInputStream());

                //取出详情图列表并构建List列表对象,最多支持6张图片上传
                for(int i=0;i<IMAGEMAXCOUNT;i++){
     
                    CommonsMultipartFile productImgFile
                            = (CommonsMultipartFile)multipartRequest.getFile("productImg"+i);
                    if(productImgFile!=null){
     
                        //如果取出的第i个详情图片不为空,那么将其加入详情图列表
                        ImageHolder productImg =
                                new ImageHolder(productImgFile.getOriginalFilename(),productImgFile.getInputStream());
                        productImgList.add(productImg);
                    }else{
     
                        //如果取出的第i个详情图片文件为空,则终止循环
                        break;
                    }
                }
            }else{
     
                modelMap.put("success",false);
                modelMap.put("errMsg","上传图片不能为空");
                return modelMap;
            }
        } catch (Exception e) {
     
            modelMap.put("success",false);
            modelMap.put("errMsg",e.toString());
            return modelMap;
        }

        //2.商品实体类
        ObjectMapper mapper = new ObjectMapper();
        Product product = null;
        String productStr = HttpServletRequestUtil.getString(request,"productStr");
        try {
     
            //尝试获取前台穿来的表单将其装换为Product实体类
            product = mapper.readValue(productStr,Product.class);
        } catch (Exception e) {
     
            modelMap.put("success",false);
            modelMap.put("errMsg",e.toString());
            return modelMap;
        }

        //进行商品添加工作
        if(product!=null && thumbnail!=null && productImgList.size()>0){
     
            try {
     
                //从当前店铺中获取店铺的id并赋值给product,减少对前端数据的依赖
                Shop currentShop = (Shop)request.getSession().getAttribute("currentShop");
                Shop shop = new Shop();
                shop.setShopId(currentShop.getShopId());
                product.setShop(shop);

                ProductExecution productExecution
                        = productService.addProduct(product, thumbnail, productImgList);
                if(productExecution.getState() == ProductStateEnum.SUCCESS.getState()){
     
                    modelMap.put("success",true);
                }else{
     
                    modelMap.put("success",false);
                    modelMap.put("errMsg",productExecution.getStateInfo());
                }
            } catch (ProductOperationException e) {
     
                modelMap.put("success",false);
                modelMap.put("errMsg",e.toString());
                return modelMap;
            }
        }else{
     
            modelMap.put("success",false);
            modelMap.put("errMsg","请输入商品信息");
        }
        return modelMap;
    }
}

2. View层的实现

2.1 productoperation.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">
    <link rel="stylesheet" href="../resources/css/shop/productmanagement.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="product-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="product-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">
                            <input type="number" id="priority" 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="number" id="normal-price" 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="number" id="promotion-price" 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="small-img">
                        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 detail-img-div">
                        <div class="item-title label">详情图片div>
                        <div class="item-input" id="detail-img">
                            <input type="file" class="detail-img">
                            
                        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 id="product-desc" placeholder="商品描述">textarea>
                        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">
                        <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="点击更换"
                                 onclick="changeVerifyCode(this)" src="../Kaptcha" />
                        div>
                    div>
                div>
            li>

        ul>
    div>
    <div class="content-block">
        
        <div class="row">
            <div class="col-50">
                <a href="#"
                   class="button button-big button-fill button-danger" id="back">返回商品管理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.min.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/common/common.js' charset='utf-8'>script>
<script type='text/javascript' src='../resources/js/shop/productoperation.js' charset='utf-8'>script>

body>
html>

2.2 productoperation.js

/**
 *  因为商品的添加和编辑复用同一个页面,所以需要根据url中的商品Id来判断
 */
$(function(){
     
    //通过url是否含有productId来判断是添加商品还是编辑
    var productId = getQueryString('productId');
    // 标示符  productId非空则为true即编辑,否则为添加商品
    var isEdit = productId ? true : false ;

    // 商品添加URL
    var addProductURL = '/o2o/shopadmin/addproduct';
    // 获取商品初始化信息的URL  根据页面原型只需要获取productCategory即可,后台调用之前写好的路由方法即可
    var initProductURL = '/o2o/shopadmin/getproductcategorylist';

    // 通过标示符,确定调用的方法
    if(isEdit){
     
        // 为true,则根据productId调用获取product信息的方法  TODO
        getProductInfoById(productId);
    }else{
     
        // 为false,则初始化新增product页面
        getProductInitInfo();
    }

    /**
     * 始化新增product页面
     *
     * 根据页面原型和数据模型,需要加载该shop对应的productCategory信息(shop信息从服务端session中获取)
     */
    function getProductInitInfo(){
     
        $.getJSON(initProductURL,
            function(data){
     
                if(data.success){
     
                    // 设置product_category
                    var productCategoryList = data.data;
                    var productCategoryTempHtml = '';
                    productCategoryList.map(function(item, index) {
     
                        productCategoryTempHtml
                            += ' item.productCategoryId
                            + '">'
                            + item.productCategoryName
                            + '';
                    });
                    $('#product-category').html(productCategoryTempHtml);
                }else{
     
                    $.toast(data.errMsg)
                }
            });
    };

    /**
     * 点击控件的最后一个且图片数量小于6个的时候,生成一个选择框
     */
    $('.detail-img-div').on('change', '.detail-img:last-child', function() {
     
        if ($('.detail-img').length < 6) {
     
            $('#detail-img').append('');
        }
    });

    /**
     * 提交按钮的响应时间,分别对商品添加和商品编辑做不同的相应
     */
    $('#submit').click(
        function(){
     
            // 创建商品Json对象,并从表单对象中获取对应的属性值
            var product = {
     };

            // 如果是编辑操作,需要传入productId
            if(isEdit){
     
                product.productId = productId;
            }

            product.productName = $('#product-name').val();
            product.productDesc = $('#product-desc').val();

            // 获取商品的特定目录值
            product.productCategory = {
     
                productCategoryId : $('#product-category').find('option').not(
                    function() {
     
                        return !this.selected;
                    }).data('value')
            };

            product.priority = $('#priority').val();
            product.normalPrice = $('#normal-price').val();
            product.promotionPrice = $('#promotion-price').val();

            // 生成表单对象用于接收参数并传递给后台
            var formData = new FormData();

            // 缩略图 (只有一张),获取缩略图的文件流
            var thumbnail = $('#small-img')[0].files[0];
            formData.append('thumbnail',thumbnail);

            // 图片详情
            $('.detail-img').map(
                function(index, item) {
     
                    // 判断该控件是否已经选择了文件
                    if ($('.detail-img')[index].files.length > 0) {
     
                        // 将第i个文件流赋值给key为productImgi的表单键值对里
                        formData.append('productImg' + index,
                            $('.detail-img')[index].files[0]);
                    }
                });
            // 将product 转换为json ,添加到forData
            formData.append('productStr', JSON.stringify(product));

            // 获取表单中的验证码
            var verifyCodeActual = $('#j_captcha').val();
            if (!verifyCodeActual) {
     
                $.toast('请输入验证码!');
                return;
            }
            formData.append("verifyCodeActual", verifyCodeActual);


            // 使用ajax异步提交
            $.ajax({
     
                url: isEdit?editProductURL:addProductURL,
                type: 'POST' ,
                data : formData,
                contentType : false,
                processData : false,
                cache : false,
                success: function(data){
     
                    if (data.success) {
     
                        $.toast('提交成功!');
                        $('#captcha_img').click();
                    } else {
     
                        $.toast('提交失败!');
                        $('#captcha_img').click();
                    }
                }
            });
        });
});

2.3 productmanagement.css

.row-product {
    border: 1px solid #999;
    padding: .5rem;
    border-bottom: none;
}
.row-product:last-child {
    border-bottom: 1px solid #999;
}
.product-name {
    white-space: nowrap;
    overflow-x: scroll;
}
.product-wrap a {
    margin-right: 1rem;
}

2.4 ShopAdminController添加路由

    @RequestMapping(value="/productoperation")
    public String productOperation(){
     
        return "shop/productoperation";
    }


【校园商铺SSM-22】商品添加--Controller+View+前后端联调的实现_第1张图片

3. 前后端联合调试

【校园商铺SSM-22】商品添加--Controller+View+前后端联调的实现_第2张图片
先按f10一步步调试:
【校园商铺SSM-22】商品添加--Controller+View+前后端联调的实现_第3张图片

【校园商铺SSM-22】商品添加--Controller+View+前后端联调的实现_第4张图片
【校园商铺SSM-22】商品添加--Controller+View+前后端联调的实现_第5张图片

【校园商铺SSM-22】商品添加--Controller+View+前后端联调的实现_第6张图片

你可能感兴趣的:(SSM校园商铺项目)