请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

request.getParameter()取出的值为空

老师您好,我在测试商店添加的时候碰到了一个问题,导致我添加不成功并报错,

//img1.sycdn.imooc.com//szimg/5a4e7f910001b3b314400810.jpg

最后定位在了这里

//img1.sycdn.imooc.com//szimg/5a4e7f9f0001d6bd14400810.jpg

可以看到HttpServletRequestUtil工具类中的getString方法的返回值为空,导致了68行报错,跟入之后发现其中的request.getParameter(key)取出并返回的result的值为空,于是我就跟到了前台去看

//img1.sycdn.imooc.com//szimg/5a4e7fd10001d5b114400810.jpg

,结果我完全不知道是否已经成功的将shop转换成JSON并存入formData的shopStr中了,在右侧看shopStr也没有找到我刚刚addend进formData的shop的JSON,请问老师这种情况下该怎么排错?

https://img1.sycdn.imooc.com//szimg/5a4f66d40001c57503280286.jpg

正在回答

8回答

估计今天不行了 刚下飞机到天津回北京。。回到很晚了。。估计明后天:)

0 回复 有任何疑惑可以回复我~
  • 提问者 吐槽职人 #1
    没关系老师,我继续往下看您的课好了,您什么时候有时间再看也来得及
    回复 有任何疑惑可以回复我~ 2018-01-06 22:34:22
  • 提问者 吐槽职人 #2
    老师您好,我已近找到问题了!原因是mvc的文件上传解析器没有配置!另外pom还有个包弄错了!
    回复 有任何疑惑可以回复我~ 2018-01-07 17:24:29
  • 提问者 吐槽职人 #3
    非常感谢老师尽心尽力的为学生解决问题,给老师添麻烦了,谢谢老师!
    回复 有任何疑惑可以回复我~ 2018-01-07 17:26:23
翔仔 2018-01-06 21:24:05

关键就是没用电脑看问题比较蛋疼。。

0 回复 有任何疑惑可以回复我~
提问者 吐槽职人 2018-01-06 01:48:37

在把ajax中的contentType注释掉并且将post那里换成单引号之后终于提交成功了//img1.sycdn.imooc.com//szimg/5a4fb91f00016fed11280314.jpg但是在后台的controller中仍然没有获取到shopStr。。。

//img1.sycdn.imooc.com//szimg/5a4fb97c0001e28411000048.jpg

并且还有个很奇怪的现象,在debug模式启动项目,请求头文件里是Content-Type:application/x-www-form-urlencoded没错,但一旦正常启动项目,请求头文件就又变回Content-Type:text/html;charset=utf-8了。。。这个奇葩的问题我也是重现了好几遍才确认的。。。我都傻眼了。。。


0 回复 有任何疑惑可以回复我~
  • 翔仔 #1
    看来还是跟contentType有关,同学可以试着将其设为false,然后跑跑 记得清缓存 如果还不行 把post改成get js和controller两头都改 抱歉哈昨晚睡着了 今早起床开车赶飞机忘记回复了
    回复 有任何疑惑可以回复我~ 2018-01-06 11:30:50
  • 提问者 吐槽职人 回复 翔仔 #2
    抱歉老师好像并不是这样。。。昨晚我是错把响应头当成请求头了。。。
    回复 有任何疑惑可以回复我~ 2018-01-06 21:02:39
  • 提问者 吐槽职人 回复 翔仔 #3
    今天又研究了一整天。。。您说的几个方法都试了,貌似都不对
    回复 有任何疑惑可以回复我~ 2018-01-06 21:05:00
翔仔 2018-01-06 01:02:10

两个文件的属性都是utf8的编码对不。如果是的话 把ajax里的contentType改成刚刚翔仔上述的那个type 然后post那里把双引号改成单引号,虽然有点迷信了不过也这样试试看:) 记得清缓存

0 回复 有任何疑惑可以回复我~
  • 提问者 吐槽职人 #1
    两个文件都是utf-8的没错,但即使我在ajax中设置了contentType :'application/x-www-form-urlencoded',到了头文件那里还是Content-Type:text/html;charset=utf-8!完全搞不懂为啥。。。换浏览器清除缓存,双引号改成单引号我都试过了。。。
    回复 有任何疑惑可以回复我~ 2018-01-06 01:14:01
