淘淘商城系列——实现添加商品功能

来源:互联网 发布:中世纪2优化9血统玩法 编辑:程序博客网 时间:2024/05/16 12:39

经过上文的学习,我相信大家都知道富文本编辑器的使用方法了,我们能走到这步,实属不易,本文终于可以来实现商品添加这个功能了。
在item-add.jsp页面当中,当点击提交按钮后,会触发submitForm方法,如下图所示。
这里写图片描述
在提交表单前需要校验输入的内容是否合法,如下图所示。
这里写图片描述
下面我们看下数据库中商品表的建表信息,可以看到价格定义的字段类型是long型,单位为分,之所以这样做是为了避免使用小数点,因为小数点使用起来比较麻烦,因此存到数据库商品表中的价格都是价格(用户输入价格时一般都是喜以元为单位,难道不是这样吗?)乘以100的(变为分)。
这里写图片描述
我们发现在商品表当中没有商品描述这个字段,怎么会没有呢?其实商品描述是专门用一张表来存放的,如下图所示。可以看到商品描述与商品ID是一一对应的,之所以把商品描述单独放到一张表当中是因为它是个大文本字段,存储的信息量会非常大,对于不需要商品描述的查询情况来说连带这个字段查询会影响查询效率,因此单独存放。
这里写图片描述
我们看看表单中是如何表示的,如下图所示,可以看到有两个<input>组件,第一个用来展示商品的价格,即单位为元的价格(这更符合用户的习惯),第二个<input>是个隐藏域,专门用来存放以分为单位的价格(即将以元为单位的价格乘以100),表单提交时便会提交name=”price”的价格并保存到数据库表中。
这里写图片描述
当用户填写完商品详细信息后,提交表单时会请求”/item/save”的url,第二个参数$("#itemAddForm").serialize()是用来将表单的数据序列化为key-value形式的字符串,如果表单提交成功应该返回200的状态码,如下所示。
这里写图片描述
由于每个操作都需要有状态码(status)来表示操作成功与否以及相关信息,因此我们定义一个TaotaoResult类来专门处理,该类定义三个属性,分别是状态、消息及数据,由于这个类会被多个工程所使用,因此放到taotao-common工程的com.taotao.common.pojo包下。
这里写图片描述
TaotaoResult类的全部代码如下,里面最常用的便是ok方法和build方法。

