Web综合实践之用户信息管理

前言

博主在Web阶段也学习了近一个月,对于前端和后端的一些连接部分也有了一些了解

本篇博客是用来总结自己写过的一个小的综合案例,其实增删改查的操作都很简单了,最重要的是如何 将前端和后端连接起来 的思想

欢迎大家提出意见哦~ 觉得博主写得不错的可以一键三连啦~ 博主写得头都要昏了~

在这里插入图片描述



登录界面

在进入系统前,我们要先进操作员的登录,这里本来该建一个新的操作员实体类,并在数据库中创建一个操作员信息表的,但是这里为了方便,直接给用户信息添加了 username 和 password 两个属性

界面展示

在这里插入图片描述

后端代码思路分析

LoginServlet 类的代码编写流程:

扫描二维码关注公众号,回复: 13648660 查看本文章
  1. 设置编码

    request.setCharacterEncoding("utf-8");
    
  2. 获取数据:获取用户填写的验证码

    String verifycode = request.getParameter("verifycode");
    
  3. 验证码校验

    如果验证失败:
    	1、先设置提示信息
    		request.setAttribute("login_msg","验证码错误");
    		
    	2、再跳转界面,跳转回登录界面(使用转发)
    		为什么要跳转呢?仔细想想,点击登录按钮后,系统自动将数据拿到数据库进行比较
    		如果登录失败就要跳转到登录界面,而登录成功就需要跳转到另一个系统界面
    		所以这里要做跳转这一步,后面都会使用到跳转,就不再详细解释了
    		request.getRequestDispatcher("/login.jsp").forward(request,response);
    
  4. 封装User对象

    将前端获取的数据进行封装,封装成实体类User(用户信息实体类)对象,这里使用的是 BeanUtils类的 populate 方法,参数为 :(存储数据的对象,要转换的对象)

  5. 调用Service查询

    调用Service实现类中的方法将封装后的对象 user 与数据库中的数据进行比较,这里要说明:

    根据三层架构,我们分为:
    1.界面层(表示层):用户看的得界面。用户可以通过界面上的组件和服务器进行交互
    2.业务逻辑层:处理业务逻辑的。(接口命名为Service,实现类为ServiceImp)
    3.数据访问层:操作数据存储文件。(接口命名为Dao,实现类为DaoImp)
    
  6. 判断是否登录成功

    验证成功
        1、把数据存入session
        session.setAttribute("user",login_user);
        2、跳转页面(重定向)
        response.sendRedirect(request.getContextPath()+"/index.jsp");
    
    验证失败
        1、提示信息
        request.setAttribute("login_msg","用户名或密码错误");
        2、跳转登录界面
        request.getRequestDispatcher("/login.jsp").forward(request,response);
    

前端代码分析

  1. 为表单设置action属性,设置表单提交的地址,其中${pageContext.request.contextPath}用来替代虚拟路径,这样就不用再更换虚拟路径后又一个个进行修改

    <form action="${pageContext.request.contextPath}/loginServlet" method="post">
    
  2. 给每一个文本框添加 id 属性,因为要将文本框的数据传入后端,传入的数据是一个map集合,key 就是 id 的内容,例如:

    <input type="text" name="username" class="form-control" id="user" placeholder="请输入用户名"/>
    
  3. 登录界面肯定需要验证码,添加一张验证码的图,"href="javascript:refreshCode();"是为该链接添加一个函数,使之能切换不同的验证码

    验证码的div如下:

    <div class="form-inline">
                <label for="vcode">验证码:</label>
                <input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码" style="width: 120px;"/>
                <a href="javascript:refreshCode();">
                    <img src="${pageContext.request.contextPath}/checkCodeServlet" title="看不清点击刷新" id="vcode"/>
                </a>
    </div>
    

    验证码的script

     <script type="text/javascript">
            //切换验证码
            function refreshCode(){
            
            
                //1.获取验证码图片对象
                var vcode = document.getElementById("vcode");
    
                //2.设置其src属性,加时间戳
                vcode.src = "${pageContext.request.contextPath}/checkCodeServlet?time="+new Date().getTime();
            }
     </script>
    
  4. 修改错误提示框里的提示信息,<strong>xxx</strong>中的xxx改为${login_msg},在Servlet中会定义这个信息,并用setAttribute()方法传入request中

    <!-- 出错显示的信息框 -->
        <div class="alert alert-warning alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" >
                <span>&times;</span>
            </button>
            <strong>${login_msg}</strong>
        </div>
    

