《Servlet、JSP和Spring MVC初学指南》——2.3 Cookies

    xiaoxiao2024-01-20  161

    本节书摘来自异步社区《Servlet、JSP和Spring MVC初学指南》一书中的第2章,第2.3节,作者:【加】Budi Kurniawan(克尼亚万) , 【美】Paul Deck著,更多章节内容可以访问云栖社区“异步社区”公众号查看

    2.3 Cookies

    URL重写和隐藏域仅适合保存无须跨越太多页面的信息。如果需要在多个页面间传递信息,则以上两种技术实现成本高昂,因为你不得不在每个页面都进行相应处理。幸运的是,Cookies技术可以帮助我们。

    Cookies是一个很少的信息片段,可自动地在浏览器和Web服务器间交互,因此cookies可存储在多个页面间传递的信息。Cookie作为HTTP header的一部分,其传输由HTTP协议控制。此外,你可以控制cookies的有效时间。浏览器通常支持每个网站高达20个cookies。

    Cookies的问题在于用户可以通过改变其浏览器设置来拒绝接受cookies。

    要使用cookies,需要熟悉javax.servlet.http.Cookie类以及HttpServletRequest和HttpServlet Response两个接口。

    可以通过传递name和value两个参数给Cookie 类的构造函数来创建一个cookies:

    Cookie cookie = new Cookie(name, value);如下是一个创建语言选择的cookie示例:

    Cookie languageSelectionCookie = new Cookie("language", "Italian");创建完一个Cookie对象后,你可以设置domain、path和maxAge属性。其中,maxAge 属性决定cookie何时过期。

    要将cookie发送到浏览器,需要调用HttpServletResponse的add方法:

    httpServletResponse.addCookie(cookie);浏览器在访问同一Web服务器时,会将之前收到的cookie一并发送。

    此外,Cookies也可以通过客户端的javascript脚本创建和删除,不过这些不在本书范围内。

    服务端若要读取浏览器提交的cookie,可以通过HttpServletRequest接口的getCookies方法,该方法返回一个Cookie数组,若没有cookies则返回null。你需要遍历整个数组来查询某个特定名称的cookie。如下为查询名为maxRecords的cookie的示例:

    Cookie[] cookies = request.getCookies(); Cookie maxRecordsCookie = null; if (cookies != null) { for (Cookie cookie : cookies) { if (cookie.getName().equals("maxRecords")) { maxRecordsCookie = cookie; break; } } }

    目前,还没有类似于getCookieByName这样的方法来帮助简化工作。此外,也没有一个直接的方法来删除一个cookie,你只能创建一个同名的cookie,并将maxAge属性设置为0,并添加到HttpServletResponse接口中。如下为删除一个名为userName的cookie代码:

    Cookie cookie = new Cookie("userName", ""); cookie.setMaxAge(0); response.addCookie(cookie);

    清单2.4的PreferenceServlet 类展示了如何通过cookies来进行会话管理,该Servlet允许用户通过修改四个cookie值来设定显示配置。

    清单2.4 PreferenceServlet类

    package app02a.cookie; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "PreferenceServlet", urlPatterns = { "/preference" }) public class PreferenceServlet extends HttpServlet { private static final long serialVersionUID = 888L; public static final String MENU = "<div style='background:#e8e8e8;" + "padding:15px'>" + "<a href='cookieClass'>Cookie Class</a>  " + "<a href='cookieInfo'>Cookie Info</a>  " + "<a href='preference'>Preference</a>" + "</div>"; @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.print("<html><head>" + "<title>Preference</title>" + "<style>table {" + "font-size:small;" + "background:NavajoWhite }</style>" + "</head><body>" + MENU + "Please select the values below:" + "<form method='post'>" + "<table>" + "<tr><td>Title Font Size: </td>" + "<td><select name='titleFontSize'>" + "<option>large</option>" + "<option>x-large</option>" + "<option>xx-large</option>" + "</select></td>" + "</tr>" + "<tr><td>Title Style & Weight: </td>" +"<td><select name='titleStyleAndWeight' multiple>" + "<option>italic</option>" + "<option>bold</option>" + "</select></td>" + "</tr>" + "<tr><td>Max. Records in Table: </td>" + "<td><select name='maxRecords'>" + "<option>5</option>" + "<option>10</option>" + "</select></td>" + "</tr>" + "<tr><td rowspan='2'>" + "<input type='submit' value='Set'/></td>" + "</tr>" + "</table>" + "</form>" + "</body></html>"); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String maxRecords = request.getParameter("maxRecords"); String[] titleStyleAndWeight = request .getParameterValues("titleStyleAndWeight"); String titleFontSize = request.getParameter("titleFontSize"); response.addCookie(new Cookie("maxRecords", maxRecords)); response.addCookie(new Cookie("titleFontSize", titleFontSize)); // delete titleFontWeight and titleFontStyle cookies first // Delete cookie by adding a cookie with the maxAge = 0; Cookie cookie = new Cookie("titleFontWeight", ""); cookie.setMaxAge(0); response.addCookie(cookie); cookie = new Cookie("titleFontStyle", ""); cookie.setMaxAge(0); response.addCookie(cookie); if (titleStyleAndWeight != null) { for (String style : titleStyleAndWeight) { if (style.equals("bold")) { response.addCookie(new Cookie("titleFontWeight", "bold")); } else if (style.equals("italic")) { response.addCookie(new Cookie("titleFontStyle", "italic")); } } } response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.println("<html><head>" + "<title>Preference</title>" + "</head><body>" + MENU + "Your preference has been set." + "<br/><br/>Max. Records in Table: " + maxRecords + "<br/>Title Font Size: " + titleFontSize + "<br/>Title Font Style & Weight: "); // titleStyleAndWeight will be null if none of the options // was selected if (titleStyleAndWeight != null) { writer.println("<ul>"); for (String style : titleStyleAndWeight) { writer.print("<li>" + style + "</li>"); } writer.println("</ul>"); } writer.println("</body></html>"); } }

    PreferenceServlet的doGet方法展示一个包含多个输入项的表单,如图2.6所示。

    图2.6 通过cookies来管理用户偏好

    表单上部有3个链接:Cookie Class、Cookie Info和Preference。它们可以导航到本应用的其他Servlet上。关于Cookie Class和Cookie Info,我们稍后介绍。

    当用户提交表单时,Web服务器会调用PreferenceServlet的doPost方法,该方法创建4个cookies,即maxRecords、titleFontSize、titleFontStyle和titleFontWeight,并覆盖该cookie之前的值,然后将用户输入的值返回给浏览器。

    可以通过如下URL访问PreferenceServlet:

    http://localhost:8080/app02a/preferenceCookieClassServlet(见清单2.5)和CookieInfoServlet(见清单2.6)各自应用这些cookie来格式化其内容。CookieClassServlet将Cookie的属性展示为一个HTML列表。

    Cookie中的max Records值决定显示多少个列表项,可通过Preference Servlet调整该值。

    清单2.5 CookieClassServlet类

    package app02a.cookie; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "CookieClassServlet", urlPatterns = { "/cookieClass" }) public class CookieClassServlet extends HttpServlet { private static final long serialVersionUID = 837369L; private String[] methods = { "clone", "getComment", "getDomain", "getMaxAge", "getName", "getPath", "getSecure", "getValue", "getVersion", "isHttpOnly", "setComment", "setDomain", "setHttpOnly", "setMaxAge", "setPath", "setSecure", "setValue", "setVersion" }; @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie[] cookies = request.getCookies(); Cookie maxRecordsCookie = null; if (cookies != null) { for (Cookie cookie : cookies) { if (cookie.getName().equals("maxRecords")) { maxRecordsCookie = cookie; break; } } } int maxRecords = 5; // default if (maxRecordsCookie != null) { try { maxRecords = Integer.parseInt( maxRecordsCookie.getValue()); } catch (NumberFormatException e) { // do nothing, use maxRecords default value } } response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.print("<html><head>" + "<title>Cookie Class</title>" + "</head><body>" + PreferenceServlet.MENU + "<div>Here are some of the methods in " + "javax.servlet.http.Cookie"); writer.print("<ul>"); for (int i = 0; i < maxRecords; i++) { writer.print("<li>" + methods[i] + "</li>"); } writer.print("</ul>"); writer.print("</div></body></html>"); } }

    CookieInfoServlet 类读取titleFontSize、titleFontWeight和titleFontStyle 三个cookie值,并写入到如下发给浏览器的CSS中,其中x、y和z分别为如上所提的cookie。

    .title { font-size: x; font-weight: y; font-style: z; }

    该style应用在一个div元素中,并格式化文字“Session Management with Cookies:”。

    清单2.6 CookieInfoServlet类

    package app02a.cookie; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "CookieInfoServlet", urlPatterns = { "/cookieInfo" }) public class CookieInfoServlet extends HttpServlet { private static final long serialVersionUID = 3829L; @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie[] cookies = request.getCookies(); StringBuilder styles = new StringBuilder(); styles.append(".title {"); if (cookies != null) { for (Cookie cookie : cookies) { String name = cookie.getName(); String value = cookie.getValue(); if (name.equals("titleFontSize")) { styles.append("font-size:" + value + ";"); } else if (name.equals("titleFontWeight")) { styles.append("font-weight:" + value + ";"); } else if (name.equals("titleFontStyle")) { styles.append("font-style:" + value + ";"); } } } styles.append("}"); response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.print("<html><head>" + "<title>Cookie Info</title>" + "<style>" + styles.toString() + "</style>" + "</head><body>" + PreferenceServlet.MENU + "<div class='title'>" + "Session Management with Cookies:</div>"); writer.print("<div>"); // cookies will be null if there's no cookie if (cookies == null) { writer.print("No cookie in this HTTP response."); } else { writer.println("<br/>Cookies in this HTTP response:"); for (Cookie cookie : cookies) { writer.println("<br/>" + cookie.getName() + ":" + cookie.getValue()); } } writer.print("</div>"); writer.print("</body></html>"); } }

    可以通过如下URL来访问CookieClassServlet:

    http://localhost:8080/app02a/cookieClass可以通过如下URL来访问CookieInfoServlet:

    http://localhost:8080/app02a/cookieInfo图2.7和图2.8分别展示了CookieClassServlet和CookieInfoServlet的显示界面。

    图2.7 CookieClassServlet输出

    图2.8 CookieInfoServlet输出

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)