注册店铺2

店铺注册之前端设计

使用sui mobile


image.png

看demo


image.png

选择表单之后复制网页源码,在webapp下创建一个index.html页面然后复制进去。然后把css和js的资源替换掉dns。
然后将表单改成商店信息,修改其他类似这样


image.png

image.png

我们不希望用户通过index.html访问我们的页面需要定义好的路由规则访问,


image.png

这样就不能访问了,只能通过路由,在controller做转发,这里返回为什么
不用WEB-INF和.html呢原因是我们在spring-web.xml已经配置好了,



image.png
image.png

验证成功之后重回写controller

package com.imooc.o2o.web.shopadmin;

@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
    @Autowired
    private ShopService shopService;
    @ResponseBody
    @RequestMapping(value = "/registershop", method = RequestMethod.GET)
    private Map registerShop(HttpServletRequest request) {
        // 返回值
        Map modelMap = new HashMap();
        // 1、接收前端传过来的Shop字符串信息,包括店铺信息以及图片信息,并转换为shop实体类
        // shopStr是跟前端约定好的key值
        String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
        // 接收完成后需要做转换
        ObjectMapper mapper = new ObjectMapper();
        // 定义一个shop实体类去接收
        Shop shop = null;
        // 开始转换
        try {
            shop = mapper.readValue(shopStr, Shop.class);
        } catch (Exception e) {
            // 转换失败就返回modelMap,告诉前台说转换失败
            modelMap.put("success", false);
            modelMap.put("errMsg", e.getMessage());
            return modelMap;
        }
        // 接收图片
        CommonsMultipartFile shopImg = null;
        // 文件上传解析器,去解析request里面的文件信息
        // 从request本次会话的上下文中去获取相关文件上传的内容
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
                request.getSession().getServletContext());
        // 如果有上传的文件流
        //需要将request转换MultipartHttpServletRequest,这个对象就能够提取相对应的文件流
        //shopImg与前端约定
        if (commonsMultipartResolver.isMultipart(request)) {
            MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest)request;
            shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");
        }else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "上传图片不能为空");
            return modelMap;
        }
        // 2、注册店铺
        if(shop != null && shopImg != null) {
            //假定前端传过来的值是不可靠所以越少依赖前端的值越好
            //就拿店铺的实体类来说,onwer的信息可以从session获取而不用去前端获取
            PersonInfo owner = new PersonInfo();
            owner.setUserId(1L);
            shop.setOwner(owner);
            File shopImgFile = new File(PathUtil.getImgBasePath() + ImageUtil.getRandomFileName());
            try {
                shopImgFile.createNewFile();
            }catch(IOException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.getMessage());
                return modelMap;
            }
            try {
                inputStreamToFile(shopImg.getInputStream(), shopImgFile);
            }catch(IOException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.getMessage());
                return modelMap;
            }
            ShopExecution se = shopService.addShop(shop, shopImgFile);
            if(se.getState()==ShopStateEnum.CHECK.getState()) {
                modelMap.put("success", true);
            }else {
                modelMap.put("success", false);
                modelMap.put("errMsg", se.getStateInfo());
            }
            return modelMap;
            
        }else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "店铺信息不能为空");
            return modelMap;
        }
    }
    
    //因为CommonsMultipartFile不能强制转换为File,但是它有InputStream方法
    //所以用InputStream来转换
    private static void inputStreamToFile(InputStream ins, File file) {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            while((bytesRead=ins.read(buffer))!=-1) {
                os.write(buffer, 0, bytesRead);
            }
        }catch(Exception e){
            throw new RuntimeException("调用inputStreamToFile产生异常" + e.getMessage());
        }finally{
            try {
                if(os!=null) {
                    os.close();
                }
                if(ins!=null) {
                    ins.close();
                }
            }catch(IOException e) {
                throw new RuntimeException("关闭inputStreamToFile产生异常" + e.getMessage());
            }
        }
    }
}

编写js内容

image.png