/** * 淘淘商城自定义响应结构 */public class TaotaoResult implements Serializable {    // 定义jackson对象    private static final ObjectMapper MAPPER = new ObjectMapper();    // 响应业务状态    private Integer status;    // 响应消息    private String msg;    // 响应中的数据    private Object data;    public static TaotaoResult build(Integer status, String msg, Object data) {        return new TaotaoResult(status, msg, data);    }    public static TaotaoResult ok(Object data) {        return new TaotaoResult(data);    }    public static TaotaoResult ok() {        return new TaotaoResult(null);    }    public TaotaoResult() {    }    public static TaotaoResult build(Integer status, String msg) {        return new TaotaoResult(status, msg, null);    }    public TaotaoResult(Integer status, String msg, Object data) {        this.status = status;        this.msg = msg;        this.data = data;    }    public TaotaoResult(Object data) {        this.status = 200;        this.msg = "OK";        this.data = data;    }//    public Boolean isOK() {//        return this.status == 200;//    }    public Integer getStatus() {        return status;    }    public void setStatus(Integer status) {        this.status = status;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    public Object getData() {        return data;    }    public void setData(Object data) {        this.data = data;    }    /**     * 将json结果集转化为TaotaoResult对象     *      * @param jsonData json数据     * @param clazz TaotaoResult中的object类型     * @return     */    public static TaotaoResult formatToPojo(String jsonData, Class<?> clazz) {        try {            if (clazz == null) {                return MAPPER.readValue(jsonData, TaotaoResult.class);            }            JsonNode jsonNode = MAPPER.readTree(jsonData);            JsonNode data = jsonNode.get("data");            Object obj = null;            if (clazz != null) {                if (data.isObject()) {                    obj = MAPPER.readValue(data.traverse(), clazz);                } else if (data.isTextual()) {                    obj = MAPPER.readValue(data.asText(), clazz);                }            }            return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);        } catch (Exception e) {            return null;        }    }    /**     * 没有object对象的转化     *      * @param json     * @return     */    public static TaotaoResult format(String json) {        try {            return MAPPER.readValue(json, TaotaoResult.class);        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    /**     * Object是集合转化     *      * @param jsonData json数据     * @param clazz 集合中的类型     * @return     */    public static TaotaoResult formatToList(String jsonData, Class<?> clazz) {        try {            JsonNode jsonNode = MAPPER.readTree(jsonData);            JsonNode data = jsonNode.get("data");            Object obj = null;            if (data.isArray() && data.size() > 0) {                obj = MAPPER.readValue(data.traverse(),                        MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));            }            return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);        } catch (Exception e) {            return null;        }    }}

注意,TaotaoResult类一定要实现序列化接口,很多人都会忘记哟!!!
添加商品和商品描述对应的都是单表操作,因此我们使用逆向工程生成的代码即可,也就是说我们不用写Dao层的代码。下面我们重点来写Service层的代码,首先在ItemService接口当中添加一个”添加商品”的方法(这一个方法要操作两张表,一张是商品表,另一张是商品描述表)。如下图所示,参数有两个,一个是代表商品表的pojo,另一个是商品描述。
这里写图片描述
下面我们到Service层来实现这个接口,如下图所示,我们在ItemServiceImpl实现类当中实现了addItem方法,其中商品ID(也叫商品编号)是采用当前毫秒数加两位随机数来生成的,为了方便以后调用,我们专门封装了一个叫做IDUtils的工具类,里面不仅封装了商品ID的生成方法还封装了图片名称的生成方法,由于该类会被多个工程使用,因此我们也放到taotao-common工程的com.taotao.common.utils包下。
这里写图片描述
为了方便大家复制,现将ItemServiceImpl实现类的代码贴出。

/** * 商品管理Service * <p>Title: ItemServiceImpl</p> * <p>Description: </p> * <p>Company: www.itcast.cn</p>  * @version 1.0 */@Servicepublic class ItemServiceImpl implements ItemService {    @Autowired    private TbItemMapper itemMapper;    @Autowired    private TbItemDescMapper itemDescMapper;    @Override    public TbItem getItemById(long itemId) {        TbItem item = itemMapper.selectByPrimaryKey(itemId);        return item;    }    @Override    public EasyUIDataGridResult getItemList(int page, int rows) {        // 分页处理        PageHelper.startPage(page, rows);        // 执行查询        TbItemExample example = new TbItemExample();        List<TbItem> list = itemMapper.selectByExample(example);        // 创建返回结果对象        EasyUIDataGridResult result = new EasyUIDataGridResult();        result.setRows(list);        // 取总记录数        PageInfo<TbItem> pageInfo = new PageInfo<TbItem>(list);        result.setTotal(pageInfo.getTotal());        return result;    }    @Override    public TaotaoResult addItem(TbItem item, String desc) {        // 先生成商品id        long itemId = IDUtils.genItemId();        item.setId(itemId);        // 商品状态,1-正常,2-下架,3-删除        item.setStatus((byte) 1);        Date date = new Date();        item.setCreated(date);        item.setUpdated(date);        // 插入到商品表        itemMapper.insert(item);        // 商品描述        TbItemDesc itemDesc = new TbItemDesc();        itemDesc.setItemId(itemId);        itemDesc.setItemDesc(desc);        itemDesc.setCreated(date);        itemDesc.setUpdated(date);        // 插入商品描述        itemDescMapper.insert(itemDesc);        return TaotaoResult.ok();    }}

同样也将IDUtils工具类的代码给出。

/** * 各种id生成策略 * <p>Title: IDUtils</p> * <p>Description: </p> * <p>Company: www.itcast.com</p>  * @author  入云龙 * @date    2015年7月22日下午2:32:10 * @version 1.0 */public class IDUtils {    /**     * 图片名生成     */    public static String genImageName() {        //取当前时间的长整形值包含毫秒        long millis = System.currentTimeMillis();        //long millis = System.nanoTime();        //加上三位随机数        Random random = new Random();        int end3 = random.nextInt(999);        //如果不足三位前面补0        String str = millis + String.format("%03d", end3);        return str;    }    /**     * 商品id生成     */    public static long genItemId() {        //取当前时间的长整形值包含毫秒        long millis = System.currentTimeMillis();        //long millis = System.nanoTime();        //加上两位随机数        Random random = new Random();        int end2 = random.nextInt(99);        //如果不足两位前面补0        String str = millis + String.format("%02d", end2);        long id = new Long(str);        return id;    }    public static void main(String[] args) {        for(int i=0;i< 100;i++)        System.out.println(genItemId());    }}

接下来我们来编写Controller层,我们在ItemController类中添加addItem方法,其中@RequestMapping("/item/save")注解中的url请求路径是在item-add.jsp页面的js代码当中定义好的,我们要保持一致才行。
这里写图片描述
下面我们便来测试我们的添加商品功能是否好使,由于taotao-common工程以及taotao-manager工程都做了修改,因此我们需要对这两个工程重新打包,如何打包在此不再赘述。
最后,我们重启taotao-manager工程和taotao-manager-web工程,启动完工程之后,我们到新增商品页面,输入相关表单信息,然后点击”提交”按钮。
这里写图片描述
我们会发现弹出一个提示框,提示我们添加成功,添加完之后,我们到商品列表中去查询,看是否有我们刚才添加的商品,我们直接查看最后一页的数据,发现最后一条就是刚才添加的商品信息,这已说明添加商品成功了。
这里写图片描述
我们再到数据库表中看看添加的商品信息,首先看tb_item表,我们还是到最后一页去查看,发现有刚才添加的信息,如下图所示。
这里写图片描述
再看商品描述表,我们可通过商品ID来快速筛选出添加的商品信息描述,如下图所示。
这里写图片描述
这说明数据存储完全没问题。这样,我们的商品添加功能便实现了。