商品用例的bean层

添加商品的用例实现首先要有封装商品的bean,还要有封装商品种类的bean。

封装商品种类的bean

14.商品添加功能_Java14.商品添加功能_Java_02
package cn.bingou.domain;

/**
 * 商品种类的bean
 * @author 吹静静
 *
 */
public class ProdCategory {
    
    private int id;
    private String cname;
    public ProdCategory() {
        super();
        // TODO Auto-generated constructor stub
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    @Override
    public String toString() {
        return "ProdCategory [id=" + id + ", cname=" + cname + "]";
    }
}
ProdCategory

封装商品的的bean

14.商品添加功能_Java14.商品添加功能_Java_02
package cn.bingou.domain;

/**
 * 商品的bean
 * @author 吹静静
 *
 */
public class Prod {

    private int id;
    private String name;
    private double price;
    private int cid;
    private String cname;//商品名称
    private int pnum;
    private String imgurl;
    private String description;
    
    public Prod(){
        
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getCid() {
        return cid;
    }

    public void setCid(int cid) {
        this.cid = cid;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public int getPnum() {
        return pnum;
    }

    public void setPnum(int pnum) {
        this.pnum = pnum;
    }

    public String getImgurl() {
        return imgurl;
    }

    public void setImgurl(String imgurl) {
        this.imgurl = imgurl;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Prod [id=" + id + ", name=" + name + ", price=" + price
                + ", cid=" + cid + ", cname=" + cname + ", pnum=" + pnum
                + ", imgurl=" + imgurl + ", description=" + description + "]";
    }
    
}
Prod

商品用例的web层

web层主要包括一些表单验证代码,文件上传的代码。

14.商品添加功能_Java14.商品添加功能_Java_02
package cn.bingou.backend.web;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import cn.bingou.domain.Prod;
import cn.bingou.factory.BaseFactory;
import cn.bingou.service.ProdService;

public class ManageAddProdServlet extends HttpServlet {

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        // 获取ServletContext对象
        ServletContext sc = this.getServletContext();
        String encode = sc.getInitParameter("encode");
        
        // 声明临时文件夹和上传文件夹的相对路径
        String tempPath="/WEB-INF/temp";
        String uploadPath="/WEB-INF/upload";
        
        // 声明一个用于保存普通表单项数据的map集合
        Map<String,String> pMap = new HashMap<String,String>();
        
        // 声明一个变量,保存商品的实际url
        String imgurl = null;
        // 1.接收表单请求
        // 2.表单验证
        
        // 借助commons-fileupload.jar
        DiskFileItemFactory factory=new DiskFileItemFactory(1024*1024,new File(sc.getRealPath(tempPath)));
        ServletFileUpload fileUpload=new ServletFileUpload(factory);
        if(!fileUpload.isMultipartContent(req)){
            throw new RuntimeException("请使用正确的文件上传表单");
        }
        // 设置单个文件的大小
        fileUpload.setFileSizeMax(1024*1024); // 10KB
        // 设置一次上传的文件的总大小
        fileUpload.setFileSizeMax(1024*1024); // 1MB
        
        // 解决上传文件名乱码问题
        fileUpload.setHeaderEncoding(encode);
        try{
            // 解析请求
            @SuppressWarnings("unchecked")
            List<FileItem> list = fileUpload.parseRequest(req);
            if(list != null){
                for(FileItem fileItem:list){
                    if(fileItem.isFormField()){
                        // 普通表单
                        String name = fileItem.getFieldName();
                        String value = fileItem.getString(encode);
                        // 将普通表单项数据添加到pMap集合中
                        pMap.put(name, value);
                    }else{
                        // 3.将上传图片保存到相应位置
                        // 文件上传项
                        String filename = fileItem.getName();
                        
                        // 解决IE浏览器的BUG
                        if(filename.contains("\\")){
                            filename = filename.substring(filename.lastIndexOf("\\")+1);
                        }
                        // 文件名重复问题
                        filename = UUID.randomUUID().toString()+"_"+filename;
                        
                        // 文件路径问题
                        String hexStr = Integer.toHexString(filename.hashCode());
                        
                        // 不足8位
                        while(hexStr.length()<8){
                            hexStr = "0" + hexStr;
                        }
                        
                        // 拆分成路径
                        String midPath = "/";
                        for(int i=0; i<hexStr.length(); i++){
                            midPath += hexStr.charAt(i)+"/";
                        }
                        
                        // /WEB-INF/upload/a/b/c/d/1/2/3/4/1231231.jpg
                        imgurl = uploadPath + midPath + filename;
                        // 生成目录
                        // d:/web/workspace/easymall/webroot/....
                        uploadPath = sc.getRealPath(uploadPath + midPath);
                        new File(uploadPath).mkdirs();
                        
                        // 将文件保存到目标目录
                        InputStream is = fileItem.getInputStream();
                        FileOutputStream fos = null;
                        try{
                            fos = new FileOutputStream(uploadPath + "/" + filename);
                            byte[] array = new byte[1024];
                            int len = is.read(array);
                            while(len != -1){
                                fos.write(array,0,len);
                                len = is.read(array);
                            }
                            
                        }catch (Exception e) {
                            e.printStackTrace();
                            throw new RuntimeException("商品图片上传失败");
                        }finally{
                            is.close();
                            fos.close();
                            // 删除临时文件
                            fileItem.delete();
                        }
                    }
                }
            }
        }catch (FileUploadException e) {
            e.printStackTrace();
        }
        
        // 4.调用Service执行逻辑
        ProdService service = BaseFactory.getFactory().getInstance(ProdService.class);
        // 创建一个JavaBean, 封装本次表单提交的商品信息
        Prod prod = new Prod();
        // 从pMap中获取普通表单项数据,添加到prod对象中
        prod.setName(pMap.get("name"));
        prod.setPrice(Double.parseDouble(pMap.get("price")));
        prod.setCname(pMap.get("cname"));
        prod.setPnum(Integer.parseInt(pMap.get("pnum")));
        // 保存商品图片的url,相对于当前应用的路径
        prod.setImgurl(imgurl);
        prod.setDescription(pMap.get("description"));
        System.out.println(prod);
        
        boolean flag = service.addProd(prod);
        // 5.根据执行的结果转发对应的视图
        if(flag){
            // 成功:提示成功信息,定时刷新到后台首页
            resp.getWriter().write("<h1 style='text-align:center;color:red'>商品添加成功,3秒后自动跳转首页</h1>");
            resp.setHeader("refresh", "3;url="+req.getContextPath()+"/backend/_right.jsp");
        }else{
            //2)失败:添加错误提示信息,转发添加商品页面
            req.setAttribute("errMsg", "商品添加失败");
            req.getRequestDispatcher("/backend/manageAddProd.jsp").forward(req, resp);
        }    
    }

    public void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }
}
ManageAddProdServlet

14.商品添加功能_Java_0714.商品添加功能_Java_08

文件上传的解决方案

上传地址:/WEB-INF/upload......

上传文件夹过大问题:16进制问文件夹