js内容主要就是操作html页面的,主要包括获取初始的信息,第一步主要是获取商铺分类,所属区域的列表信息,第二步是当我们提交的时候将表单里的内容全部获取到,然后通过Ajax给转发到后台,所有的动作都是异步的,这样就不影响用户的体验。

/**
 * 第一功能:从后台获取店铺分类,以及区域等信息将它填充至前台的html控件里面 第二功能:将表单的全部信息获取到转发到后台去注册店铺
 */
$(function(){
    // 初始化url,获取店铺的分类和区域信息
    var initUrl = '/o2o/shopadmin/getshopinitinfo';
    // 注册店铺的url
    var registerShopUrl = '/o2o/shopadmin/registershop';
    alert(initUrl);
    getShopInitInfo();
    // 获取店铺的基本信息
    function getShopInitInfo(){
        $.getJSON(initUrl,function(data){
            if(data.success){
                var tempHtml = '';
                var tempAreaHtml = '';
                data.shopCategoryList.map(function(item, index){
                    tempHtml += '';
                });
                data.areaList.map(function(item, index){
                    tempAreaHtml += '';
                });
                $('#shop-category').html(tempHtml);
                $('#area').html(tempAreaHtml);
            }
        });
    //实现第二功能
    $('#submit').click(function(){
        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);
        formData.append('shopStr', JSON.stringify(shop));
        $.ajax({
            url:registerShopUrl,
            type:'POST',
            data:formData,
            contentType:false,
            proceesData:false,
            cache:false,
            success:function(data){
                if(data.success){
                    $.toast("提交成功!");
                }else{
                    $.toast("提交失败!" + data.errMsg);
                }
            }
        })
    })
    }
})

现在就来实现shopinitinfo方法,这个方法主要是返回区域,店铺类别相关的信息,之前我们已经实现了获取区域列表,现在从dao层开始实现店铺类别。


image.png

创建相关mapper




    

注意from不是form还有最后一个字段parent_id不用逗号。

测试:

public class ShopCategoryDaoTest extends BaseTest {
    @Autowired
    private ShopCategoryDao shopCategoryDao;
    
    @Test
    public void testQueryShopCategory() {
        List shopCategoryList = shopCategoryDao.queryShopCategory(new ShopCategory());
        assertEquals(2, shopCategoryList.size());
        //测试当查找店铺类别传入参数时
        ShopCategory testCategory = new ShopCategory();
        ShopCategory parentCategory = new ShopCategory();
        parentCategory.setShopCategoryId(1L);
        testCategory.setParent(parentCategory);
        shopCategoryList = shopCategoryDao.queryShopCategory(testCategory);
        assertEquals(1, shopCategoryList.size());
    }
    
}

service层

@Service
public class ShopCategoryServiceImpl implements ShopCategoryService {

    @Autowired
    ShopCategoryDao shopCategoryDao;

    @Override
    public List getShopCategoryList(ShopCategory shopCategoryCondition) {
        return shopCategoryDao.queryShopCategory(shopCategoryCondition);
    }

}

返回去写controller层的实现getShopInitInfo这个方法
很多controller都是这样
首先,写一个modelMap对象
然后就一个list来接收相关信息
然后就trycatch调用service的方法赋给上面的list,如果成功就把两个list放入moelMap,如果失败就把失败信息放入modelMap,最后在放回modelMap

package com.imooc.o2o.web.shopadmin;