提问者 吐槽职人 2018-01-05 23:24:15
$(function () {
    // 用于店铺注册时候的店铺类别以及区域列表的初始化的URL
    var initUrl = '/shopadmin/getshopinitinfo';
    // 注册店铺的URL
    var registerShopUrl = '/shopadmin/registerShop';
    getShopInitInfo();

    //取得所有二级店铺类别以及区域信息,并分别赋值进类别列表以及区域列表
    function getShopInitInfo() {
        $.getJSON(initUrl, function(data) {
            if (data.success) {
                var tempHtml = "";
                var tempAreaHtml = "";
                // 初始化区域列表
                data.shopCategoryList.map(function(item) {
                    tempHtml += '<option data-id="' + item.shopCategoryId
                        + '">' + item.shopCategoryName + "</option>";
                });
                data.areaList.map(function(item) {
                    tempAreaHtml += '<option data-id="' + item.areaId + '">'
                        + item.areaName + "</option>";
                });
                $("#shop-category").html(tempHtml);
                $("#area").html(tempAreaHtml);
            }
        });
    }

    $("#submit").click(function () {
        // 创建shop对象
        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);
        // 将shop json对象转成字符流保存至表单对象key为shopStr的的键值对里
        var shopJSON = JSON.stringify(shop);
        alert(shopJSON);
        formData.append("shopStr", JSON.stringify(shop));
        // 将数据提交至后台处理相关操作
        $.ajax({
            url : registerShopUrl,
            type : "POST",
            data : formData,
            contentType : false,
            processData : false,
            cache : false,
            success : function(data) {
                if (data.success) {
                    $.toast("提交成功!");
                } else {
                    $.toast("提交失败!" + data.errMsg);
                }
            }
        });
    });
});


0 回复 有任何疑惑可以回复我~
提问者 吐槽职人 2018-01-05 23:23:33
@RequestMapping(value = "/registerShop", method = RequestMethod.POST)
@ResponseBody
private Map<String, Object> registerShop(HttpServletRequest request) {
    //返回对象,modelMap存储成功或错误信息
    Map<String, Object> modelMap = new HashMap<String, Object>();
    //1.接收并转化相应的参数,包括店铺信息以及图片信息
    String shopStr = request.getParameter("shopStr");
    //String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
    //jackson实体类
    ObjectMapper mapper = new ObjectMapper();
    Shop shop = null;
    try {
        //1-1使用jackson将接受的参数转换成实体类
        shop = mapper.readValue(shopStr, Shop.class);
    } catch (IOException e) {
        //异常返回
        modelMap.put("success", false);
        modelMap.put("errMsg", e.toString());
        return modelMap;
    }
    //1-2处理图片信息
    //spring自带对象用来存储上传文件的CommonsMultipartFile
    CommonsMultipartFile shopImg = null;
    //CommonsMultipartResolver :一个多分解的容器
    //request.getSession().getServletContext():获取当前会话的上下文中上传的文件内容
    CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
            request.getSession().getServletContext());
    //如果不为空的话
    if (commonsMultipartResolver.isMultipart(request)) {
        //将整个request放进容器里变成多部分request
        MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
        //取出容器中前台命名为shopImg的文件流放入shopImg,这样就取得了上传的文件
        shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");
    } else {
        //失败返回
        modelMap.put("success", false);
        modelMap.put("errMsg", "上传不能为空");
        return modelMap;
    }

    //转换shopImg格式为file
    //声明一个空file文件用于转换shopImg
    File shopImgFile = new File(PathUtil.getImgBasePath() + ImageUtil.getRandomFileName());
    try {
        //创建空文件
        shopImgFile.createNewFile();
    } catch (IOException e) {
        //异常返回
        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;

        try {
            se = shopService.addShop(shop, shopImg.getInputStream(), shopImg.getOriginalFilename());
        } catch (IOException e) {
            //异常返回
            modelMap.put("success", false);
            modelMap.put("errMsg", "上传不能为空");
            return modelMap;
        }
        if (se.getState() == ShopStateEnum.CHECK.getState()) {
            //成功返回
            modelMap.put("success", true);
            modelMap.put("errMsg", se.getStateInfo());
        } else {
            //失败返回
            modelMap.put("success", false);
            modelMap.put("errMsg", "请输入店铺信息");
            return modelMap;
        }
        return modelMap;
    } else {
        //失败返回
        modelMap.put("success", false);
        modelMap.put("errMsg", "请输入店铺信息");
        return modelMap;
    }
}


0 回复 有任何疑惑可以回复我~
翔仔 2018-01-05 22:58:31

同学好 麻烦把完整的js代码和controller对应方法的代码贴一下

0 回复 有任何疑惑可以回复我~
  • 提问者 吐槽职人 #1
    老师您看一下
    回复 有任何疑惑可以回复我~ 2018-01-05 23:25:39
  • 翔仔 回复 提问者 吐槽职人 #2
    同学好,代码看起来是没有问题的,这个问题比较难判断,因为代码我这边没办法去执行,所以从经验判断,如果代码没问题,那么很有可能是两处中的一处有问题:
    第一处是content-type
    第二处是编码问题
    具体可以参阅
    http://blog.csdn.net/fs1360472174/article/details/44727159
    针对第一种问题,同学可以看看content-type是否为application/x-www-form-urlencoded,可以在chrome开发者模式请求头header里查询
    针对第二种问题,同学可以右键js文件通过属性查看js文件的编码,并且右键controller文件,通过属性查看controller文件的编码,两者保持utf8
    此外,同学也可以清除下浏览器缓存再试试,还有可能是缓存问题:)
    PS:这种不明显的问题解决起来有点棘手,目前还没遇到过
    回复 有任何疑惑可以回复我~ 2018-01-05 23:54:34
  • 提问者 吐槽职人 回复 翔仔 #3
    非常感谢老师的指导!今天太晚了您早点休息吧!我自己在研究研究!
    回复 有任何疑惑可以回复我~ 2018-01-06 00:05:52