        // 2.表单验证
        // 借助commons-fileupload.jar
        DiskFileItemFactory factory=new DiskFileItemFactory(1024*1024,new File(sc.getRealPath(tempPath)));
        ServletFileUpload fileUpload=new ServletFileUpload(factory);
        if(!fileUpload.isMultipartContent(req)){
            throw new RuntimeException("请使用正确的文件上传表单");
        }

fileUpload.isMultipartContent(req)用于判断是普通表单,还是带文件上传的表单。
  在 fileupload 包中, HTTP 请求中的复杂表单元素都被看做一个 FileItem 对象;

FileItem 对象必须由 ServletFileUpload 类中的 parseRequest() 方法解析 HTTP 请求(即被包装之后的 HttpServletRequest 对象)出来,

即分离出具体的文本表单和上传文件;而 ServletFileUpload 对象的创建需要依赖于 FileItemFactory 工厂将获得的上传文件 FileItem 对象保存至服务器硬盘,即 DiskFileItem 对象。

商品用例的service层

14.商品添加功能_Java14.商品添加功能_Java_02
package cn.bingou.service;

import cn.bingou.domain.Prod;

public interface ProdService {
    /**
     * 添加商品的方法
     * @param prod 封装了商品信息的Bean
     * @return true-添加成功 false-添加失败
     */
    boolean addProd(Prod prod);
}
ProdService
14.商品添加功能_Java14.商品添加功能_Java_02
package cn.bingou.service;

import cn.bingou.dao.ProdDao;
import cn.bingou.domain.Prod;
import cn.bingou.domain.ProdCategory;
import cn.bingou.exception.MsgException;
import cn.bingou.factory.BaseFactory;

public class ProdServiceImpl implements ProdService {

    private ProdDao dao = BaseFactory.getFactory().getInstance(ProdDao.class);
    
