美文网首页
第十三篇学习总结

第十三篇学习总结

作者: 拼搏男孩 | 来源:发表于2020-01-30 12:54 被阅读0次

第十三篇学习总结

一、主页展示

主页展示分两个步骤,将所有的商品信息从数据库中取出来,然后分页。

1、获取所有商品信息

获取所有商品信息的思路是dao使用SQL语句从数据库中查询到所有商品信息的集合,service层再交给servlet。不过在此之前首先要定义一个JavaBean用于存储和运输数据,这个JavaBean中应该包含一个商品应该包含的所有信息:id,name,price,num,img

public List<Goods> getGoods(Goods goods){

    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

    try {
        cn = JDBCUtils.getConnection();
        //由于要进行分页,并且提供名称匹配搜索,所以限制了搜索条件,不过由于
        //name的默认值是"",前后各加一个%表示匹配所有
        ps = cn.prepareStatement("select * from goods where name like ? limit ?,?");
        goods.getName();
        ps.setString(1,"%"+goods.getName()+"%");
        ps.setInt(2,goods.getStart());
        ps.setInt(3,goods.getPageSize());
        rs = ps.executeQuery();
        //调用DBUtils的selectMore方法进行映射
        List<Goods> list = DBUtils.selectMore(Goods.class,rs);
        //如果查询到了就返回这个list,否则返回null
        return list;
    }catch (Exception  e){
        e.printStackTrace();
    }finally {
        JDBCUtils.close(rs,ps,cn);
    }

    return null;
}