增加功能

界面展示

在这里插入图片描述

后端代码思路分析

AddUserServlet 的代码编写思路:
在这里插入图片描述

  1. 设置编码

    设置编码的作用主要是为了防止乱码,代码如下:

    request.setCharacterEncoding("utf-8");
    
  2. 获取参数

    这里的参数指的是页面里输入的数据(前端输入的数据),获取到后端,再到数据库中进行查询和比较,使用的是 getParameterMap() 方法

  3. 封装对象

    将前端获取的数据进行封装,封装成实体类User(用户信息实体类)对象,这里使用的是 BeanUtils类的 populate 方法,参数为 :(存储数据的对象,要转换的对象)

  4. 调用Service

    调用Service实现类中的方法将封装后的对象 user 与数据库中的数据进行比较

  5. 跳转到 FindUserByPageServlet(重定向)

前端代码分析

  1. 为表单设置action属性,设置表单提交的地址,其中${pageContext.request.contextPath}用来替代虚拟路径,这样就不用再更换虚拟路径后又一个个进行修改

    <form action="${pageContext.request.contextPath}/addUserServlet" method="post">
    
  2. 给每一个文本框添加 id 属性,因为要将文本框的数据传入后端,传入的数据是一个map集合,key 就是 id 的内容,例如:

    <input type="text" class="form-control" id="age" name="age" required="required" placeholder="请输入年龄">
    


删除功能

界面展示

删除有两种删除方法,一是单独删除一行,二是删除选中的多行数据

在这里插入图片描述

后端代码思路分析

DelUserServlet 类(删除单行) 代码编写思路:
在这里插入图片描述

  1. 获取id

    String id = request.getParameter("id");
    
  2. 调用Service删除

    UserService service=new UserServiceImpl();
    service.deletUser(id);
    
  3. 跳转到查询所有Servlet

    response.sendRedirect(request.getContextPath()+"/findUserByPageServlet");
    

DelSelectServlet 类(删除多行) 代码编写思路:

在这里插入图片描述

  1. 获取所有id

    String[] ids=request.getParameterValues("uid");
    
  2. 调用Service删除

    UserService service=new UserServiceImpl();
    service.delSelectedUser(ids);
    
  3. 跳转到查询所有Servlet

    response.sendRedirect(request.getContextPath()+"/findUserByPageServlet");
    

