SSM项目笔记

SSM项目笔记,第1张

1.使用mybatis逆向工程提供的功能以及分页插件来完成分页 *** 作
   <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 &gt; #{lprice}
        </if>
/*如果最低价格为空 最高价格不为空 则查询小于最高价格的商品*/
        <if test="(lprice == null and lprice =='') and (hprice != null or hprice != '') ">
          and  #{lprice}  &gt;  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">&nbsp;&nbsp;&nbsp;
            商品类型:<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>&nbsp;&nbsp;&nbsp;
            价格:<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");
            }
        })
    }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/941707.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)