//DBUtils的selectMore方法需要两个参数,第一个是类的字节码,第二个是查询后的ResultSet
public static <E> List<E> selectMore(Class<E> clazz, ResultSet rs){
    List<E> list = new ArrayList<>();
    try {
        ResultSetMetaData metaData = rs.getMetaData(); //获取结果集的表头字段信息
        int cnum = metaData.getColumnCount(); //获取结果集中字段的数量
        while(rs.next()){//遍历每一行数据
            E obj = clazz.newInstance(); //反射创建一个对象
            for (int i = 1; i <=cnum ; i++) { //遍历所有的字段
                String cname = metaData.getColumnLabel(i); //拿到字段标签
                String ctn = metaData.getColumnTypeName(i);//拿到类型名
                Object value = rs.getObject(cname); //获取当前行对应的当前字段的值
                if(value==null){ //如果值为null
                    if(ctn.equals("INTEGER")){ //如果类型是Integer,把值设置为0
                        value = 0;
                    }
                }
                Field field = clazz.getDeclaredField(cname);//反射获取类中的成员变量
                field.setAccessible(true); //取消语法检查

                field.set(obj,value);//把我们取出来的这个字段的值赋值给javabean对象的成员变量
            }
            list.add(obj);//将这个封装着数据的对象放到list集合中
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return list;
}

2、分页

实现分页首先要定义一个BaseBean类,里面有三个成员变量:currentPage当前页,初始为1,pageSize每页展示的数量,可以自定义,start每页开始的下标,可以通过计算得出。然后最重要的就是字符串拼接,实现分页首先要知道总共有多少页。

package com.qianfeng.paging;

import java.util.Map;

//这是页面底部的分页栏
public class Paging {
    public static String getPage(BaseBean baseBean, int count, String url, Map<String,String[]> map) {
        int pageSize = baseBean.getPageSize(); //获取每页的数量
        int pageCount = count%pageSize==0?count/pageSize:count/pageSize+1;//计算总页数

        if(pageCount==0){ //如果总页数是0,就没有分页
            return "";
        }
        //获取当前页码
        int currentPage = baseBean.getCurrentPage();
        //如果当前页大于总页数, 将当前页设置为最后一页
        if(currentPage>pageCount){
            currentPage=pageCount;
        }
        //如果当前页小于等于0,将当前页设置为1
        if(currentPage<=0){
            currentPage=1;
        }
        //计算分页的起始位置
        int start = (currentPage-1)*pageSize; // 计算开始位置
        //将计算好的起始位置存到 Javabean,便于之后查询数据
        baseBean.setStart(start);

        //用户如果带有参数, name我们拼接的url上页也应该带着参数, 这样点击的时候, 请求后台时,才能把参数带过去, 获取的结果,也是条件筛选的结果
        StringBuilder sb = new StringBuilder(url);
        sb.append("?"); //将原来的url和?拼接到一起, 形成一个头
        //遍历request中的参数, 将key和value拼接成请求  key=value&
        for (Map.Entry<String, String[]> entry : map.entrySet()) {
            String key = entry.getKey();
            //因为下面已经拼接了当前页面,那么,currentPage就不需要在这里拼接了
            if(!"currentPage".equals(key)){
                String[] values = entry.getValue();
                //请求时,可能有一个参数名对应多个值的情况
                for (String value : values) {
                    sb.append(key.concat("=").concat(value).concat("&"));
                }
            }
        }
        url = sb.toString(); //将拼接好的StringBuilder转成字符串,已备使用

        //拼接按钮
        sb = new StringBuilder();

        //如果当前页是第一页, 首页和上一页都不能点击
        if(currentPage==1){
            sb.append("<a >首页</a>");
            sb.append("<a >上一页</a>");
        }else{
            sb.append("<a href='"+url+"currentPage=1'>首页</a>");
            sb.append("<a href='"+url+"currentPage="+(currentPage-1)+"'>上一页</a>");
        }
        //遍历拼接页码
        if(pageCount<=7){
            for (int i = 1; i <= pageCount; i++) {
                if(i==currentPage){
                    sb.append("<a >"+i+"</a>");
                }else{
                    sb.append("<a href='"+url+"currentPage="+i+"'>"+i+"</a>");
                }
            }
        }else{
            //在多页面情况下会有省略好,我们使用保持按钮的总数是9个, 当前页的前后两个显示显示出来,当前页的前后第三个用省略号代替
            //但是,但用户点击到第一页时, 后面之后两个按钮和一个省略号,总数不足9个, 当前页前面不够了, 之后再后面多显示几个按钮
            int n = 2;
            if(currentPage==1||currentPage==pageCount){
                n = 5;
            }else if(currentPage==2||currentPage==pageCount-1){
                n = 4;
            }else if(currentPage==3||currentPage==pageCount-2){
                n = 3;
            }
            for (int i = 1; i <= pageCount; i++) {
                if(i==currentPage){
                    sb.append("<a >"+i+"</a>");
                }else if(i>=currentPage-n&&i<=currentPage+n){
                    sb.append("<a href='"+url+"currentPage="+i+"'>"+i+"</a>");
                }else if(i==currentPage-(n+1)||i==currentPage+(n+1)){
                    sb.append("<a >...</a>");
                }
            }
        }

        //如果当前页时最后一页,那么下一页和尾页都不能点击
        if(currentPage==pageCount){
            sb.append("<a >下一页</a>");
            sb.append("<a >尾页</a>");
        }else{
            sb.append("<a href='"+url+"?currentPage="+(currentPage+1)+"'>下一页</a>");
            sb.append("<a href='"+url+"?currentPage="+pageCount+"'>尾页</a>");
        }

        //拼接跳转页面按钮和js代码
        sb.append("<input id='pageNum' type='number'/><button onclick='toPage()'>跳转</button>");
        sb.append("<script>function toPage(){" +
                "location.href='"+url+"?currentPage='+document.getElementById('pageNum').value"+
                "}</script>");
        sb.append("<span>共 "+pageCount+" 页</span>");
        return sb.toString();
    }
}


import com.qianfeng.shop.bean.Goods;
import com.qianfeng.shop.service.ShopSerivice;
import com.qianfeng.paging.Paging;

import com.qianfeng.utils.WebUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet("/shop/toMainPage")
public class ToMainPage extends HttpServlet {

    private ShopSerivice shopSerivice = new ShopSerivice();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //接受参数和当前页码
        //继承BaseBean, 当前Javabean对象就可以使用分页参数了
        Goods goods = WebUtils.populate(Goods.class,req);
        //要想展示分页,我们要知道总共有多少页,想要知道总共有多少页,就必须知道总共有多少数据,然后计算总页数
        //获取总数据量
        int count = shopSerivice.getGoodsCount(goods);
        //计算分页 需要当前页,每一页多少个, 数据的总量, 请求的url, 参数
        String paging = Paging.getPage(goods,count,"/shop/toMainPage",req.getParameterMap());
        //将计算出的分页的html代码放到请求域中
        req.setAttribute("paging",paging);
        //获取当前页的实际数据
        List<Goods> list = shopSerivice.getGoods(goods);
        //将数据放到请求域中
        req.setAttribute("list",list);
        //将请求参数放到请求域中,便于回显
        req.setAttribute("goods",goods);

        req.getRequestDispatcher("/WEB-INF/pages/main.jsp").forward(req,resp);
    }
}

获取到当前页面的商品信息后就把这些信息放在request域中,jsp页面使用JSTL和EL表达式在页面展示。

二、后台

后台就是给管理员添加、修改、删除、查询数据的。

1、登录过滤器

如果用户在未登录的情况下请求非登录页面,应该将用户的请求重定向到登录页面,同时有一些页面即使不登录也应该能请求,比如一些静态资源。能实现这种功能的只有过滤器。

import com.qianfeng.shop.bean.UserBack;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@WebFilter("/*")
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //因为要使用session,所以将ServletRequest强转成HttpServletRequest
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        //有一些静态资源和serlvet请求是不需要拦截的, 放行
        //获取请求路径 /项目名/请求地址
        String str = request.getRequestURI();
        //将一些页面排除
        if(str.startsWith("/shopback/resource/")||str.startsWith("/shopback/user/login")){
            filterChain.doFilter(request,servletResponse);
            return;
        }

        //获取登陆标志
        Object userBack = request.getSession().getAttribute("user");
        //判断使用已经登陆
        if(userBack==null){
            request.getRequestDispatcher("/resource/pages/login.jsp").forward(request,servletResponse);
        }else{
            filterChain.doFilter(request,servletResponse);
        }

    }

    @Override
    public void destroy() {

    }
}