前端代码分析

  1. 为单行删除按钮添加函数,完成删除功能

    <a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a></td>
    
    <script>
    	function deleteUser(id){
            
            
    	            //用户安全提示
    	            if(confirm("您确定要删除吗?")){
            
            
    	                //访问路径
    	                location.href="${pageContext.request.contextPath}/delUserServlet?id="+id;
    	            }
    	        }
    </script>
    
  2. 给多行删除按钮添加单击事件

    <a class="btn btn-primary" href="javascript:void(0);" id="delSelected">删除选中</a>
    
    <script>
            window.onload = function(){
            
            
                //给删除选中按钮添加单击事件
                document.getElementById("delSelected").onclick = function(){
            
            
                    if(confirm("您确定要删除选中条目吗?")){
            
            
    
                        var flag = false;
                        //判断是否有选中条目
                        var cbs = document.getElementsByName("uid");
                        for (var i = 0; i < cbs.length; i++) {
            
            
                            if(cbs[i].checked){
            
            
                                //有一个条目选中了
                                flag = true;
                                break;
                            }
                        }
    
                        if(flag){
            
            //有条目被选中
                            //表单提交
                            document.getElementById("form").submit();
                        }
                    }
                }
                //1.获取第一个cb
                document.getElementById("firstCb").onclick = function(){
            
            
                    //2.获取下边列表中所有的cb
                    var cbs = document.getElementsByName("uid");
                    //3.遍历
                    for (var i = 0; i < cbs.length; i++) {
            
            
                        //4.设置这些cbs[i]的checked状态 = firstCb.checked
                        cbs[i].checked = this.checked;
                    }
                }
            }
        </script>
    

    实现了两个小细节:(1) 点击删除后有一个确认框,避免删除过快导致无法挽回;(2) 可以实现复选框全选中功能

  3. 给表单第一列添加复选框,实现多行删除的选中功能

    <form id="form" action="${pageContext.request.contextPath}/delSelectServlet" method="post">
            <table border="1" class="table table-bordered table-hover">
                <tr class="success">
                    <!-- 复选框 -->
                    <th><input type="checkbox" id="firstCb"></th>
                    <th>编号</th>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>年龄</th>
                    <th>籍贯</th>
                    <th>QQ</th>
                    <th>邮箱</th>
                    <th>操作</th>
                </tr>
    
                <c:forEach items="${pb.list}" var="user" varStatus="s">
                    <tr>
                        <!-- 复选框 -->
                        <td><input type="checkbox" name="uid" value="${user.id}"></td>
                        <td>${s.count}</td>
                        <td>${user.name}</td>
                        <td>${user.gender}</td>
                        <td>${user.age}</td>
                        <td>${user.address}</td>
                        <td>${user.qq}</td>
                        <td>${user.email}</td>
                        <td><a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>&nbsp;
                            <a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a></td>
                    </tr>
                </c:forEach>
    
            </table>
        </form>
    


修改功能

界面展示

在这里插入图片描述

后端代码思路分析

在这里插入图片描述
FindUserServlet 类代码编写思路:

		//1.获取id
        String id = request.getParameter("id");
        //2.调用Service
        UserService service=new UserServiceImpl();
        User user=service.findUserById(id);
        //3.将user存入request
        request.setAttribute("user",user);
        //4.转发到update.jsp
        request.getRequestDispatcher("/update.jsp").forward(request,response);

UpdateUserServlet 类代码编写思路:

		//1.设置编码
        request.setCharacterEncoding("utf-8");
        //2.获取map
        Map<String, String[]> map = request.getParameterMap();

        //封装对象
        User user=new User();
        try {
    
    
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        } catch (InvocationTargetException e) {
    
    
            e.printStackTrace();
        }

        //4.调用Service修改
        UserService service=new UserServiceImpl();
        service.updateUser(user);

        //5.跳转到查询所有Servlet
        response.sendRedirect(request.getContextPath()+"/findUserByPageServlet");

前端代码分析

  1. 为表单设置action属性,设置表单提交的地址,其中${pageContext.request.contextPath}用来替代虚拟路径,这样就不用再更换虚拟路径后又一个个进行修改

    <form action="${pageContext.request.contextPath}/updateUserServlet" method="post">
    
  2. 设置隐藏域 提交id

    <input type="hidden" name="id" value="${user.id}">
    
  3. 设置信息回显,点击进入修改页面后,依然能看到原来的信息

    普通的文本框就添加value属性,性别选择添加一个 value 属性和 checked

    地址信息的回显用以下方法:

    			<c:if test="${user.address == '陕西'}">
                    <option value="陕西" selected>陕西</option>
                    <option value="北京">北京</option>
                    <option value="上海">上海</option>
                </c:if>
    
                <c:if test="${user.address == '北京'}">
                    <option value="陕西" >陕西</option>
                    <option value="北京" selected>北京</option>
                    <option value="上海">上海</option>
                </c:if>
    
                <c:if test="${user.address == '上海'}">
                    <option value="陕西" >陕西</option>
                    <option value="北京">北京</option>
                    <option value="上海" selected>上海</option>
                </c:if>
    
  4. 给姓名设置 readonly 属性规定输入字段为只读,修改时无法修改姓名

    <input type="text" class="form-control" id="name" name="name"  value="${user.name}" readonly="readonly" placeholder="请输入姓名" />
    