翔仔 2018-01-05 11:15:26
同学好,以下是我的js部分的代码,这个问题一般需要debug看看shop是否有值,同时再看formData里的shopStr是否有值,之后再看看跟后台对接的method type之类是否正确:)
/**
 * 
 */
$(function() {
	// 从URL里获取shopId参数的值
	var shopId = getQueryString('shopId');
	// 由于店铺注册和编辑使用的是同一个页面,
	// 该标识符用来标明本次是添加还是编辑操作
	var isEdit = shopId ? true : false;
	// 用于店铺注册时候的店铺类别以及区域列表的初始化的URL
	var initUrl = '/o2o/shopadmin/getshopinitinfo';
	// 注册店铺的URL
	var registerShopUrl = '/o2o/shopadmin/registershop';
	// 编辑店铺前需要获取店铺信息,这里为获取当前店铺信息的URL
	var shopInfoUrl = "/o2o/shopadmin/getshopbyid?shopId=" + shopId;
	// 编辑店铺信息的URL
	var editShopUrl = '/o2o/shopadmin/modifyshop';
	// 判断是编辑操作还是注册操作
	if (!isEdit) {
		getShopInitInfo();
	} else {
		getShopInfo(shopId);
	}
	// 通过店铺Id获取店铺信息
	function getShopInfo(shopId) {
		$.getJSON(shopInfoUrl, function(data) {
			if (data.success) {
				// 若访问成功,则依据后台传递过来的店铺信息为表单元素赋值
				var shop = data.shop;
				$('#shop-name').val(shop.shopName);
				$('#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>';
				var tempAreaHtml = '';
				// 初始化区域列表
				data.areaList.map(function(item, index) {
					tempAreaHtml += '<option data-id="' + item.areaId + '">'
							+ item.areaName + '</option>';
				});
				$('#shop-category').html(shopCategory);
				// 不允许选择店铺类别
				$('#shop-category').attr('disabled', 'disabled');
				$('#area').html(tempAreaHtml);
				// 给店铺选定原先的所属的区域
				$("#area option[data-id='" + shop.area.areaId + "']").attr(
						"selected", "selected");
			}
		});
	}
	// 取得所有二级店铺类别以及区域信息,并分别赋值进类别列表以及区域列表
	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() {
		// 创建shop对象
		var shop = {};
		if (isEdit) {
			// 若属于编辑,则给shopId赋值
			shop.shopId = shopId;
		}
		// 获取表单里的数据并填充进对应的店铺属性中
		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);
		// 将shop json对象转成字符流保存至表单对象key为shopStr的的键值对里
		formData.append('shopStr', JSON.stringify(shop));
		// 获取表单里输入的验证码
		var verifyCodeActual = $('#j_captcha').val();
		if (!verifyCodeActual) {
			$.toast('请输入验证码!');
			return;
		}
		formData.append('verifyCodeActual', verifyCodeActual);
		// 将数据提交至后台处理相关操作
		$.ajax({
			url : (isEdit ? editShopUrl : registerShopUrl),
			type : 'POST',
			data : formData,
			contentType : false,
			processData : false,
			cache : false,
			success : function(data) {
				if (data.success) {
					$.toast('提交成功!');
					if (!isEdit) {
						// 若为注册操作,成功后返回店铺列表页
						window.location.href = "/o2o/shopadmin/shoplist";
					}
				} else {
					$.toast('提交失败!' + data.errMsg);
				}
				// 点击验证码图片的时候,注册码会改变
				$('#captcha_img').click();
			}
		});
	});

})


0 回复 有任何疑惑可以回复我~
  • 提问者 吐槽职人 #1
    老师您好,请问我该如何去看formData里的shopStr是否有值呢?只能通过传到后台再取出这种方式吗?
    回复 有任何疑惑可以回复我~ 2018-01-05 15:48:00
  • 提问者 吐槽职人 #2
    js中的shop是有值的,但是到了后台想要取出formData中的shopStr时值就为空了,现在我不确定是否在append进formData的时候值就为空了
    回复 有任何疑惑可以回复我~ 2018-01-05 15:52:03
  • 翔仔 回复 提问者 吐槽职人 #3
    同学好,chrome的开发者模式里能设置断点进行前端调试呢,可以在watch里看到
    回复 有任何疑惑可以回复我~ 2018-01-05 16:31:25
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信