2、登录

我们在数据库中存储的用户密码加密后的数据,并不会直接存储用户的明文密码,所以用户登录的时候要进行密码加密:

/**
* 根据用户名密码查询用户信息
* @param userBack
* @return
*/
public UserBack getUserByUserNameAndPassword(UserBack userBack){
    //使用自定义工具对密码进行md5加密
    String password = DigestString.digest(userBack.getPassword());
    userBack.setPassword(password);

    UserBack back = userDao.getUserByUserNameAndPassword(userBack);
    return back;
}
//使用md5算法进行加密
public class DigestString {

    public static String digest(String str){
        try {
            MessageDigest digest = MessageDigest.getInstance("md5");
            byte[] bs = digest.digest(str.getBytes());
            //然后再使用Base64算法将字节数组转换为字符串
            Base64.Encoder encoder = Base64.getEncoder();

            str = encoder.encodeToString(bs);
            return str;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {



    }

}

3、商品分类的增删改查

商家通过后台管理系统不仅可以对商品信息进行增删改查,还可以对商品类型进行增删改查,这些操作除了查询,全都是使用Ajax异步提交的,操作成功后再重新请求当前页面。

function editById(id){
        $("#content").hide(1000); //列表消失
        $("#edit").show(1000); //修改框出现

        $.ajax({
            url:"/shopback/shop/getTypeById",
            type:"post",
            data:{id:id},
            dataType:"json",
            success: function (data) {
                if(data.code==-1){
                    alert(data.message);
                }else if(data.code==1){
                    var typeBean = data.data;
                    //服务器获取分类信息成功, 之后将这些信息放到页面中
                    $("#editName").val(typeBean.name);
                    $("#editUserName").text(typeBean.userName);
                    $("#editTime").text(typeBean.time);
                    $("#editId").val(typeBean.id);
                }
            }
        })


    }

4、商品管理

4.1 商品管理分页

和用户看到的主页面分页一样,管理员在后台对商品进行管理也需要分页。在商品管理页面,不仅要展示商品的基本信息:图片、商品名、数量、价格等,还需要提供商品管理的操作:增加、删除、修改、查询。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>商品管理页面</title>
    <style>
        img{
            width: 100px;
            height: 100px;
        }
    </style>
</head>
<body>
    <a href="/shopback/shop/toTypesPage">跳转分类管理页面</a>
    <div id="content">
        <div>
        <!-- 名称搜索表单 -->
            <form action="/shopback/shop/toGoodsPage">
                <input name="name" value="${goods.name}"> <button>搜索</button>
            </form>
        </div>
        <div>
        <!-- 添加新商品按钮,点击之后显示添加新商品框 -->
            <button onclick="openAdd()">添加新商品</button>
        </div>
        <div>
        <!-- 创建一个表格,用于展示商品信息 -->
            <table>
                <tr>
                    <th>编号</th>
                    <th>名称</th>
                    <th>类型</th>
                    <td>价格</td>
                    <th>数量</th>
                    <th>状态</th>
                    <th>操作人</th>
                    <th>操作时间</th>
                    <th>操作</th>
                </tr>
                <!-- 这个list是放在request域中的商品信息 -->
                <c:forEach items="${list}" var="item">
                    <tr>
                        <th>${item.id}</th>
                        <th>${item.name}</th>
                        <th>${item.typeName}</th>
                        <td>${item.price}</td>
                        <th>${item.num}</th>
                        <th>
                        <!-- 由于我们在数据库中存储的商品状态是用数值1和0来表示的,这里需要进行判断 -->
                            <c:if test="${item.status==0}">
                                <span style="color: red">下架状态</span>
                            </c:if>
                            <c:if test="${item.status==1}">
                                <span style="color: green">上架状态</span>
                            </c:if>
                        </th>
                        <th>${item.userName}</th>
                        <th>${item.createTime}</th>
                        <th>
                        <!-- 修改删除与上架、下架按钮,点击事件都有对应的函数,参数是商品的id -->
                            <a href="javascrit:void(0)" onclick="openEdit(${item.id})">修改</a>
                            <a href="javascrit:void(0)" onclick="deleteById(${item.id})">删除</a>
                            <c:if test="${item.status==0}">
                                <a href="javascrit:void(0)" onclick="editStatus(${item.id},1)">上架</a>
                            </c:if>
                            <c:if test="${item.status==1}">
                                <a href="javascrit:void(0)" onclick="editStatus(${item.id},0)">下架</a>
                            </c:if>
                        </th>
                    </tr>
                </c:forEach>
            </table>
        </div>
        <div>
            ${paging}
        </div>
    </div>

    <!-- 添加商品的div -->
    <div id="add" style="display: none">
        封面图 : <img id="img" src="https://cn.bing.com/th?id=OIP.LR1EWcFdBaQdJoU7ZUDIDwHaGV&pid=Api&rs=1" onclick="openFile()"> <br>
        <input type="file" style="display: none" id="addFile" onchange="submitImg()">
        <input id="addImg" type="hidden">
        商品名称 : <input id="addName"> <br>
        商品类型 : <select id="addTypeId">
                    <c:forEach items="${types}" var="item">
                        <option value="${item.id}">${item.name}</option>
                    </c:forEach>
                </select>    <br>
        商品价格 : <input type="number" id="addPrice">  <br>
        商品数量 : <input type="number" id="addNum">  <br>
        <!-- 用于富文本框的div -->
        商品详情 : <div id="addContent"></div>
        <button onclick="addSubmit()">提交</button> <button onclick="cancel()">取消</button>
    </div>

</body>
<!-- 导入wangEditor与jQuery的js -->
<script src="/shopback/resource/js/wangEditor.min.js"></script>
<script src="/shopback/resource/js/jquery.js"></script>
<script>
    //预加载, 内部的代码会在页面加载完毕之后才执行
    var e;
    $(function(){
        //创建模板
        var E = window.wangEditor;
        e = new E("#addContent"); //创建富文本对象
        //自定义图片上传服务器,因为wangEditor的默认上传的是网络图片
        e.customConfig.uploadImgServer = '/shopback/file/upload';
        e.create();
    })

    function addSubmit() {
        var img = $("#addImg").val();
        var name = $("#addName").val();
        var typeId = $("#addTypeId").val();
        var price = $("#addPrice").val();
        var num = $("#addNum").val();
        var content = e.txt.html();

        var obj = {img:img,name:name,typeId:typeId,price:price,num:num,content:content};

        $.ajax({
            url:"/shopback/shop/addGoods",
            type:"post",
            data:obj,
            dataType:"json",
            success: function (data) {
                if(data.code==-1){
                    alert(data.message)
                }else if (data.code==1){
                    location.reload();
                }
            }
        })
    }


    function submitImg(){
        var file = $("#addFile")[0].files[0];
        var formData = new FormData();
        formData.append("file",file);

        $.ajax({
            url:"/shopback/file/upload",
            type:"post",
            data:formData,
            contentType:false,
            processData:false,
            dataType:"json",
            success: function (data) {
                if(data.errno!=0){
                    alert("对不起,图片上传失败");
                }else if(data.errno==0){
                    $("#addImg").val(data.data[0]);
                    $("#img").attr("src",data.data[0]);
                }
            }
        })
    }

    function openFile(){
        $("#addFile").click();
    }
    //打开添加框
    function openAdd(){
        $("#content").hide();
        $("#add").show();
    }
    //添加和修改框全部隐藏, 主列表出现
    function cancel(){
        $("#content").show();
        $("#add").hide();
        $("#edit").hide();
    }



    //根据id删除商品信息
    function deleteById(id){

        var flg = confirm("您确定要删除吗?");
        if(!flg){
            return;
        }

        $.ajax({
            url:"/shopback/shop/deleteGoodsById",
            type:"post",
            data:{id:id},
            dataType:"json",
            success: function (data) {
                if(data.code==-1){
                    alert(data.message)
                }else if (data.code==1){
                    location.reload();
                }
            }
        })

    }


    function editStatus(id,status) {
        var flg ;
        if(status==0){
            flg = confirm("是否确定要下架?");
        }else{
            flg = confirm("是否确定要上架?");
        }
        if(!flg){
            return;
        }

        $.ajax({
            url:"/shopback/shop/editGoodsStatus",
            type:"post",
            data:{id:id,status:status},
            dataType:"json",
            success: function (data) {
                if(data.code==-1){
                    alert(data.message)
                }else if (data.code==1){
                    location.reload();
                }
            }
        })

    }
</script>
</html>

编写前台页面之后,还要编写对应的servlet、service、dao,因为每一个操作都需要同数据库进行交互

相关文章

  • 第十三篇学习总结

    第十三篇学习总结 一、主页展示 主页展示分两个步骤,将所有的商品信息从数据库中取出来,然后分页。 1、获取所有商品...

  • 学习总结第十三篇 5.17

    课程小结: 1、顺序结构:格式控制 %d, %c, %f, %lf 2、分支结构:if-else、switch-c...

  • 如何让坚持自然发生

    ----《通向财富自由之路》学习总结第十三篇 最近一万小时理论比较火,说的是不管是某个行业或者某个技能,只要你能坚...

  • 每周读书总结

    读书总结第十三周 时间:7.24-7.30 数量:个人分享9篇 朋友圈分享2 主题: 项目沟通管理 【读书总结】 ...

  • 彭放|感悟《论语》的人文情怀之【13.1】——子路问政

    第十三篇 子路第十三简介 从今天开始进入“子路第十三”的学习。本篇共有30章,包含为政者先正己,富民兴教...

  • 013

    第十三篇

  • 第十三篇反思总结

    这几天总是没时间看书和背单词,一方面是因为作业(但是我在洗澡的时侯,我又想到,不是因为作业变多了,而是我想写了)。...

  • 学习总结

    付爱宝微商财富领袖集训营第十三期 第十三组宋百玲2017年7月10日总结 自己学习后的五个收获: 1:团队不会听我...

  • 【重温基础】13.迭代器和生成器

    本文是 重温基础 系列文章的第十三篇。今日感受:每次自我年终总结,都会有各种情绪和收获。 系列目录: 【复习资料】...

  • 学习第十三的总结

    一、学习内容 1、Python重看了上一次课程中的函数的内容、主要学了函数的创建、函数调用、参数传递、匿名函数、r...

网友评论

      本文标题:第十三篇学习总结

      本文链接:https://www.haomeiwen.com/subject/gxyithtx.html