@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
    @Autowired
    private ShopService shopService;
    @Autowired
    private ShopCategoryService shopCategoryService;
    @Autowired
    private AreaService areaService;
    
    /**
     * 获取区域以及店铺类别的信息将它返回给前台
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value="/getshopinitinfo", method=RequestMethod.GET)
    private Map getInitInfo(HttpServletRequest request){
        Map modelMap = new HashMap();
        List shopCategoryList = new ArrayList();
        List areaList = new ArrayList();
        try {
            shopCategoryList = shopCategoryService.getShopCategoryList(new ShopCategory());
            areaList = areaService.getAreaList();
            modelMap.put("shopCategoryList", shopCategoryList);
            modelMap.put("areaList", areaList);
            modelMap.put("success", true);
        }catch(Exception e) {
            modelMap.put("success", false);
            modelMap.put("errMsg", e.getMessage());
        }
        return modelMap;
        
    }
    
    
    /**
     * 获取前台表单信息并且转换为Shop实体类
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/registershop", method = RequestMethod.POST)
    private Map registerShop(HttpServletRequest request) {
        // 返回值
        Map modelMap = new HashMap();
        // 1、接收前端传过来的Shop字符串信息,包括店铺信息以及图片信息,并转换为shop实体类
        // shopStr是跟前端约定好的key值
        String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
        // 接收完成后需要做转换
        ObjectMapper mapper = new ObjectMapper();
        // 定义一个shop实体类去接收
        Shop shop = null;
        // 开始转换
        try {
            shop = mapper.readValue(shopStr, Shop.class);
        } catch (Exception e) {
            // 转换失败就返回modelMap,告诉前台说转换失败
            modelMap.put("success", false);
            modelMap.put("errMsg", e.getMessage());
            return modelMap;
        }
        // 接收图片
        CommonsMultipartFile shopImg = null;
        // 文件上传解析器,去解析request里面的文件信息
        // 从request本次会话的上下文中去获取相关文件上传的内容
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
                request.getSession().getServletContext());
        // 如果有上传的文件流
        //需要将request转换MultipartHttpServletRequest,这个对象就能够提取相对应的文件流
        //shopImg与前端约定
        if (commonsMultipartResolver.isMultipart(request)) {
            MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest)request;
            shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");
        }else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "上传图片不能为空");
            return modelMap;
        }
        // 2、注册店铺
        if(shop != null && shopImg != null) {
            //假定前端传过来的值是不可靠所以越少依赖前端的值越好
            //就拿店铺的实体类来说,onwer的信息可以从session获取而不用去前端获取
            PersonInfo owner = new PersonInfo();
            owner.setUserId(1L);
            shop.setOwner(owner);
            File shopImgFile = new File(PathUtil.getImgBasePath() + ImageUtil.getRandomFileName());
            try {
                shopImgFile.createNewFile();
            }catch(IOException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.getMessage());
                return modelMap;
            }
            try {
                inputStreamToFile(shopImg.getInputStream(), shopImgFile);
            }catch(IOException e) {
                modelMap.put("success", false);
                modelMap.put("errMsg", e.getMessage());
                return modelMap;
            }
            ShopExecution se = shopService.addShop(shop, shopImgFile);
            if(se.getState()==ShopStateEnum.CHECK.getState()) {
                modelMap.put("success", true);
            }else {
                modelMap.put("success", false);
                modelMap.put("errMsg", se.getStateInfo());
            }
            return modelMap;
            
        }else {
            modelMap.put("success", false);
            modelMap.put("errMsg", "店铺信息不能为空");
            return modelMap;
        }
    }
    
    //因为CommonsMultipartFile不能强制转换为File,但是它有InputStream方法
    //所以用InputStream来转换
    private static void inputStreamToFile(InputStream ins, File file) {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            while((bytesRead=ins.read(buffer))!=-1) {
                os.write(buffer, 0, bytesRead);
            }
        }catch(Exception e){
            throw new RuntimeException("调用inputStreamToFile产生异常" + e.getMessage());
        }finally{
            try {
                if(os!=null) {
                    os.close();
                }
                if(ins!=null) {
                    ins.close();
                }
            }catch(IOException e) {
                throw new RuntimeException("关闭inputStreamToFile产生异常" + e.getMessage());
            }
        }
    }
}

首先店铺是存储在二级id里面的,而不是首页的一级id,下面都是一级id


image.png

二级id


可以看到旧书籍交易信息店铺是在二级id二手书籍店铺类别下的


image.png

也就是说店铺所属的shopCategory的parentid是非空的,因为需要在


image.png

需要把new ShopCategory换成pardentid不为空的类别供店铺来选择
要更改的是mapper文件,要先判断传进来的参数是否为空,如果不为空那么它的parent_id也不能为空,如果为空就选出所有的类别来。
image.png

更写更合理的controller层

如果使用inputStringtofile转换为file,这样每次都得创建空文件,并且如果失败会有异常不稳定。所以需要修改,把inputStringtofile注释掉。并且把上面注册店铺包产该方法去掉。
就能减少Comm转换为file所带来的风险并且减少代码

验证码
引入jar包


image.png

引入jar包之后就需要在web.xml去编写它的一个servlet,这个servlet就负责去生成验证码


    
        Kaptcha
        com.google.core.Kaptcha.servlet.KaptchaServlet
        
        
            kaptcha.border
            no
        
        
        
            kaptcha.testproducer.font.color
            no
        
        
        
            kaptcha.image.width
            135
        
        
        
            kaptcha.testproducer.char.string
            ABCDEFGKPRSTWX345689
        
        
        
            kaptcha.image.height
            50
        
        
        
            kaptcha.testproducer.font.size
            43
        
        
        
            kaptcha.noise.color
            black
        
        
        
            kaptcha.textproducer.char.length
            4
        
        
        
            kaptcha.textproducer.font.names
            Arial
        
    

使用验证码

 
        
  • 验证码
    点击更换
  • 创建changeVerifyCode方法


    image.png

    在shopoperation.js接收验证码并且传进后台里面去。


    image.png

    将编写好的common.js引进html中

    编写servletMapping

    
            Kaptcha
            /Kaptcha
        
    

    把web.xml里的test改成text,然后启动服务器,验证码生成了,但是是黑色的。我们指定是红色的,发现text写错test了


    image.png

    然后希望不管提交成功还是失败反正提交之后就得刷新一次验证码,所以需要在shopoperation.js最后加上


    image.png

    前端编写完之后去编写后端,后端就是接收验证码去验证验证码,输入的验证码是否与图片验证码一样的。这里我们只验证大写,因为我们之前在web.xml里设置都是大写和数字,我们也需要输入大写,小写是会不成功匹配的,我们也可以在这个chek方法里加个判断小写条件就行了。


    image.png


    之后在controller层调用这个方法判断
    image.png

    总结:
    验证码的使用:
    1、首先导入jar包
    2、然后在web.xml定义servlet,这个servlet是为katcha做服务的,包括指定了样式,例如字体等等,同时设置servelt-mapping去相应katcha的请求。
    3、在shopoperation.html中以html的形式生成验证码,就是编写验证码的控件,然后再验证码控件的图片编写一个onclick方法,这个方法主要去调用验证码的servlet去生成新的验证码。
    4、生成之后当提交就在js里获取到,并且通过ajax传入到后台,然后在后端通过controller对验证码进行比对。

    前后端验证:

    打开tomcat的调试模式:
    然后访问我们的页面,打开调试工具之后打开sources里面找到js文件
    然后设置断点,然后输入所有字段,按f10进行按行调试判断是否js编写正确以至于获取到值。可以看到我们少写了#,并且ajax里的process写错,发现错误就回到代码去修改之后再刷新页面。


    image.png

    当前端调试完成后,按f8直接跳到后台,我们先在controller里设置断点,然后按f6按行调试,调试到验证验证码的时候就按f5进入,发现图片的验证码我们可以获取得到,但是我们自己输入的验证码却获取不到,原因是缺少处理文件流的mutilpartResolver就是你传入了文件流,我们的后台没有办法识别的到。这个项目的配置不是在web.xml,不然就是在spring-web.xml,在spring-web.xml里配置一个


    image.png

    之后再导入jar包去处理文件上传的类库
    image.png

    之后再debug启动服务器在测试就有了,之后一直调试到最后,它就会去添加,但是我这里还出现一个问题,就是水印的图片得方法resources文件下就好了。
    最后可以看到数据库数据的添加,文件里缩略图的生成。

    我们的店铺注册大概就做好,为什么说大概呢,因为还有很多没有实现,例如验证电话号码啊非空等等,还有验证码大小写。

    你可能感兴趣的:(注册店铺2)