6.5 创建登录业务的Filter
创建UserLoginFilter实现未登录拦截。
package com.zj.web.filter; import com.sun.org.apache.bcel.internal.Const; import com.zj.commons.Constants; import com.zj.pojo.User; import jdk.nashorn.internal.objects.NativeArray; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionAttributeListener; import java.io.IOException; /*判断当前客户端浏览器是否登录的Filter*/ @WebFilter("/*") public class UserLoginFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String uri = request.getRequestURI(); //判断当前路径是否是login.jsp或者login.do,放行这两个资源,还需要放行验证码图片。 if (uri.indexOf("login.jsp") != -1 || uri.indexOf("login.do") != -1 || uri.indexOf("ValidateCodeServlet.do")!= -1) { filterChain.doFilter(request,response); }else { HttpSession session = request.getSession(); User user = (User) session.getAttribute(Constants.USER_SESSION_KEY); if (user != null) { filterChain.doFilter(request,response); }else { request.setAttribute(Constants.REQUEST_MSG,"不登陆不好使!(⊙o⊙)?"); request.getRequestDispatcher("login.jsp").forward(request, response); } } } @Override public void destroy() { } }
6.6 实现用户只能在一处登录
当前的一个账号可以在多个浏览器登录,我们要实现的是账号在另一个浏览器登陆的时候会挤掉当前浏览器的账户。
实现的原理是将当前用户的session放在context中缓存,用户在当前浏览器登录的时候首先查看context中是否存在当前用户的session信息,存在的话表示当前用户在其他浏览器已经登录过了,则删除该之前浏览器和服务端之间的会话session,重新建立当前浏览器与服务端的session连接,并将该session保存到context中。
6.7 解决HttpSession超时销毁时的异常问题
6.6实现了用户只能在一处登录,但是session有自动销毁的时间是半个小时。此时session被tomcat销毁但是context还保存着已经被销毁的session的信息,再使用另一个浏览器登陆时仍然能拿到这个被销毁的session,再一次销毁这个session的时候就会报错,因为之前已经被tomcat销毁了嘛。此时可以通过listener监听器来监听session的声明周期。
package com.zj.web.listener; import com.zj.commons.Constants; import com.zj.pojo.User; import javax.servlet.ServletContext; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; @WebListener public class HttpSessionLifeListener implements HttpSessionListener { /*HttpSession被销毁之前触发该方法*/ @Override public void sessionDestroyed(HttpSessionEvent se) { //获取servletContext对象,将保存在context中的即将被销毁的session删除。 HttpSession session = se.getSession(); ServletContext servletContext = session.getServletContext(); User user = (User) servletContext.getAttribute(Constants.USER_SESSION_KEY); servletContext.removeAttribute(user.getUserid()+""); } }
6.8 在登录中添加验证码功能
首先将生成验证码的servlet工具类添加到项目中
package com.zj.commons; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; @WebServlet("/ValidateCodeServlet.do") public class ValidateCodeServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 在内存中创建图象 int width = 70, height = 45; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics g = image.getGraphics(); // 生成随机类 Random random = new Random(); // 设定背景色 g.setColor(getRandColor(200, 250)); g.fillRect(0, 0, width, height); // 设定字体 g.setFont(new Font("Times New Roman", Font.PLAIN, 20)); // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到 g.setColor(getRandColor(160, 200)); for (int i = 0; i < 155; i++) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x, y, x + xl, y + yl); } // 取随机产生的认证码(4位数字) String sRand = ""; for (int i = 0; i < 4; i++) { String rand = String.valueOf(random.nextInt(10)); sRand += rand; // 将认证码显示到图象中 g.setColor(new Color(20 + random.nextInt(110), 20 + random .nextInt(110), 20 + random.nextInt(110))); // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成 g.drawString(rand, 13 * i + 6, 16); } // 图象生效 g.dispose(); try { ImageIO.write(image, "JPEG", response.getOutputStream()); } catch (Exception e) { System.out.println("验证码图片产生出现错误:" + e.toString()); } //保存验证码到Session request.getSession().setAttribute("randStr", sRand); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } /* * 给定范围获得随机颜色 */ private Color getRandColor(int fc, int bc) { Random random = new Random(); if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } }
修改登录页面在login.jsp中添加验证码标签img,定义函数change每次点击验证码都会更换。
<img id="code" src="ValidateCodeServlet.do" onclick="change"/>
/*点击验证码图片生成验证码*/ function change() { $("#code").attr("src","ValidateCodeServlet.do?"+Math.random()) }
在 UserLoginFilter过滤器中放行验证码图片资源。
if (uri.indexOf("login.jsp") != -1 || uri.indexOf("login.do") != -1 || uri.indexOf("ValidateCodeServlet.do")!= -1) { filterChain.doFilter(request,response); }
在UserLoginServlet中实现验证码的校验。
6.9 用户退出功能
在left.jsp页面添加退出功能的标签。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> </html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <link href="css/style.css" rel="stylesheet" type="text/css" /> <script language="JavaScript" src="js/jquery.js"></script> <script type="text/javascript"> $(function(){ //导航切换 $(".menuson .header").click(function(){ var $parent = $(this).parent(); $(".menuson>li.active").not($parent).removeClass("active open").find('.sub-menus').hide(); $parent.addClass("active"); if(!!$(this).next('.sub-menus').size()){ if($parent.hasClass("open")){ $parent.removeClass("open").find('.sub-menus').hide(); }else{ $parent.addClass("open").find('.sub-menus').show(); } } }); // 三级菜单点击 $('.sub-menus li').click(function(e) { $(".sub-menus li.active").removeClass("active") $(this).addClass("active"); }); $('.title').click(function(){ var $ul = $(this).next('ul'); $('dd').find('.menuson').slideUp(); if($ul.is(':visible')){ $(this).next('.menuson').slideUp(); }else{ $(this).next('.menuson').slideDown(); } }); }) </script> </head> <body style="background:#f0f9fd;"> <div class="lefttop"><span></span>导航菜单</div> <dl class="leftmenu"> <dd> <div class="title"><span><img src="images/leftico03.png" /></span>用户管理</div> <ul class="menuson"> <li><cite></cite><a href="userAdd.jsp" target="rightFrame">添加用户</a><i></i></li> <li><cite></cite><a href="findUser.jsp" target="rightFrame">查询用户</a><i></i></li> <li><cite></cite><a href="logout.do" target="rightFrame">退出登录</a><i></i></li> </ul> </dd> </dl> </body> </html>
创建用户退出登录的servlet
package com.zj.web.servlet; 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 javax.servlet.http.HttpSession; import java.io.IOException; /*用户退出*/ @WebServlet("/logout.do") public class LogoutServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); //因为配置了监听器,在session销毁的时候会调用监听器的方法,删除context中的session session.invalidate(); //重定向到登录页面 resp.sendRedirect("login.jsp"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } }
七、添加用户业务
7.1 创建添加用户持久层
创建接口和实现类
package com.zj.dao; import com.zj.pojo.User; public interface UserManageDao { //用户添加 void insertUser(User user); }
package com.zj.dao.impl; import com.zj.commons.jdbcUtils; import com.zj.dao.UserManageDao; import com.zj.pojo.User; import java.sql.Connection; import java.sql.PreparedStatement; public class UserManageDaoImpl implements UserManageDao { @Override public void insertUser(User user) { Connection con = null; try { con = jdbcUtils.getConnection(); //关闭自动提交事务,加深对事务印象 con.setAutoCommit(false); PreparedStatement ps = con.prepareStatement("INSERT INTO users values (default ,?,?,?,?,?)"); ps.setString(1, user.getUsername()); ps.setString(2, user.getUserpwd()); ps.setString(3, user.getUsersex()); ps.setString(4, user.getPhonenumber()); ps.setString(5, user.getQqnumber()); ps.executeUpdate(); con.commit(); }catch (Exception e) { e.printStackTrace(); //出现异常回滚 jdbcUtils.rollbackConnection(con); }finally { jdbcUtils.closeConnection(con); } } }
7.2 创建添加用户业务层
创建添加用户的接口和实现类
package com.zj.service; import com.zj.pojo.User; public interface UserManageService { void addUser(User user); }
package com.zj.service.Impl; import com.zj.dao.UserManageDao; import com.zj.dao.impl.UserManageDaoImpl; import com.zj.pojo.User; import com.zj.service.UserManageService; public class UserManageServiceImpl implements UserManageService { /*添加用户*/ @Override public void addUser(User user) { UserManageDao userManageDao = new UserManageDaoImpl(); userManageDao.insertUser(user); } }
7.3 创建添加用户servlet
package com.zj.web.servlet; import com.zj.pojo.User; import com.zj.service.Impl.UserManageServiceImpl; import com.zj.service.UserManageService; 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; @WebServlet("/userManage.do") public class UserManageServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String flag = req.getParameter("flag"); if ("add".equals(flag)) { addUser(req, resp); } } //添加用户 private void addUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ User user = this.createUser(request, response); try { UserManageService userManagerService = new UserManageServiceImpl(); userManagerService.addUser(user); response.sendRedirect("ok.jsp"); //重定向防止数据重复提交 }catch (Exception e) { e.printStackTrace(); response.sendRedirect("error.jsp"); } } //获取用户提交的数据 private User createUser(HttpServletRequest request,HttpServletResponse response){ String username = request.getParameter("username"); String userpwd = request.getParameter("userpwd"); String usersex = request.getParameter("usersex"); String phonenumber = request.getParameter("phonenumber"); String qqnumber = request.getParameter("qqnumber"); User user = new User(0,username, userpwd, usersex, phonenumber, qqnumber); return user; } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } }
7.4 创建添加用户页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <link href="../css/style.css" rel="stylesheet" type="text/css" /> <link href="../css/style.css" rel="stylesheet" type="text/css" /> <link href="../css/select.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="../js/jquery.js"></script> <script type="text/javascript" src="../js/jquery.idTabs.min.js"></script> <script type="text/javascript" src="../js/select-ui.min.js"></script> <script type="text/javascript" src="editor/kindeditor.js"></script> <script type="text/javascript" src="My97DatePicker/WdatePicker.js"></script> <script type="text/javascript"> $(document).ready(function(e) { $(".select1").uedSelect({ width : 345 }); }); function save(){ window.location='ok.html'; } </script> <script type="text/javascript"> KE.show({id:"ecp",width:"800px",height:"300px"}); </script> </head> <body> <div class="place"> <span>位置:</span> <ul class="placeul"> <li><a href="#">用户管理</a></li> <li><a href="#">添加用户</a></li> </ul> </div> <div class="formbody"> <div class="formtitle"><span>添加用户</span></div> <form action="../userManage.do" method="post"> <%--当前是添加用户信息--%> <input type="hidden" name="flag" value="add"/> <ul class="forminfo"> <li> <label>用户名</label> <input name="username" type="text" class="dfinput" /></li> <li> <li> <label>用户密码</label> <input name="userpwd" type="text" class="dfinput" /><i></i></li> <li> <label>性别</label> <input name="usersex" type="radio" value="1" checked="checked" />男 <input name="usersex" type="radio" value="0" />女 </li> <li> <label>联系方式</label> <input name="phonenumber" type="text" class="dfinput" /> </li> <li> <label>QQ号</label> <input name="qqnumber" type="text" class="dfinput" /> </li> <li> <label> </label> <input type="submit" class="btn" value="确认保存" /> </li> </ul> </form> </div> </body> </html>
创建添加成功的页面ok.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <link href="css/style.css" rel="stylesheet" type="text/css" /> <script type="text/javascript"> function submitForm(){ window.close(); } </script> </head> <body> <div class="place"> <span>位置:</span> <ul class="placeul"> <li><a href="#">操作提示</a></li> </ul> </div> 操作成功! </body> </html>