记录不同客户端访问服务器的次数
由于对不同的客户端需要区分,所以使用session记录不同客户端的数据。由于访问次数需要保留,所以使用setAttribute方法进行记录。第一次访问时存储为1,后续访问在此基础上自增。
步骤一:新建CountServlet
图- 1
步骤二:部署应用,访问
图- 2
步骤三:多次刷新页面查看计数变化
图- 3
步骤四:重启浏览器,查看页面输出
图- 4
步骤五:查看控制台输出窗口
图– 5
结论:sessionID跟随一次会话,存储在客户端浏览器的内存中一个叫JSESSIONID的Cookie里面。第一次创建后,只要不关闭浏览器,那么每一次的请求sessionID都会被自动发送到服务器端。重启浏览器后,sessionID会被销毁,重新创建新的数值。
图- 6
图- 7
图-6为第一次访问,JSESSIONID在响应头中以Set-Cookie的形式传回客户端。图-7为刷新页面时的数据包,在请求头中,JSESSIONID以Cookie消息头的形式发给服务器端,以此同一个ID值找到对应的session对象。
CountServlet.java文件的代码:
package web; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class CountServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //获取session对象 HttpSession session = request.getSession(); //输出sessionID System.out.println(session.getId()); //获取绑定的计数器 Integer count = (Integer)session.getAttribute("count"); if(count==null){//第一次访问 count = 1; }else{//不是第一次访问 count++; } //在session中绑定计数器 session.setAttribute("count", count); //输出提示信息 out.println("这是第"+count+"次访问"); out.close(); } }
web.xml文件代码:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>CountServlet</servlet-name> <servlet-class>web.CountServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CountServlet</servlet-name> <url-pattern>/count</url-pattern> </servlet-mapping> </web-app>
保存登录信息,保护某些资源只有在登录验证之后才能访问。
登录信息提交后进行验证,验证通过则将用户信息保存在session中,验证失败则转发回登录页面。对于需要保护的资源,添加从session中获取绑定值的功能,以判断是否能够成功获取绑定的用户信息为判断依据,获取到则代表已验证,则允许访问,获取不到绑定在session中的用户信息,代码验证没有通过,则拒绝访问该资源,而将请求重定向到登录页面。
步骤一:新建login.jsp页面
图– 8
图- 9
步骤二:新建ActionServlet类及配置
图– 10
图- 11
步骤三:新建index.jsp页面
图- 12
步骤四:部署后直接访问index.jsp页面
部署后访问index.jsp失败,会重定向到login.jsp页面
图- 13
步骤五:在login.jsp页面进行登录
图- 14
步骤六:新开页面后直接访问index.jsp页面
图- 15
在新开的页面直接访问index.jsp页面也能够看到显示的登录信息。
步骤七:重启浏览器后访问index.jsp页面
重启浏览器后,直接访问index.jsp页面,结果与步骤四一致。因为,关闭浏览器后保存的JSESSIONID信息会丢失,以至于无法再在服务器中找到绑定了登录信息的session对象,于是认为没有登录过,进行了重定向操作。
步骤八:修改index.jsp页面,添加“登出”链接
图- 16
步骤九:修改ActionServlet
图- 17
步骤十:重新访问login.jsp进行登录
图- 18
步骤十一:点击“登出”后,再次访问index.jsp
登出后,再次直接输入地址访问index.jsp,结果同步骤四,重定向到login.jsp页面。符合登出功能的效果。
ActionServlet.java文件:
package web; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ActionServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String uri = request.getRequestURI(); String action = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf(".")); HttpSession session = request.getSession(); System.out.println(session.getId()); // 判断动作是否为登录 if (action.equals("login")) { String name = request.getParameter("uname"); String pwd = request.getParameter("pwd"); if (name.equals("111") && pwd.equals("111")) { session.setAttribute("uname", name); // 重定向到首页 response.sendRedirect("index.jsp"); } else { // 登录失败 request.setAttribute("msg", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } } else if (action.equals("logout")) { // session失效 session.invalidate(); response.sendRedirect("login.jsp"); } out.close(); } }
web.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>CountServlet</servlet-name> <servlet-class>web.CountServlet</servlet-class> </servlet> <servlet> <servlet-name>ActionServlet</servlet-name> <servlet-class>web.ActionServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CountServlet</servlet-name> <url-pattern>/count</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ActionServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
login.jsp文件:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <title>Insert title here</title> </head> <body> <h3>登录</h3> <form action="login.do" method="post"> 用户名:<input name="uname"/><Br><br> 密码:<input name="pwd" type="password"/><br><Br> <input type="submit" value="登录"/> </form> </body> </html>
index.jsp文件:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% //session验证 Object uname = session.getAttribute("uname"); if(uname == null){ response.sendRedirect("login.jsp"); return; } %> <html> <head> </head> <body> <h3>首页</h3>欢迎你:<%=uname.toString()%><br><Br><Br> <a href="logout.do">登出</a> </body> </html>
使用编程式,修改session的超时时间为10秒。实现当用户登陆后,如果十秒钟没有任何动作,则session时效,此时再访问index.jsp页面,则依然会重定向到login.jsp页面,重新登录。
使用setMaxInactiveInterval(10)方法实现编程式的session超时设置。时间单位为秒。
步骤一:修改ActionServlet
在创建session后,设置超时时间为10秒。
图- 19
步骤二:访问login.jsp页面后十秒内不操作
访问login.jsp,输入用户信息进行登录,到达index.jsp页面后,不再有任何动作,过十秒后,刷新index.jsp页面,请求会重定向到login.jsp页面。
如果以声明式的方式修改超时时间,则需要到tomcat的conf目录下,寻找web.xml文件,修改session-timeout。
图- 20
ActionServlet.java文件代码:
package web; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ActionServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String uri = request.getRequestURI(); String action = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf(".")); // 判断动作是否为登录 if (action.equals("login")) { String name = request.getParameter("uname"); String pwd = request.getParameter("pwd"); if (name.equals("111") && pwd.equals("111")) { HttpSession session = request.getSession(); System.out.println(session.getId()); // 编程式--设定session超时时间为10秒 session.setMaxInactiveInterval(10); session.setAttribute("uname", name); // 重定向到首页 response.sendRedirect("index.jsp"); } else { // 登录失败 request.setAttribute("msg", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } } else if (action.equals("logout")) { HttpSession session = request.getSession(); // session失效 session.invalidate(); response.sendRedirect("login.jsp"); } out.close(); } }
如果浏览器禁用Cookie,则session不能再继续使用。如何在禁用Cookie的情况下依然能继续使用session。
使用URL重写的方法,即改写原本的访问地址,在URI后面使用参数的方式携带上sessionID。
步骤一:修改ActionServlet
图- 21
步骤二:禁用浏览器Cookie
图- 22
步骤三:使用login.jsp完成登录
图 - 23
由于禁用了cookie,所以要想继续使用session那么就可以通过如上方式,在URL中添加sessionID信息,以达到传递id标识的作用。
ActionServlet.java文件代码:
package web; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ActionServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String uri = request.getRequestURI(); String action = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf(".")); HttpSession session = request.getSession(); System.out.println(session.getId()); // 编程式--设定session超时时间为10秒 //session.setMaxInactiveInterval(10); // 判断动作是否为登录 if (action.equals("login")) { String name = request.getParameter("uname"); String pwd = request.getParameter("pwd"); if (name.equals("111") && pwd.equals("111")) { session.setAttribute("uname", name); // 重定向到首页 response.sendRedirect( response.encodeRedirectURL("index.jsp")); } else { // 登录失败 request.setAttribute("msg", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } } else if (action.equals("logout")) { // session失效 session.invalidate(); response.sendRedirect("login.jsp"); } out.close(); } }
根据随机产生的字符串绘制图片,并输出到jsp页面中
使用java的绘图技术,动态绘制一张图片,由Servlet完成后,通过OutputStream将其内容输出到客户端。浏览器通过img标签的src属性访问该Servlet以获得动态图片。
步骤一:创建validateCode.jsp页面
图- 24
步骤二:创建ValidateCode.java文件
图- 25
步骤三:部署后访问查看图片
图- 26
ValidateCode.java文件代码:
package web; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ValidateCode extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.创建空白图片 BufferedImage image = new BufferedImage(100,30,BufferedImage.TYPE_INT_RGB); //1.获取图片画笔 Graphics g = image.getGraphics(); Random r = new Random(); //2.设置画笔颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); //3.绘制矩形的背景 g.fillRect(0, 0, 100, 30); //4.调用自定义的方法,获取长度为5的字母数字组合的字符串 String number = getNumber(5); g.setColor(new Color(0,0,0)); g.setFont(new Font(null,Font.BOLD,24)); //5.设置颜色字体后,绘制字符串 g.drawString(number, 5, 25); //6.绘制8条干扰线 for(int i=0;i<8;i++){ g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255),r.nextInt(255))); g.drawLine(r.nextInt(100), r.nextInt(30), r.nextInt(100), r.nextInt(30)); } response.setContentType("image/jpeg"); OutputStream ops = response.getOutputStream(); ImageIO.write(image, "jpeg", ops); ops.close(); } private String getNumber(int size){ String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; String number = ""; Random r = new Random(); for(int i=0;i<size;i++){ number+=str.charAt(r.nextInt(str.length())); } return number; } }
validateCode.jsp文件代码:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <title>Insert title here</title> <style type="text/css"> .s1{ cursor:pointer; } </style> </head> <body> 验证码:<input name="vcode"/> <img src="code" onclick="this.src='code?'+Math.random();" class="s1" title="点击更换" /> </body> </html>
web.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>ValidateCode</servlet-name> <servlet-class>web.ValidateCode</servlet-class> </servlet> <servlet-mapping> <servlet-name>ValidateCode</servlet-name> <url-pattern>/code</url-pattern> </servlet-mapping> </web-app>
在登录时添加验证码功能。
在产生验证码的随机字符串之后,绑定到session中,验证过程中将用户输入和session绑定中的验证码比对一致后再判断用户名和密码。
步骤一:修改ValidateCode.java文件
图 - 27
步骤二:修改login.jsp页面
图– 28
图 - 29
步骤三:修改ActionServlet.java文件
图 - 30
步骤四:重新部署,访问应用
用户名和密码以及验证码均正确的情况下登录成功。验证码区分大小写。登出后直接访问index.jsp会自动回到login.jsp页面。
ValidateCode.java文件:
package web; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ValidateCode extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.创建空白图片 BufferedImage image = new BufferedImage(100,30,BufferedImage.TYPE_INT_RGB); //1.获取图片画笔 Graphics g = image.getGraphics(); Random r = new Random(); //2.设置画笔颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); //3.绘制矩形的背景 g.fillRect(0, 0, 100, 30); //4.调用自定义的方法,获取长度为5的字母数字组合的字符串 String number = getNumber(5); HttpSession session = request.getSession(); session.setAttribute("code", number); g.setColor(new Color(0,0,0)); g.setFont(new Font(null,Font.BOLD,24)); //5.设置颜色字体后,绘制字符串 g.drawString(number, 5, 25); //6.绘制8条干扰线 for(int i=0;i<8;i++){ g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255),r.nextInt(255))); g.drawLine(r.nextInt(100), r.nextInt(30), r.nextInt(100), r.nextInt(30)); } response.setContentType("image/jpeg"); OutputStream ops = response.getOutputStream(); ImageIO.write(image, "jpeg", ops); ops.close(); } private String getNumber(int size){ String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; String number = ""; Random r = new Random(); for(int i=0;i<size;i++){ number+=str.charAt(r.nextInt(str.length())); } return number; } }
login.jsp文件:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <title>Insert title here</title> <style type="text/css"> .s1{ cursor:pointer; } </style> </head> <body> <h3>登录</h3> <form action="login.do" method="post"> 用户名:<input name="uname"/><Br><br> 密码:<input name="pwd" type="password"/><br><Br> 验证码:<input name="vcode"/> <img src="code" onclick="this.src='code?'+Math.random();" class="s1" title="点击更换" /><br><Br> <input type="submit" value="登录"/> </form> </body> </html>
ActionServlet文件:
package web; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ActionServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String uri = request.getRequestURI(); String action = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf(".")); // 判断动作是否为登录 if (action.equals("login")) { String name = request.getParameter("uname"); String pwd = request.getParameter("pwd"); String number = request.getParameter("vcode"); HttpSession session = request.getSession(); String code = session.getAttribute("code").toString(); if (number.equals(code) && name.equals("111") && pwd.equals("111")) { // 编程式--设定session超时时间为10秒 //session.setMaxInactiveInterval(10); session.setAttribute("uname", name); // 重定向到首页 //response.sendRedirect("index.jsp"); response.sendRedirect( response.encodeRedirectURL("index.jsp")); } else { // 登录失败 request.setAttribute("msg", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } } else if (action.equals("logout")) { HttpSession session = request.getSession(); // session失效 session.invalidate(); response.sendRedirect("login.jsp"); } out.close(); } }
web.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>CountServlet</servlet-name> <servlet-class>web.CountServlet</servlet-class> </servlet> <servlet> <servlet-name>ActionServlet</servlet-name> <servlet-class>web.ActionServlet</servlet-class> </servlet> <servlet> <servlet-name>ValidateCode</servlet-name> <servlet-class>web.ValidateCode</servlet-class> </servlet> <servlet-mapping> <servlet-name>CountServlet</servlet-name> <url-pattern>/count</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ActionServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ValidateCode</servlet-name> <url-pattern>/code</url-pattern> </servlet-mapping> </web-app>