    @Override
    public boolean addProd(Prod prod) {
        // 查询数据库,确认是否已经存在该商品种类
        int cid = -1;
        try {
            cid = dao.getCidByCname(prod.getCname());
        } catch (MsgException e) {
            e.printStackTrace();
            return false;
        }
        // 如果没有这个商品种类
        if(cid == -1){
            // 创建ProdCategory对象,封装要添加的数据
            ProdCategory pc = new ProdCategory();
            pc.setCname(prod.getCname());
            // 1)先添加这个商品种类
            boolean flag = dao.insertPC(pc);
            if(flag == false){ // 添加商品失败
                return false;
            }
            // 2)再次查询cid,获取数据库中最新生成的cid
            try {
                cid = dao.getCidByCname(prod.getCname());
            } catch (MsgException e) {
                e.printStackTrace();
                return false;
            }
        }
        
        // 将查询到的cid添加到prod对象中
        prod.setCid(cid);
        // 添加商品
        boolean flag = dao.insertProd(prod);
        
        return flag;
    }
}
ProdServiceImpl

 

商品用例的dao层

14.商品添加功能_Java14.商品添加功能_Java_02
package cn.bingou.dao;

import cn.bingou.domain.Prod;
import cn.bingou.domain.ProdCategory;
import cn.bingou.exception.MsgException;

public interface ProdDao {
    
    /**
     * 根据商品种类名称查询商品种类id的方法
     * @param cname 商品种类名称
     * @return 商品种类的id 或 -1
     * @throws 封装了自定义消息的异常对象
     */
    int getCidByCname(String cname) throws MsgException;

    /**
     * 添加商品种类的方法
     * @param pc 封装了商品种类信息的JavaBean
     * @return true-添加成功 false-添加失败
     */
    boolean insertPC(ProdCategory pc);

    /**
     * 添加商品信息的方法
     * @param prod 封装了商品信息的JavaBean
     * @return true-添加成功 false-添加失败
     */
    boolean insertProd(Prod prod);
}
ProdDao
14.商品添加功能_Java14.商品添加功能_Java_02
package cn.bingou.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import cn.bingou.domain.Prod;
import cn.bingou.domain.ProdCategory;
import cn.bingou.exception.MsgException;
import cn.bingou.util.JDBCUtils;

public class ProdDaoImpl implements ProdDao {

    @Override
    public int getCidByCname(String cname) throws MsgException {
        String sql="select id from prod_category where cname=?";
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            conn=JDBCUtils.getConnection();
            ps=conn.prepareStatement(sql);
            ps.setString(1, cname);
            rs=ps.executeQuery();
            if(rs.next()){
                // 说明存在该条商品种类记录
                return rs.getInt("id");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new MsgException("查询商品种类时出现异常");
        }finally{
            JDBCUtils.close(conn, ps, rs);
        }
        return -1;
    }

    @Override
    public boolean insertPC(ProdCategory pc) {
        String sql="insert into prod_category values(null,?)";
        Connection conn=null;
        PreparedStatement ps=null;
        try {
            conn=JDBCUtils.getConnection();
            ps=conn.prepareStatement(sql);
            ps.setString(1, pc.getCname());
            int i=ps.executeUpdate();
            if(i>0){
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.close(conn, ps, null);
        }
        return false;
    }

    @Override
    public boolean insertProd(Prod prod) {
        String sql="insert into prod values(null,?,?,?,?,?,?)";
        Connection conn=null;
        PreparedStatement ps=null;
        try {
            conn=JDBCUtils.getConnection();
            ps=conn.prepareStatement(sql);
            ps.setString(1, prod.getName());
            ps.setDouble(2, prod.getPrice());
            ps.setInt(3, prod.getCid());
            ps.setInt(4, prod.getPnum());
            ps.setString(5, prod.getImgurl());
            ps.setString(6, prod.getDescription());
            int i=ps.executeUpdate();
            if(i>0){
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.close(conn, ps, null);
        }
        return false;
    }
}
ProdDaoImpl

14.商品添加功能_Java_17

需要导入的jar包

14.商品添加功能_Java_1814.商品添加功能_Java_19

config.properties配置文件

UserDao=cn.bingou.dao.UserDaoImpl
UserService=cn.bingou.service.UserServiceImpl
ProdService=cn.bingou.service.ProdServiceImpl
ProdDao=cn.bingou.dao.ProdDaoImpl

遇到的BUG

1.properties配置文件和代码里面的调用不一致

2.该了web层代码包名后要修改web.xml配置文件的配置