Java Web 网络商城案例演示二十
一、查询全部商品信息
步骤实现:
1、修改链接 left,jsp
${pageContext.request.contextPath}/AdminProductServlet?method=findAllProductsWithPage&num=1
2、AdminProductServlet—>findAllProductsWithPage
获取当前页
调用业务层功能查询全部商品信息
返回业务层全部商品信息返回PageModel
将PageModel放入request
转发到/admin/product/list.jsp
AdminProductServlet
public class AdminProductServlet extends BaseServlet {
// findAllProductsWithPage
public String findAllProductsWithPage(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 获取当前页
int curNum = Integer.parseInt(request.getParameter("num"));
// 调用业务层功能查询全部商品信息
// 返回业务层全部商品信息返回PageModel
ProductService productService = new ProductServiceImpl();
PageModel pm = productService.findAllProductsWithPage(curNum);
// 将PageModel放入request
request.setAttribute("page", pm);
// 转发到/admin/product/list.jsp
return "/admin/product/list.jsp";
}
}
二、上传商品信息
1、上传的准备工作
form method=“post”
form
form enctype=“multiprt/from-data”
2、上传协议格式
请求行
post/TestUpload/ServletDemo http/1.1
请求头
请求头
请求头
请求正文:
…multpart/form-data…;boundary=--------------544154484
ccontent-type:image/bmp
content-length:143214
.--------544154484
…name=“username”;
tom
.--------544154484
…name=“password”;
.--------544154484
1234
…name=“userhead”;filename=“11.bmp”
图片二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据二进制数据--------544154484
结论:
1、如果在表单当中设置了enctype=multipart/form-data属性之后,在服务端利用request.getParameter(name);无法获取到数据
原因:request.getParameter(name);获取的是请求体当中键值对的数据或者路径之后键值对的数据
http://localhost:8080/TestUpload/ServletDemo?username=tom
2、request.getInputStream();可以获取到请求体中全部的内容,理论上就可以利用这个API实现手动上传
3、利用工具来实现上传的思路commons-fileupload.jar commons-io.jar
(1)导入commons-fileupload.jar jar包
(2)执行很简单的3句话
(3)获取到一个集合(< FileItem >)
将每对分隔线中间的内容都分装在FileItem对象上
(4)遍历集合
(5)如果当前的FileItem对象是普通项
将普通项上的name属性的值作为键,将获取到的内容作为值,放入MAP集合当中
{username《=》tom,password《=》1234}
(6)如果当前的FileItem对象是上传项
通过FileItem获取到输入流对象,通过输入流可以获取到图片二进制数据,在服务端创建一个空文件(后缀必须和上传到服务端的文件名后缀一致)
建立和空文件对应输出流
将输入流中的数据刷到输出流当中
释放资源
向map中存入一个键值对的数据 userhead《==》/image/11.bmp
{username《=》tom,password《=》1234,userhead《=》image/11.bmp}
(7)利用BeanUtils将MAP中的数据填充到user对象上
(8)调用service dao将user上携带的数据仓库,重定向到查询全部商品信息路径上
问题:
1、如果文件重名发送覆盖问题
可以使用UUID
2、同目录下文件/目录过多,性能问题
在image下最多创建16个目录,任意一个目录进入之后最多创建16个目录,最多创建8层目录。
上传商品,添加商品
原理分析
步骤实现
1、页面跳转
准备工作
在/admin/product/list.jsp 修改了addProduct()函数当中链接
function addProduct() {
window.location.href = "${pageContext.request.contextPath}/AdminProductServlet?method=addProductUI";
}
/admin/product/add.jsp 遍历分类信息
2、实现上传
(1)准备工作:
设置form表单 :method=post enctype="multipart/form-data "
<form id="userAction_save_do" name="Form1" action="${pageContext.request.contextPath}/AddProductServlet?method=addProduct" method="post" enctype="multipart/form-data">
(2)确定form标签下各个组件的name属性的值保持合法一致。
/admin/product/addl.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<HTML>
<HEAD>
<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<LINK href="${pageContext.request.contextPath}/css/Style1.css" type="text/css" rel="stylesheet">
</HEAD>
<body>
<form id="userAction_save_do" name="Form1" action="${pageContext.request.contextPath}/AdminProductServlet?method=addProduct" method="post" enctype="multipart/form-data">
<table cellSpacing="1" cellPadding="5" width="100%" align="center" bgColor="#eeeeee" style="border: 1px solid #8ba7e3" border="0">
<tr>
<td class="ta_01" align="center" bgColor="#afd1f3" colSpan="4"
height="26">
<STRONG>添加商品</STRONG>
</td>
</tr>
<tr>
<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
商品名称:
</td>
<td class="ta_01" bgColor="#ffffff">
<input type="text" name="pname" value="" id="userAction_save_do_logonName" class="bg"/>
</td>
<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
是否热门:
</td>
<td class="ta_01" bgColor="#ffffff">
<select name="is_hot">
<option value="1">是</option>
<option value="0">否</option>
</select>
</td>
</tr>
<tr>
<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
市场价格:
</td>
<td class="ta_01" bgColor="#ffffff">
<input type="text" name="market_price" value="" id="userAction_save_do_logonName" class="bg"/>
</td>
<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
商城价格:
</td>
<td class="ta_01" bgColor="#ffffff">
<input type="text" name="shop_price" value="" id="userAction_save_do_logonName" class="bg"/>
</td>
</tr>
<tr>
<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
商品图片:
</td>
<td class="ta_01" bgColor="#ffffff" colspan="3">
<input type="file" name="pimage" />
</td>
</tr>
<tr>
<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
所属的分类:
</td>
<td class="ta_01" bgColor="#ffffff" colspan="3">
<select name="cid">
<c:forEach items="allCats" var="c">
<option value="${c.cid }">${c.cname }</option>
</c:forEach>
</select>
</td>
</tr>
<tr>
<td width="18%" align="center" bgColor="#f5fafe" class="ta_01">
商品描述:
</td>
<td class="ta_01" bgColor="#ffffff" colspan="3">
<textarea name="pdesc" rows="5" cols="30"></textarea>
</td>
</tr>
<tr>
<td class="ta_01" style="WIDTH: 100%" align="center" bgColor="#f5fafe" colSpan="4">
<button type="submit" id="userAction_save_do_submit" value="确定" class="button_ok">
确定
</button>
<FONT face="宋体"> </FONT>
<button type="reset" value="重置" class="button_cancel">重置</button>
<FONT face="宋体"> </FONT>
<INPUT class="button_ok" type="button" onclick="history.go(-1)" value="返回"/>
<span id="Label1"></span>
</td>
</tr>
</table>
</form>
</body>
</HTML>
(3)AdminProductServlet当中addProduct
导入相关jar包
使用工具类生成目录
一下工具类生成一个随机的目录结构
package cn.itzheng.store.utils;
import java.util.UUID;
public class UploadUtils {
/**
* 获取随机名称
*
* @param realName 真实名称
* @return uuid
*/
public static String getUUIDName(String realName) {
// realname 可能是 1.jpg 也可能是 1
// 获取后缀名
int index = realName.lastIndexOf(".");//获取到.所在的位置
if (index == -1) {//判断获取到的.是否为-1,也就是文件是否是没有后缀的
return UUID.randomUUID().toString().replace("-", "").toUpperCase();
} else {
return UUIDUtils.getId()+ realName.substring(index);//通过位置获取到对应.后面的名称在加上前面生成的对应随机的名称
}
}
/**
* 获取文件真实名称
*
* @param name
* @return
*/
public static String getRealName(String name) {
// c:/upload/1.jpg 1.jpg
// 获取最后一个"/"
int index = name.lastIndexOf("\\");
return name.substring(index + 1);
}
/**
* 获取文件目录
*
* @param name 文件名称
* @return 目录
*/
public static String getDir(String name) {
//任意的一个对象都有一个hash码
int i = name.hashCode();
System.out.println(i);
//将hash码转成16进制的字符串//-1351534400--->af7138c0
String hex = Integer.toHexString(i);
System.out.println(hex);
int j = hex.length();
for (int k = 0; k < 8 - j; k++) {
hex = "0" + hex;
}
return "/" + hex.charAt(0) + "/" + hex.charAt(1) + "/" + hex.charAt(2) + "/" + hex.charAt(3) + "/"
+ hex.charAt(4) + "/" + hex.charAt(5) + "/" + hex.charAt(6) + "/" + hex.charAt(7);
}
@SuppressWarnings("unused")
public static void main(String[] args) {
// String s="G:\\day17-基础加强\\resource\\1.jpg";
//String s = "1.jgp";
// realName = getRealName(s);
// System.out.println(realName);
//String uuidName = getUUIDName(realName);
// System.out.println(uuidName);
//调用该函数生成一个随机的目录结构
String dir = getDir("AAAAAAAAAAAA");
///a/f/7/1/3/8/c/0
System.out.println(dir);
}
}
AdminProductServlet–》addProduct方法当中
// addProduct
public String addProduct(HttpServletRequest request, HttpServletResponse response) throws Exception {
// map存储表单当中数据
Map<String, String> map = new HashMap<String, String>();
// 携带表单中的数据向service,dao
Product product = new Product();
try {
// 利用request.getInputStream();获取到请求体中全部的数据,进行拆分和封装
// DiskFileItemFactory 磁盘文件项工厂
DiskFileItemFactory fac = new DiskFileItemFactory();
// ServletFileUpload服务器文件上载
ServletFileUpload upload = new ServletFileUpload(fac);
// 转换request,将其中从页面传入的数据list当中放入的是文件对应的项目数据
List<FileItem> list = upload.parseRequest(request);
// 遍历集合
for (FileItem item : list) {
if (item.isFormField()) {
// 如果当前的FileItem对象是普通项
// 将普通项上的name属性的值作为键,将获取到的内容作为值,放入MAP集合当中
// {username《=》tom,password《=》1234}
// 获取到每一个普通项将其放入到map集合当中
map.put(item.getFieldName(), item.getString("utf-8"));
} else {//
// 如果当前的FileItem对象是上传项(将文件从页面上刷入到系统当中,并且将其对应的路径放入到map集合当中)
// 获取到原始的文件名称
String oldFileName = item.getName();// 获取到上传的文件的名称
// 生成一个随机的新的名称就是要保存文件的名称 1222.doc 21511151.doc
String newFileName = UploadUtils.getUUIDName(oldFileName);
// 通过FileItem获取到输入流对象,通过输入流可以获取到图片二进制数据,在服务端创建一个空文件(后缀必须和上传到服务端的文件名后缀一致)
InputStream is = item.getInputStream();
// 获取到当前项目下products/3下的一个真实的路径//D:\tomcat\webapps\store_v5\products\3
String realpath = getServletContext().getRealPath("/products/3/");
// 生成一个随机的目录结构
String dir = UploadUtils.getDir(newFileName);// dir ===> /a/f/7/1/3/8/c/0
String path = realpath + dir;// D:\tomcat\webapps\store_v5\products\3 + /a/f/7/1/3/8/c/0
// 内存当中去声明一个目录
File newDir = new File(path);
if (!newDir.exists()) {
newDir.mkdirs();// 创建newDir对应路径的目录
}
// 在服务器上创建一个空文件(后缀必须和上传到服务端的文件名称的后缀一致)
File finalFile = new File(newDir, newFileName);
if (!finalFile.exists()) {
finalFile.createNewFile();// 在newDir对应目录的结构当中创建newFileName对应名称的文件
}
// 建立和空文件对应输出流
OutputStream os = new FileOutputStream(finalFile);
// 将输入流中的数据刷到输出流当中
IOUtils.copy(is, os);
// 释放资源
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
// 向map中存入一个键值对的数据 userhead《==》/image/11.bmp
// {username《=》tom,password《=》1234,userhead《=》image/11.bmp}
// 在map集合当中放入对应的pimage键和值就是图片路径
map.put("pimage", "/products/3/" + dir + "/" + newFileName);
}
}
// 利用BeanUtils将MAP中的数据填充到Product对象上
BeanUtils.populate(product, map);
product.setPid(UUIDUtils.getId());
product.setPdate(new Date());
product.setPflag(0);
// 调用service dao将user上携带的数据仓库,重定向到查询全部商品信息路径上
ProductService productService = new ProductServiceImpl();
productService.saveProduct(product);
response.sendRedirect("/store_v5/AdminProductServlet?method=findAllProductsWithPage&num=1");
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
ProductService
void saveProduct(Product product) throws Exception;
ProductServiceImpl
@Override
public void saveProduct(Product product) throws Exception {
productDao.saveProduct(product);
}
ProductDao
void saveProduct(Product product) throws Exception;
ProductDaoImpl
@Override
public void saveProduct(Product product) throws Exception {
// TODO Auto-generated method stub
String sql = "INSERT INTO product VALUES(?,?,?,?,?,?,?,?,?,?)";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
Object[] params = { product.getPid(), product.getPname(), product.getMarket_price(), product.getShop_price(),
product.getPimage(), product.getPdate(), product.getIs_hot(), product.getPdesc(), product.getPflag(),
product.getCid() };
qr.update(sql, params);
}