6、UMS-编辑用户【难点】【阶段重点】
6.1、需求说明
遇到这样的复杂需求,我们需要拆分成两步来做:
1、用户数据查询回显:跳转到编辑页面,在编辑页面回显该用户的数据
2、用户数据修改:编辑页面修改完毕后,点击“确定”,真正修改数据到xml中
6.2、用户数据查询回显
6.2.1、需求分析
分析:
关键点:
1、地址栏传递id
2、request作用域及请求转发
3、对User数据在JSP进行回显
如果数据在request作用域:
文本框:value="${参数名.属性名}"
文本域:<textarea>${参数名.属性名}</textarea>
单选框/复选框:
JavaBean javaBean = (JavaBean)request.getAttribute("参数名");
if(javaBean!=null && javaBean.getXxx()!=null){
if(javaBean.getXxx().equals("值")){
out.write("checked='checked'");
}
}
选择框:
JavaBean javaBean = (JavaBean)request.getAttribute("参数名");
if(javaBean!=null && javaBean.getXxx()!=null){
if(javaBean.getXxx().equals("值")){
out.write("selected='selected'");
}
}
流程:
6.2.2、代码实现
/user/list.jsp
<td align="center" style="HEIGHT: 22px"> <a href="<%=pageContext.getServletContext().getContextPath()%>/user?method=editView&id=<%=user.getId()%>"> <img src="<%=request.getContextPath() %>/images/i_edit.gif" border="0" style="CURSOR: hand"> </a> </td>
//
UserServlet
/** * 跳转到编辑页面 * @return */ public String editView(){ HttpServletRequest request = getRequest(); //1、获取参数id String id = request.getParameter("id"); //2、调用service根据id查询用户信息 User user = userService.searchUserById(id); //3、存入request作用域 request.setAttribute("user",user); //4、请求转发 return "forward:/user/edit.jsp"; }
/user/edit.jsp
<% User u = (User) request.getAttribute("user"); %> <form method="post" action=""> <input type="hidden" name="id" value="" /> <table cellSpacing="1" cellPadding="5" width="100%" align="center" bgColor="#eeeeee" style="border: 1px solid #8ba7e3" border="0"> <tr> <td class="ta_01" align="center" bgColor="#afd1f3" colSpan="4" height="26"> <strong><STRONG>编辑用户</STRONG> </strong> </td> </tr> <tr> <td align="center" bgColor="#f5fafe" class="ta_01"> 登录名: </td> <td class="ta_01" bgColor="#ffffff"> <input type="text" name="loginName" id="loginName" class="bg" value="${user.loginName}"/> </td> <td align="center" bgColor="#f5fafe" class="ta_01"> 用户类型: </td> <% String utype = null; if(u!=null){ utype = u.getUtype(); } %> <td class="ta_01" bgColor="#ffffff"> <input type="radio" name="utype" value="管理员" <% if(utype!=null && utype.equals("管理员")){ out.write("checked='checked'"); } %> />管理员 <input type="radio" name="utype" value="普通用户" <% if(utype!=null && utype.equals("普通用户")){ out.write("checked='checked'"); } %> />普通用户 </td> </tr> <tr> <td align="center" bgColor="#f5fafe" class="ta_01"> 密码: </td> <td class="ta_01" bgColor="#ffffff"> <input type="password" name="loginPwd" id="loginPwd" value="${user.loginPwd}"/> </td> <td align="center" bgColor="#f5fafe" class="ta_01"> 用户姓名: </td> <td class="ta_01" bgColor="#ffffff"> <input type="text" name="userName" class="bg" value="${user.userName}" /> </td> </tr> <tr> <td align="center" bgColor="#f5fafe" class="ta_01"> 性别: </td> <td class="ta_01" bgColor="#ffffff"> <% String sex = null; if(u!=null){ sex = u.getSex(); } %> <input type="radio" value="男" name="sex" id="sex0" <% if(sex!=null && sex.equals("男")){ out.write("checked='checked'"); } %> />男 <input type="radio" value="女" name="sex" id="sex1" <% if(sex!=null && sex.equals("女")){ out.write("checked='checked'"); } %> />女 </td> <td align="center" bgColor="#f5fafe" class="ta_01"> 学历: </td> <td class="ta_01" bgColor="#ffffff"> <% String education = null; if(u!=null){ education = u.getEducation(); } %> <select name="education" id="education"> <option value="">--选择学历--</option> <option value="博士" <% if(education!=null && education.equals("博士")){ out.write("selected='selected'"); } %> >博士</option> <option value="硕士" <% if(education!=null && education.equals("硕士")){ out.write("selected='selected'"); } %> >硕士</option> <option value="本科" <% if(education!=null && education.equals("本科")){ out.write("selected='selected'"); } %> >本科</option> <option value="专科" <% if(education!=null && education.equals("专科")){ out.write("selected='selected'"); } %> >专科</option> <option value="高中" <% if(education!=null && education.equals("高中")){ out.write("selected='selected'"); } %> >高中</option> </select> </td> </tr> <tr> <td align="center" bgColor="#f5fafe" class="ta_01"> 出生日期: </td> <td class="ta_01" bgColor="#ffffff"> <input type="text" name="birthday" id="birthday" size="20" readonly="true" value="${user.birthday}" onclick="c.show(this)" /> </td> <td align="center" bgColor="#f5fafe" class="ta_01"> 电话: </td> <td class="ta_01" bgColor="#ffffff"> <input type="text" name="telephone" id="telephone" value="${user.telephone}"/> </td> </tr> <tr> <td align="center" bgColor="#f5fafe" class="ta_01"> 兴趣爱好: </td> <% String[] interest = null; if(u!=null){ interest = u.getInterest(); } %> <td class="ta_01" bgColor="#ffffff" colSpan="3"> <input type="checkbox" name="interest" value="看电影" <% if(interest!=null){ for (String s : interest) { if(s.equals("看电影")){ out.write("checked='checked'"); break; } } } %> /> 看电影 <input type="checkbox" name="interest" value="旅游" <% if(interest!=null){ for (String s : interest) { if(s.equals("旅游")){ out.write("checked='checked'"); break; } } } %> />旅游 <input type="checkbox" name="interest" value="健身" <% if(interest!=null){ for (String s : interest) { if(s.equals("健身")){ out.write("checked='checked'"); break; } } } %> />健身 <input type="checkbox" name="interest" value="购物" <% if(interest!=null){ for (String s : interest) { if(s.equals("购物")){ out.write("checked='checked'"); break; } } } %> />购物 <input type="checkbox" name="interest" value="睡觉" <% if(interest!=null){ for (String s : interest) { if(s.equals("睡觉")){ out.write("checked='checked'"); break; } } } %> />睡觉 </td> </tr> <TR> <TD class="ta_01" align="center" bgColor="#f5fafe"> 备注: </TD> <TD class="ta_01" bgColor="#ffffff" colSpan="3"> <textarea cols="30" rows="3" name="remark" style="WIDTH: 96%">${user.remark}</textarea> </TD> </TR>
6.3、用户数据修改
6.3.1、需求分析
分析:
关键点:
1、ID不需要被修改,需要被从JSP传递给servlet,因为若未传递ID,ID为null
2、修改逻辑:
①查询所有信息
②迭代删除被修改的信息,添加新信息 (新集合)
③新集合以覆盖方式保存新信息
3、路径更改问题
添加、修改、删除
流程:
6.3.2、代码实现
/user/edit.jsp
<form method="post" action="<%=pageContext.getServletContext().getContextPath()%>/user"> <input type="hidden" name="method" value="modifyUser" /> <input type="hidden" name="id" value="${user.id}" />
UserServlet
/** * 修改用户信息 * @return */ public String modifyUser(){ //1、获取所有表单数据 User param = toBean(User.class); //2、调用service进行保存 boolean result = userService.modifyUser(param); //3、根据service保存结果,进行展示 if(result){ //修改成功 return "redirect:/user?method=list"; }else{ //修改失败 getRequest().setAttribute("errorMsg","修改失败"); return "forward:/user/error.jsp"; } }
UserService
/** * 修改用户信息 * @param param * @return */ public boolean modifyUser(User param) { try { //1、查询所有用户信息 List<User> ulist = userDao.searchAll(); //2、迭代删除被修改的用户 if(ulist!=null){ Iterator<User> it = ulist.iterator(); while (it.hasNext()){ User next = it.next(); if(next.getId().equals(param.getId())){ it.remove(); break; } } } //3、向集合追加被修改用户的新信息 ulist.add(param); //4、以覆盖方式写回xml userDao.saveUlist(ulist); } catch (Exception e) { return false; } return true; }
6.4、令牌机制-数据更新操作中BUG说明及解决
问题描述:反复刷新页面就会导致 添加功能被重复执行,添加重复数据
问题解决方案:
解决方案1:直接解决法(规避法)
/** * 添加用户 * @return */ public String addUser(){ //1、接收表单数据 User param = toBean(User.class); //2、调用service进行保存 boolean result = userService.addUser(param); //3、根据service处理结果,做不同的跳转 if(result){ //添加成功 return "redirect:/user?method=list"; }else{ //添加失败 getRequest().setAttribute("errorMsg","添加失败"); return "forward:/user/error.jsp"; } }
对于恶意刷新 Servlet的用户,无法进行避免。
解决方案2:逻辑解决法-令牌机制(以添加操作为例)
令牌:随机的字符串,唯一的不重复。
令牌机制作用:通过发令牌,比对令牌,保障你的操作是唯一不重复的。
本质防止两个基础操作:
重复刷新
恶意访问
/user/list.jsp
<a class="button_add" style="padding: 2px 4px 2px 10px; border: 1px solid #8AA2CC;" href="<%=request.getContextPath() %>/user?method=toAddView" id="add">添加</a>
UserServlet
/** * 跳转到添加页面(起点:发令牌) * @return */ public String toAddView(){ //1、随机生成令牌 String tokenId = UUID.randomUUID().toString().replaceAll("-",""); //2、将令牌备份到session中 getRequest().getSession().setAttribute("addUserTokenId",tokenId); //3、跳转到添加页面 return "redirect:/user/add.jsp"; }
/user/add.jsp
<form name="Form1" method="post" action="<%=pageContext.getServletContext().getContextPath()%>/user" > <input type="hidden" name="addUserTokenId" value="${addUserTokenId}"/>
UserServlet
/** * 添加用户 * @return */ public String addUser(){ //一、(关卡)令牌机制校验 //1、分别获取表单传递而来的令牌(人物自带令牌) 和 session中的令牌 (关卡备份令牌) String addUserTokenId = getRequest().getParameter("addUserTokenId"); String addUserTokenIdFromSession = (String) getRequest().getSession().getAttribute("addUserTokenId"); //2、进行令牌校验 //如果addUserTokenIdFromSession为null或者addUserTokenId为null,说明是非法操作,展示错误信息 //如果两个令牌不一致,说明校验失败,也存在非法操作,展示错误信息 //令牌校验失败,跳转错误页面 if(addUserTokenId==null || addUserTokenIdFromSession==null || !addUserTokenId.equals(addUserTokenIdFromSession)){ getRequest().setAttribute("errorMsg","非法添加操作,请按正常流程进行"); return "forward:/user/error.jsp"; } //3、令牌校验成功,为了防止重复校验,将session中的令牌销毁 getRequest().getSession().removeAttribute("addUserTokenId"); //二、令牌校验完成的,才能进行添加用户操作 //1、接收表单数据 User param = toBean(User.class); //2、调用service进行保存 boolean result = userService.addUser(param); //3、根据service处理结果,做不同的跳转 if(result){ //添加成功 return "forward:/user?method=list"; }else{ //添加失败 getRequest().setAttribute("errorMsg","添加失败"); return "forward:/user/error.jsp"; } }
令牌机制:
起点:发令牌
人物:带令牌
关卡:校验令牌,校验成功销毁关卡令牌
7、UMS-用户登录【阶段2】
7.1、需求说明
7.2、需求分析
分析:
关键点:
1、JavaBean javaBean = toBean(JavaBean.class);
2、登录校验:
service:
若用户名正确,并且密码也正确,登录成功;否则登录失败
用户名正确:遍历用户的用户名 和 表单输入的用户名相同
3、session域对象,请求重定向
登录成功,页面跳转,路径也被改变,说明使用的是请求重定向。
重定向不能使用request作用域传递数据,使用更大的session传递数据
流程:
7.3、代码实现
//
/login/login.jsp <form action="<%=pageContext.getServletContext().getContextPath()%>/login" method="post" target="_parent"> <input type="hidden" name="method" value="login"/> <tr> <td height="30" nowrap> <font color="000F60"><strong>用户名:</strong> </font> </td> <td> <input type="text" name="loginName" class="test" style="width: 160px;"/> </td> </tr> <tr> <td height="30" nowrap> <strong><font color="000F60">密码: </font> </strong> </td> <td> <input type="password" name="loginPwd" class="text" style="width: 160px;"/> </td> </tr> /** * 用户登录 * @return */ public String login(){ //1、接收表单参数 User param = toBean(User.class); //2、调用service进行登录处理 User result = null; try { result = userService.login(param); } catch (Exception e) { //抛出异常,登录也是失败 getRequest().setAttribute("errorMsg",e.getMessage()); return "forward:/login/login.jsp"; } //3、根据返回结果,跳转不同的页面 if(result!=null){ //登录成功 getRequest().getSession().setAttribute("loginUser",result); return "redirect:/index.jsp"; }else{ //登录失败 getRequest().setAttribute("errorMsg","用户名或密码错误"); return "forward:/login/login.jsp"; } }
UserService
/** * 用户登录。 用户登录成功,返回User对象。 登录失败,返回Null * @param param * @return */ public User login(User param) { //1、获取所有用户信息 List<User> ulist = userDao.searchAll(); //2、遍历所有用户信息 if(ulist!=null){ for (User u : ulist) { //3、每遍历一个用户信息,对比表单用户名是否正确,对比表单密码是否正确. 都正确,登录成功 if(u.getLoginName().equals(param.getLoginName()) && u.getLoginPwd().equals(param.getLoginPwd())){ return u; } } } //4、经过遍历,没有一个成功,登录失败 return null; } /login/top.jsp 用户名: <font color="blue">${loginUser.userName}</font></td> /login/login.jsp <strong style="font-size: 14px;color:red;">${errorMsg}</strong>