文章目录
10 . 商品类别下拉选项实现 – 监听器实现(自动查询并存入全局对象中)
10.1 业务逻辑层 – 实现获取所有类别数据
创建ProductTypeService接口,定义获取所有类别数据方法getAll
package com.yanyu.service;
package ...
public interface ProductTypeService {
List<ProductType> getAll();
}
创建ProductTypeServiceImpl实现接口的所有类别数据方法getAll
package com.yanyu.service.impl;
import ...
@Service("ProductTypeServiceImpl")
public class ProductTypeServiceImpl implements ProductTypeService {
//数据访问层对象
@Autowired
ProductTypeMapper productTypeMapper;
@Override
public List<ProductType> getAll() {
return productTypeMapper.selectByExample(new ProductTypeExample());
}
}
10.2 通过监听器自动查询并存入全局对象中
spring容器的注册是通过监听器,与该对象是同一个监听器,无法确定谁先创建,所以无法使用spring的自动装配,需手动从Spring容器取出ProductTypeServiceImpl对象
package com.yanyu.listener;
import ...
@WebListener
public class ProductTypeListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//手动从Spring容器取出ProductTypeServiceImpl对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_*.xml");
ProductTypeService productTypeService = (ProductTypeService) context.getBean("ProductTypeServiceImpl");
List<ProductType> typeList = productTypeService.getAll();
//放入全局作用域中
sce.getServletContext().setAttribute("typeList",typeList);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
10.3 前端下拉框显示类别
<tr>
<td class="one">类别</td>
<td>
<select name="typeId">
<!--typeList后端传输的商品类别数据-->
<c:forEach items="${typeList}" var="type">
<option value="${type.typeId}">${type.typeName}</option>
</c:forEach>
</select>
</td>
</tr>
11. 上传文件 --ajax异步上传并回显 – springMVC组件
11.1 前端上传图片
文件选择
<tr>
<td class="three">图片介绍</td>
<!--ajax接收返回的图片位置并加载到imgDiv中-->
<td> <br><div id="imgDiv" style="display:block; width: 40px; height: 50px;"></div><br><br><br><br>
<!--选择文件,触发点击事件将文件传给Ajax异步上传-->
<input type="file" id="pimage" name="pimage" onchange="fileChange()" >
<span id="imgName" ></span><br>
</td>
Ajax异步提交事件 – 采用ajaxfileupload.js文件(封装ajax异步上传的功能)
<!-- 引入ajaxfileupload.js-->
<script type="text/javascript" src="${pageContext.request.contextPath }/js/ajaxfileupload.js"></script>
<script type="text/javascript">
function fileChange(){//注意:此处不能使用jQuery中的change事件,因此仅触发一次,因此使用标签的:onchange属性
$.ajaxFileUpload({
url: '/prod/ajaxImg.action',//用于文件上传的服务器端请求地址
secureuri: false,//是否需要安全协议一般设置为false
fileElementId: 'pimage',//文件上传控件的id属性 <input type="file" id="pimage" name="pimage" />
dataType: 'json',//返回值类型 一般设置为json
success: function(obj) //服务器成功响应处理函数
{
$("#imgDiv").empty(); //清空原有数据
//创建img 标签对象
var imgObj = $("<img>");
//给img标签对象追加属性
imgObj.attr("src","/image_big/"+obj.imgurl);
imgObj.attr("width","100px");
imgObj.attr("height","100px");
//将图片img标签追加到imgDiv末尾
$("#imgDiv").append(imgObj);
},
error: function (e)//服务器响应失败处理函数
{
alert(e.message);
}
});
}
</script>
11.2 在ProductInfoAction中添加异步Ajax文件上传处理
Ajax文件上传处理并返回含图片位置的json对象用于回显图片
//异步Ajax文件上传处理
@ResponseBody
@RequestMapping("/ajaxImg")
//pimage与前台上传的name值一样
public Object ajaxImg(MultipartFile pimage,HttpServletRequest request){
//生成文件名和后缀,通过FileNameUtil工具类将前台上传的文件名通过UUID重新生成,防止重复
String uuidFileName = FileNameUtil.getUUIDFileName()+FileNameUtil.getFileType(pimage.getOriginalFilename());
//存取路径 -- 完整的项目本地路径
String path = request.getServletContext().getRealPath("/image_big");
//存储 File.separator -> \
try {
pimage.transferTo(new File(path+File.separator+uuidFileName));
} catch (IOException e) {
e.printStackTrace();
}
//返回josn对象,包含图片路径,
String s = "{\"imgurl\":\""+uuidFileName+"\"}";
return s;
}
FileNameUtil工具类 – 用于UUID文件名防止重复
package com.yanyu.utils;
import java.util.UUID;
public class FileNameUtil {
//根据UUID生成文件名
public static String getUUIDFileName() {
UUID uuid = UUID.randomUUID();
return uuid.toString().replace("-", "");
}
//从请求头中提取文件名和类型
public static String getRealFileName(String context) {
// Content-Disposition: form-data; name="myfile"; filename="a_left.jpg"
int index = context.lastIndexOf("=");
String filename = context.substring(index + 2, context.length() - 1);
return filename;
}
//根据给定的文件名和后缀截取文件名
public static String getFileType(String fileName){
//9527s.jpg
int index = fileName.lastIndexOf(".");
return fileName.substring(index);
}
}
12 . 新增商品功能
12.1 业务逻辑层 – 实现新增商品
ProductInfoService接口添加save方法
//新增商品
int save(ProductInfo info);
ProductInfoServiceImpl实现类实现save
@Override
public int save(ProductInfo info) {
return productInfoMapper.insert(info);
}
12.2 界面控制层 – ProductInfoAtion中,添加save完成添加,返回初始页
@RequestMapping("/save")
public String save(ProductInfo info,HttpServletRequest request){
//文件由ajaxImg方法上传,将uuidFileName设置为全局变量,在此传递给数据库
info.setpImage(uuidFileName);
//前端提交的数据不包含时间,由后端添加
info.setpDate(new Date());
//num受影响行数
int num=0;
try {
num = productInfoService.save(info);
} catch (Exception e) {
e.printStackTrace();
}
if(num>0){
request.setAttribute("msg","增加成功!");
}else{
request.setAttribute("msg","增加失败!");
}
//转发到所有商品初始页
return "forward:/prod/split.action";
}
13. 更新商品
13.1 根据主键id查询商品,用于修改数据 - getById方法
业务逻辑层 – ProductInfoService接口添加getById方法
//按主键id查询商品
ProductInfo getById(int pid);
业务逻辑层 – ProductInfoServiceImpl实现类实现getById
@Override
public ProductInfo getById(int pid) {
return productInfoMapper.selectByPrimaryKey(pid);
}
界面控制层 – ProductInfoAtion中,添加one方法完成查询,返回修改页
@RequestMapping("one")
public String one(int pid, Model model){
ProductInfo byId = productInfoService.getById(pid);
model.addAttribute("prod",byId);
//更新时可以修改图片,防止数据冲突,清除uuidFileName
uuidFileName="";
return "update";
}
13.3 前端点击编辑,跳转one方法根据主键id查询所要修改的数据,回显
function one(pid) {
location.href = "${pageContext.request.contextPath}/prod/one.action?pid=" + pid;
}
....
<button type="button" class="btn btn-info " onclick="one(${p.pId})">编辑 </button>
13.3 更新前端页面 – 主要代码
//取消时返回初始页
<script type="text/javascript">
function myclose(ispage) { window.location="${pageContext.request.contextPath}/admin/product/split.action";
//window.close();
}
</script>
<div id="table">
<form action="${pageContext.request.contextPath}/prod/update.action" enctype="multipart/form-data" method="post" id="myform">
//修改根据id,所以要提交,但不修改用隐藏域
<input type="hidden" value="${prod.pId}" name="pId">
//用于判断是否重新上传图片
<input type="hidden" value="${prod.pImage}" name="pImage">
...
商品名称
商品介绍
定价
...
//显示图片和异步上传
<tr>
<td class="one">图片介绍</td>
<td> <br><div id="imgDiv" style="display:block; width: 40px; height: 50px;"><img src="/image_big/${prod.pImage}" width="100px" height="100px" ></div><br><br><br><br>
<input type="file" id="pimage" name="pimage" onchange="fileChange()">
<span id="imgName"></span><br>
</td>
</tr>
...
总数量
...
//取出全局中的数据,与修改商品的类别id对比,selected="selected"表示选中
<tr>
<td class="one">类别</td>
<td>
<select name="typeId">
<c:forEach items="${typeList}" var="type">
<option value="${type.typeId}"
<c:if test="${type.typeId==prod.typeId}">
selected="selected"
</c:if>
>${type.typeName}</option>
</c:forEach>
</select>
</td>
</tr>
<td>
<input type="submit" value="提交" class="btn btn-success">
</td>
<td>
<input type="reset" value="取消" class="btn btn-default" onclick="myclose(1)">
</td>
</tr>
</table>
</form>
</div>
13.4 修改数据 - update方法
业务逻辑层 – ProductInfoService接口添加update方法
//更新商品
int update(ProductInfo info);
业务逻辑层 – ProductInfoServiceImpl实现类实现update
@Override
public int update(ProductInfo info) {
return productInfoMapper.updateByPrimaryKey(info);
}
界面控制层 – ProductInfoAtion中,添加update完成更新
@RequestMapping("/update")
public String update(ProductInfo info,HttpServletRequest request){
//判断是否有重新上传的图片,若有则修改图片地址,没有不变
if(!uuidFileName.equals("")) {
info.setpImage(uuidFileName);
}
//num受影响行数
int num=0;
try {
num = productInfoService.update(info);
} catch (Exception e) {
e.printStackTrace();
}
if(num>0){
request.setAttribute("msg","更新成功!");
}else{
request.setAttribute("msg","更新失败!");
}
//转发到所有商品初始页
return "forward:/prod/split.action";
}