<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
1.1分页插件用法
pageInfo用来存储分页所需的各种信息
//传入相应的值
PageHelper.startPage(pageNum,pageSize);
//设置完排序后,取集合,切记切记,一定在取集合之前,设置pageHelper.startPage(pageNum,pageSize)
List<ProductInfo> list = productInfoMapper.selectByExample(example);
//将查询到的集合封装进PageInfo对象中
PageInfo<ProductInfo> pageInfo = new PageInfo<>(list);
1.2界面代码
<div id="middle">
<table class="table table-bordered table-striped">
<tr>
<th>th>
<th>商品名th>
<th>商品介绍th>
<th>定价(元)th>
<th>商品图片th>
<th>商品数量th>
<th> *** 作th>
tr>
<c:forEach items="${info.list}" var="p">
<tr>
<td valign="center" align="center"><input type="checkbox" name="ck" id="ck" value="${p.pId}" onclick="ckClick()">td>
<td>${p.pName}td>
<td>${p.pContent}td>
<td>${p.pPrice}td>
<td><img width="55px" height="45px"
src="${pageContext.request.contextPath}/image_big/${p.pImage}">td>
<td>${p.pNumber}td>
<%--<td><a href="${pageContext.request.contextPath}/admin/product?flag=delete&pid=${p.pId}" onclick="return confirm('确定删除吗?')">删除a>--%>
<%-- <a href="${pageContext.request.contextPath}/admin/product?flag=one&pid=${p.pId}">修改a>td>--%>
<td>
<button type="button" class="btn btn-info "
onclick="one(${p.pId},${info.pageNum})">编辑
button>
<button type="button" class="btn btn-warning" id="mydel"
onclick="del(${p.pId})">删除
button>
td>
tr>
c:forEach>
table>
<div id="bottom">
<div>
<nav aria-label="..." style="text-align:center;">
<ul class="pagination">
<li>
<a href="javascript:ajaxsplit(${info.prePage})" aria-label="Previous">
<span aria-hidden="true">«span>a>
li>
<c:forEach begin="1" end="${info.pages}" var="i">
<c:if test="${info.pageNum==i}">
<li>
<%-- <a href="${pageContext.request.contextPath}/prod/split.action?page=${i}" style="background-color: grey">${i}a>--%>
<a href="javascript:ajaxsplit(${i})"
style="background-color: grey">${i}a>
li>
c:if>
<c:if test="${info.pageNum!=i}">
<li>
<%-- <a href="${pageContext.request.contextPath}/prod/split.action?page=${i}">${i}a>--%>
<a href="javascript:ajaxsplit(${i})">${i}a>
li>
c:if>
c:forEach>
<li>
<%-- <a href="${pageContext.request.contextPath}/prod/split.action?page=1" aria-label="Next">--%>
<a href="javascript:ajaxsplit(${info.nextPage})" aria-label="Next">
<span aria-hidden="true">»span>a>
li>
<li style=" margin-left:150px;color: #0e90d2;height: 35px; line-height: 35px;">总共 <font
style="color:orange;">${info.pages}font> 页
<c:if test="${info.pageNum!=0}">
当前 <font
style="color:orange;">${info.pageNum}font> 页
c:if>
<c:if test="${info.pageNum==0}">
当前 <font
style="color:orange;">1font> 页
c:if>
li>
ul>
nav>
div>
div>
div>
1.3controller层的代码
//ajax分页翻页处理
@ResponseBody
@RequestMapping("/ajaxsplit")
public void ajaxSplit(int page, HttpSession session){
PageInfo info = productInfoService.splitPage(page, PAGE_SIZE);
session.setAttribute("info",info);
}
service层的代码
@Service
public class ProductInfoServiceImpl implements ProductInfoService {
@Autowired
ProductInfoMapper productInfoMapper;
@Override
public List<ProductInfo> getAll() {
return productInfoMapper.selectByExample(null);
}
@Override
public PageInfo splitPage(int pageNum, int pageSize) {
//分页插件使用PageHelper工具类完成分页设置
PageHelper.startPage(pageNum,pageSize);
//进行pageInfo的数据封装
//进行有条件的查询,必须创建ProductInfoExample对象
ProductInfoExample example = new ProductInfoExample();
//设置排序,按住键降序排序
//select * from product_info order by p_id desc
example.setOrderByClause("p_id desc");
//设置完排序后,取集合,切记切记,一定在取集合之前,设置pageHelper.startPage(pageNum,pageSize)
List<ProductInfo> list = productInfoMapper.selectByExample(example);
//将查询到的集合封装进PageInfo对象中
PageInfo<ProductInfo> pageInfo = new PageInfo<>(list);
return pageInfo;
}
}
===========================================================================
//mybatis的逆向工程中会生成实例及实例对应的example,example用于添加条件,相当where后面的部分
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
======================================================================
//pruductinfomapper用来放置条件
List<ProductInfo> selectByExample(ProductInfoExample example);
=======================================================================
//pruductinfomapper.xml
<select id="selectByExample" resultMap="BaseResultMap" parameterType="com.bjpowernode.pojo.ProductInfoExample" >
select
<if test="distinct" >
distinct
</if>
<include refid="Base_Column_List" />
from product_info
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null" >
order by ${orderByClause}
</if>
</select>
新增商品
新增商品业务逻辑层的实现
完成商品类别的绑定
查询全部商品名称
@Service("ProductTypeServiceImpl")
public class ProductTypeServiceImpl implements ProductTypeService {
@Autowired
ProductTypeMapper productTypeMapper;
@Override
public List<ProductType> getAll() {
return productTypeMapper.selectByExample(new ProductTypeExample());
}
}
商品类别监听器开发
Q:为什么要使用监听器?
A:因为以后可能会有很多地方要用到查看类别的功能,监听器随着服务器的启动而加载,可以减少数据库的负载
@WebListener
public class ProductTypeListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//手工从spring容器中取出ProductTypeServiceImpl的对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_*.xml");
ProductTypeService productTypeService = (ProductTypeService) context.getBean("ProductTypeServiceImpl");
List<ProductType> typeList = productTypeService.getAll();
//放入全局作用域中,供新增页面,修改页面,前台的查询功能提供全部商品类别集合
servletContextEvent.getServletContext().setAttribute("typeList",typeList);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
页面下拉列表框显示商品类型
<tr>
<td class="one">类别td>
<td>
<select name="typeId">
<c:forEach items="${typeList}" var="type">
<option value="${type.typeId}">${type.typeName}option>
c:forEach>
select>
td>
tr>
异步ajax图片上传
点击图片 上传后换成一个全新的名字 ,同时进行回显 在提交按钮点击之前图片已经上传,并回显,所以按下提交之后不需要对图片进行 *** 作
OTOD:借助jquery的插件
页面层代码
<tr>
<td class="three">图片介绍td>
<td> <br><div id="imgDiv" style="display:block; width: 40px; height: 50px;">div><br><br><br><br>
<input type="file" id="pimage" name="pimage" onchange="fileChange()" >
<span id="imgName" >span><br>
td>
tr>
function fileChange(){//注意:此处不能使用jQuery中的change事件,因此仅触发一次,因此使用标签的:onchange属性
alert("change");
$.ajaxFileUpload({
url: "${pageContext.request.contextPath}/prod/ajaxImg.action",//用于文件上传的服务器端请求地址
secureuri: false,//一般设置为false
fileElementId: 'pimage',//文件上传控件的id属性
dataType: 'json',//返回值类型 一般设置为json
success: function(obj) //服务器成功响应处理函数
{
alert(obj);
$("#imgDiv").empty(); //清空原有数据
//创建img 标签对象
var imgObj = $("");
//给img标签对象追加属性
imgObj.attr("src","/image_big/"+obj.imgurl);
imgObj.attr("width","100px");
imgObj.attr("height","100px");
//将图片img标签追加到imgDiv末尾
$("#imgDiv").append(imgObj);
//将图片的名称(从服务端返回的JSON中取得)赋值给文件本框
//$("#imgName").html(data.imgName);
},
error: function (e)//服务器响应失败处理函数
{
alert(e.message);
}
});
}
服务端上传图片
需要借用图片命名工具
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);
}
}
要上传文件需要借用springMVC提供的文件上传组件,极大简化文件上传的功能
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
bean>
controller层的开发
//异步ajax文件上传处理
@ResponseBody
@RequestMapping("/ajaxImg")
//MultipartFile专门用来接收上传的文件流
//要求action方法中参数的名称,要和提交的name名称完全一样
public Object ajaxImg(MultipartFile pimage,HttpServletRequest request) {
//提取生成文件名UUID+上传图片的后缀.jpg .png
String saveFileName = FileNameUtil.getUUIDFileName() + FileNameUtil.getFileType(pimage.getOriginalFilename());
//等到项目中图片存储的路径
String path = request.getServletContext().getRealPath("/image_big");
//转存
try {
pimage.transferTo(new File(path + File.separator + saveFileName));
} catch (IOException e) {
e.printStackTrace();
}
//添加json的依赖,返回客户端JSPN对象,封装图片路径,为了在页面实现立刻回显
JSONObject object = new JSONObject();
object.put("imgurl",saveFileName);
return object.toString();
}
}
商品增加Actiond的开发
前端添加表单提交地址如下
因此后端的controller的ProductInfoAction 设置 @RequestMapping(“/save”)方法
@RequestMapping("/save")
//因为info的属性名与 表单提交的name名字一样所以可以自动注入
public String save(ProductInfo info,HttpServletRequest request){
//由于提交表单缺少image 和 date所以手动设置
info.setpImage(saveFileName);
info.setpDate(new Date());
int num = -1;
try {
num = productInfoService.save(info);
} catch (Exception e) {
e.printStackTrace();
}
if (num>0){
request.setAttribute("msg","增加成功");
}else {
request.setAttribute("msg","增加失败");
}
//增加成功后应该重新访问数据库,所以跳转到分页显示的action上
return "forward:/prod/split.action";
}
编写service层的save方法,调用通过逆向工程获取的insert方法
@Override
public int save(ProductInfo info) {
return productInfoMapper.insert(info);
}
更新商品
页面点击按钮进行回显
function one(pid, ispage) {
location.href = "${pageContext.request.contextPath}/prod/one.action?pid=" + pid + "&page=" + ispage;
}
编写service层根据主键回显商品的方法
@Override
public ProductInfo getById(int id) {
return productInfoMapper.selectByPrimaryKey(id);
}
编写controller层根据主键回显商品的方法
//根据主键查找 one.action
@RequestMapping("/one")
public String one(int pid, Model model){
ProductInfo info = productInfoService.getById(pid);
model.addAttribute("prod",info);
//回显的update界面
return "update";
}
编写update页面
<form action="${pageContext.request.contextPath}/prod/update.action" enctype="multipart/form-data" method="post" id="myform">
<input type="hidden" value="${prod.pId}" name="pId">
<input type="hidden" value="${prod.pImage}" name="pImage">
<input type="hidden" value="${page}" name="page">
<table>
<tr>
<td class="one">商品名称td>
<td><input type="text" name="pName" class="two" value="${prod.pName}">td>
tr>
<tr class="three">
<td class="four">td>
<td><span id="pnameerr">span>td>
tr>
<tr>
<td class="one">商品介绍td>
<td><input type="text" name="pContent" class="two" value="${prod.pContent}">td>
tr>
<tr class="three">
<td class="four">td>
<td><span id="pcontenterr">span>td>
tr>
<tr>
<td class="one">定价td>
<td><input type="number" name="pPrice" class="two" value="${prod.pPrice}">td>
tr>
<tr class="three">
<td class="four">td>
<td><span id="priceerr">span>td>
tr>
<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>
<tr class="three">
<td class="four">td>
<td><span>span>td>
tr>
<tr>
<td class="one">总数量td>
<td><input type="number" name="pNumber" class="two" value="${prod.pNumber}">td>
tr>
<tr class="three">
<td class="four">td>
<td><span id="numerr">span>td>
tr>
<tr>
<td class="one">类别td>
<td>
<select name="typeId">
//typelist来自监听器的商品编号集合
<c:forEach items="${typeList}" var="type">
<option value="${type.typeId}"
if test="${type.typeId==prod.typeId}">
selected="selected"
c:if>
>${type.typeName}option>
c:forEach>
select>
td>
tr>
<tr class="three">
<td class="four">td>
<td><span>span>td>
tr>
<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>
根据主键ID进行修改
service
@Override
public int update(ProductInfo info) {
return productInfoMapper.updateByPrimaryKey(info);
}
controller
@RequestMapping("/update")
public String update(ProductInfo info,HttpServletRequest request){
//因为ajax的异步图片上传,如果上传过
//则saveFileName里有上传上来的图片名称
//如果没有使用异步ajax上传图片,则saveFileName=""
//实体类info使用隐藏表单域提供上来的pImg原始图片的名称
if (!"".equals(saveFileName)){
info.setpImage(saveFileName);
}
//完成更新处理
int num = -1;
try {
num = productInfoService.update(info);
} catch (Exception e) {
e.printStackTrace();
}
if (num>0){
request.setAttribute("msg","更新成功");
}else{
request.setAttribute("msg","更新失败");
}
//处理完更新后,saveFileName里有可能有数据
//而下一次更新时要使用这个变量为判断的依据,就会出错,所以必须清空saveFileName
saveFileName = "";
return "forward:/prod/split.action";
}
单个删除功能
页面js部分开发
由于采用的是局部刷新所以上方的alert执行不到,所以在ajax中再次alert
//单个删除
function del(pid) {
if (confirm("确定删除吗")) {
//发出ajax请求
$.ajax({
url: "${pageContext.request.contextPath}/prod/delete.action",
data:{"pid":pid},
type: "post",
dataType:"text",
success:function (msg){
alert(msg);
$("#table").load("http://localhost:8888/admin/product.jsp #table");
}
})
}
后台实现
@RequestMapping("/delete")
//@ResponseBody是用来解析数据的返回 要到分页的地方再返回
public String delete(int pid,HttpServletRequest request){
int num = -1;
try {
num = productInfoService.delete(pid);
} catch (Exception e) {
e.printStackTrace();
}
if (num>0){
request.setAttribute("msg","删除成功");
}else {
request.setAttribute("msg","删除失败");
}
//删除结束后跳到分页显示
return "forward:/prod/deleteAjaxSplit.action";
}
因为删除之后需要再次进行分页所以需要在执行之后转发到deleteAjaxSplit再次进行分页显示 msg也同样在deleteAjaxSplit进行接收显示所以deleteAjaxSplit上方需要加入@ResponseBod解析返回的数据
@ResponseBody
@RequestMapping(value = "/deleteAjaxSplit", produces = "text/html;charset=UTF-8")
public Object deleteAjaxSplit(HttpServletRequest request){
//获取第一页的数据
PageInfo info = productInfoService.splitPage(1,PAGE_SIZE);
request.getSession().setAttribute("info",info);
return request.getAttribute("msg");
}
批量删除多个
数据访问层及业务逻辑层
//批量删除功能 接口
int deleteBatch(String[] ids);
=================================
//mapper
<!-- 批量删除商品的功能 -->
<delete id="deleteBatch">
delete from product_info where p_id in
<foreach collection="array" item="pid" separator="," open="(" close=")">
#{pid}
</foreach>
</delete>
=============================
service
@Override
public int deleteBatch(String[] ids) {
return productInfoMapper.deleteBatch(ids);
}
控制器
//批量删除商品
@RequestMapping("deleteBatch")
public String deleteBatch(String pids,HttpServletRequest request){
String[] ps = pids.split(",");
int num = productInfoService.deleteBatch(ps);
try {
if (num>0){
request.setAttribute("msg","批量删除成功");
}else {
request.setAttribute("msg","批量删除失败");
}
} catch (Exception e) {
request.setAttribute("msg","当前商品不可以删除");
}
return "forward:/prod/deleteAjaxSplit.action";
}
@ResponseBody
@RequestMapping(value = "/deleteAjaxSplit", produces = "text/html;charset=UTF-8")
public Object deleteAjaxSplit(HttpServletRequest request){
//获取第一页的数据
PageInfo info = productInfoService.splitPage(1,PAGE_SIZE);
request.getSession().setAttribute("info",info);
return request.getAttribute("msg");
}
批量删除
//批量删除
function deleteBatch() {
//取得所有被选中删除商品的pid
var zhi=$("input[name=ck]:checked");
var str="";
var id="";
if(zhi.length==0){
alert("请选择将要删除的商品!");
}else{
// 有选中的商品,则取出每个选 中商品的ID,拼提交的ID的数据
if(confirm("您确定删除"+zhi.length+"条商品吗?")){
//拼接ID
$.each(zhi,function (index,item) {
id=$(item).val(); //22 33
alert(id);
if(id!=null)
str += id+","; //22,33,44
});
//发送请求到服务器端
$.ajax({
url:"${pageContext.request.contextPath}/prod/deleteBatch.action",
data:{"pids":str},
type:"post",
dataType: "text",
success:function (msg){
alert(msg);
//将页面上现显示的数据重新加载
$("#table").load("http://localhost:8888/admin/product.jsp #table");
}
})
}
}
}
按条件查询
页面传送条件到后台封装对象 vo
public class ProductInfoVo {
//商品名称
private String pname;
//商品类型
private Integer typeid;
//最高价格
private Integer hprice;
//最低价格
private Integer lprice;
开发顺序 mapper-service-controller-页面
多条件查询数据访问层的开发//多条件查询商品
List<ProductInfo> selectCondition(ProductInfoVo vo);
<!-- List<ProductInfo> selectCondition(ProductInfo vo);-->
<select id="selectCondition" parameterType="com.bjpowernode.pojo.vo.ProductInfoVo" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from product_info
<where >
<if test="pname != null and pname = '' ">
and p_name like concat('%',#{pname},'%')
</if>
<if test="typeid != null and typeid != '' ">
and type_id = #{typeid}
</if>
/*如果最低价格不为空,最高价格为空,则查询大于最低价格的所有商品*/
<if test="(lprice !='' and lprice!= null) and (hprice == null or hprice == '') ">
and p_price > #{lprice}
</if>
/*如果最低价格为空 最高价格不为空 则查询小于最高价格的商品*/
<if test="(lprice == null and lprice =='') and (hprice != null or hprice != '') ">
and #{lprice} > p_price
</if>
/*如果最高和最低价格都不为空,则查询介于最高价格和最低价格之间的商品*/
<if test="(lprice != null and lprice !='') and (hprice != null and hprice != '') ">
and p_price between #{lprice} and #{hprice}
</if>
</where>
order by p_id desc
</select>
service层的开发
@Override
public List<ProductInfo> selectCondition(ProductInfoVo vo) {
return productInfoMapper.selectCondition(vo);
}
controller层的开发
//多条件查询功能实现
@ResponseBody
@RequestMapping("condition")
public void condition(ProductInfoVo vo,HttpSession session){
List<ProductInfo> list = productInfoService.selectCondition(vo);
session.setAttribute("list",list);
}
页面
<form id="myform">
商品名称:<input name="pname" id="pname">
商品类型:<select name="typeid" id="typeid">
<option value="-1">请选择</option>
<c:forEach items="${typeList}" var="pt">
<option value="${pt.typeId}">${pt.typeName}</option>
</c:forEach>
</select>
价格:<input name="lprice" id="lprice">-<input name="hprice" id="hprice">
<input type="button" value="查询" onclick="condition()">
</form>
function condition(){
var pname= $("#pname").val();
var typeid = $("#typeid").val();
var lprice = $("#lprice").val();
var hprice= $("#hprice").val();
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/prod/condition.action",
data: {"pname":pname,"typeid":typeid,"lprice":lprice,"hprice":hprice},
success:function (){
$("#table").load("http://localhost:8888/admin/product.jsp #table");
}
})
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)