分页查询功能

因为需要做出分页的效果,所以原来的简单的查询功能就不再使用了,这里就结合着分页来介绍

界面展示

在这里插入图片描述

后端代码思路分析

在这里插入图片描述
在这里插入图片描述
先创建一个PageBean实体类,实体类成员变量如下:

	//总记录数
    private int totalCount;
    //总页码
    private int totalPage;
    //每页的数据
    private List<T> list;
    //当前页码
    private int currentPage;
    //每页显示的记录数
    private int rows;

FindUserByPageServlet 代码编写思路:

		request.setCharacterEncoding("utf-8");

        //1.获取参数
        //当前页码
        String currentPage = request.getParameter("currentPage");
        //每页显示条数
        String rows = request.getParameter("rows");

		//当页码为0时,使当前页码变为1
        if(currentPage==null || "".equals(currentPage)){
    
    
            currentPage="1";
        }

        if(rows==null||"".equals(rows)){
    
    
            rows="5";
        }

        //获取条件查询参数
        Map<String,String[]> condition=request.getParameterMap();

        //2.调用service查询
        UserService service=new UserServiceImpl();
        PageBean<User> pb=service.findUserByPage(currentPage,rows,condition);

        //3.将PageBean存入request
        request.setAttribute("pb",pb);
        request.setAttribute("condition",condition);
        //4.转发到 list.jsp
        request.getRequestDispatcher("/list.jsp").forward(request,response);

上述代码的第2步是一个重点,返回的pb是根据查询文本框输入的数据进行查询得到的List数据

前端代码分析

<div>
        <nav aria-label="Page navigation">
            <ul class="pagination">
                <!-- 左角标 -->
                <c:if test="${pb.currentPage == 1}">
                    <li class="disabled">
                </c:if>

                <c:if test="${pb.currentPage != 1}">
                    <li>
                </c:if>

                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pb.currentPage - 1}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}" aria-label="Previous">
                        <span aria-hidden="true">&laquo;</span>
                    </a>
                </li>

				<!-- 页码 -->
                <c:forEach begin="1" end="${pb.totalPage}" var="i">
                    <c:if test="${pb.currentPage == i}">
                        <li class="active"><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}">${i}</a></li>

                    </c:if>

                    <c:if test="${pb.currentPage != i}">
                        <li><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}">${i}</a></li>

                    </c:if>
                </c:forEach>

					<!-- 右角标 -->
                    <c:if test="${pb.currentPage==pb.totalPage}">
                        <li class="disabled">
                    </c:if>

                    <c:if test="${pb.currentPage != pb.totalPage}">
                        <li>
                    </c:if>

                    <a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${pb.currentPage + 1}&rows=5&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}" aria-label="Next">
                        <span aria-hidden="true">&raquo;</span>
                    </a>
                </li>

				<!-- 备注 -->
                <span style="font-size: 25px;margin: 5px" >
                    共${pb.totalCount}条数据,共${pb.totalPage}页
                </span>
            </ul>
        </nav>
    </div>

上述代码大致分为四个部分:"<" 、页码数字、">"、一共多少数据

(1) 每个部分的链接地址都由 ${pageContext.request.contextPath} + 实际地址 + 当前页码 + 每页显示的记录数 + 文本框的值信息 组成,这样就组成了复制分页查询的分页条

(2) 在 “<” 和 “>” 的部分做了 if 选择,当页码为1或者最大时,再点击 “<” 和 “>” 图标,就会显示无法点击的图标,用法是给 li 标签添上class="disabled"属性,但是实际上还是能点击,并且网页会报错,但是这个问题在后端已经解决了

(3) 在页码数字的部分做了 if 选择,使每个当前页码的样式与其他的页码样式不一样,用法是给 li 标签添上class="active"属性

猜你喜欢

转载自blog.csdn.net/ljc20180584024/article/details/122320154