一、RequestDispatcher接口
1、请求转发和请求重定向的区别
ServletRequest:是一个域对象。内部维护了一个Map<String,Object>
Object getAttribute(String name):
void setAttribute(String name,Object obj):
void removeAttribute(String name):
重定向:客户端行为
HttpServletResponse.setState(302);
HttpServletResponse.setHeader("Location",String url);
或者
HttpServletResponse.sendRedirect(String url);等同以上2句代码
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // 重定向演示 public class ServletDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("demo", "text"); // 返回特征码,进行重定向 // response.setStatus(302); // response.setHeader("Location", "/review_day06/servlet/ServletDemo2"); response.sendRedirect("/review_day06/servlet/ServletDemo2"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String value = (String) request.getAttribute("demo"); if (value != null) response.getOutputStream().write(value.getBytes()); else response.getOutputStream().write("value is null.<br/>".getBytes()); response.getOutputStream().write("This is Demo2".getBytes()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
结果:
value is null. This is Demo2
客户端发送了两次请求,且两次请求并不是同一个,故:
源组件和目标组件中的request并不是同一个,所以不能实现数据的共享。
转发:服务器行为
方式一:
RequestDispatcher rd = ServletContext.getRequestDispatcher(String path):必须以"/"开头。path只能使用绝对路径
方式二:
RequestDispatcher rd = request.getRequestDispatcher(String path):如果以"/"开头,表示使用绝对路径;不以"/"开头,表示相对路径。
import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //转发演示 public class ServletDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("demo", "text"); //RequestDispatcher rd = request.getRequestDispatcher("/servlet/ServletDemo4"); //此处使用"/review_day06/servlet/ServletDemo4"报错;使用ServletDemo4不报错;/servlet/ServletDemo4不报错 RequestDispatcher rd = getServletContext().getRequestDispatcher("/servlet/ServletDemo4"); //此处使用"/review_day06/servlet/ServletDemo4"报错;使用ServletDemo4也报错 rd.forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo4 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String value = (String) request.getAttribute("demo"); response.getOutputStream().write((value+"<br/>").getBytes()); response.getOutputStream().write("This is demo4".getBytes()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
结果:
text This is demo4
转发时,客户端只发送了一次请求,源组件和目标组件中的request是同一个,可以实现数据共享。
**扩展知识点:各种URL地址的写法。
相对路径:实际开发中不建议使用。
绝对路径:建议使用方式。
绝对路径的写法:
如果是给服务器用的地址:"/"代表当前应用 /day06
如果是给客户端用的地址:"/"并不代表当前应用,只是区分相对路径用的。需要加上/day06
sendRedirect(String url): url要加 /day06
href: 要加 /day06
form-->action:要加 /day06
请求转发:不要加 /day06
2、包含
源组件包含目标组件:共享请求和响应对象的数据。
目标组件的输出都会出现在源组件中。
目标组件设置的所有响应码头无效。
import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //include演示 //源组件 public class ServletDemo5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("这是demo5<br/>"); RequestDispatcher rd = request.getRequestDispatcher("/servlet/ServletDemo6"); rd.include(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //目标组件 public class ServletDemo6 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("这是demo6"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
结果:
这是demo5 这是demo6
二、会话技术概述
1、什么是会话?如同打电话
2、会话过程中主要解决的问题是保存用户的数据
3、开发技术:
a、cookie技术:客户端技术
响应消息:Set-Cookie:
请求消息:Cookie:
b、session技术:服务器端技术
三、Cookie概述:API
1、Cookie是Servlet向客户端写的小数据信息。这些信息被浏览器保存在自己的缓存目录中。再次请求服务器资源时能带过去。
2、Cookie的属性:
name:必须要的属性。
value:必须要的属性。
------------------------------------------------
以下属性可选:
comment:
path:生成cookie的资源路径。区分重名cookie的。
http://localhost:8080/day06/servlet/ServletDemo1
path:/day06/servlet
带Cookie问题:
localost/day06/servlet : lastAccessTime Cookie
访问路径:http://www.baidu.com/index.jsp 不会带,域名不同
访问路径:http://localhost:8080/day06 会带
访问路径:http://localhost:8080/day06/servlet/a/b/ServletDemo2 不会
如果把cookie的path设置为了当前应用:“/day06”,意味着访问day06下面的任何资源,浏览器都会带cookie过来。
domain:域。默认是生成Cookie的域名。
maximum age:设置Cookie的最大存活时间。默认值最大存活时间是浏览器进程(会话范围)。如果值0,代表要删除该cookie,注意domain/path
version:
每个浏览器客户端最多能放300个cookie。对每一个网站做多能放20个cookie;每一个cookie的大小不能超过4KB。
域名+路径+name(domain+path+name):唯一确定一个Cookie
3、如何向客户端写Cookie:HttpServletResponse.addCookie(Cookie c)(原理:response.setHeader("Set-Cookie","name=value");
4、服务器如何获取客户端带来的Cookie。HttpServletRequest.getCookies()(原理:request.getHeader("Cookie"));
四、Cookie案例:
1、记录最后一次的访问时间:帮助大家理解Cookie原理的。
import java.io.IOException; import java.io.PrintWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* * 显示用户上次的访问时间 * name = value-->lastAccessTime = ; * * 思路: * 1.需要获取cookie,从cookie中取出最后的访问时间返回给客户端; * 2.将新的访问时间写回给cookie * */ public class CookieDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write("上次访问的时间是:"); //从cookie中取出最后的访问时间返回给客户端; //1.获取所有的Cookie Cookie[] cookies = request.getCookies(); //2.从中取出值为lastAccessTime的Cookie for(int i=0;cookies!=null&&i<cookies.length;i++){ if("lastAccessTime".equals(cookies[i].getName())){ long time = Long.parseLong(cookies[i].getValue());//得到上次访问的时间 Date d = new Date(time); DateFormat df = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); //将获得的时间响应给浏览器 out.write(df.format(d)); } } //3.将本次访问的时间写回给cookie Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+""); cookie.setMaxAge(24*60*60);//cookie保存时间 cookie.setPath(request.getContextPath());//request.getContextPath()等同于/review_day06 response.addCookie(cookie); //4.删除cookie out.write("<a href='"+request.getContextPath()+"/servlet/CookieDemo2'>清除</a>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //清除cookie public class CookieDemo2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = new Cookie("lastAccessTime", ""); cookie.setPath(request.getContextPath()); cookie.setMaxAge(0); response.addCookie(cookie); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
结果:
2、记住登陆用户名
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //功能:1.提供登录的UI界面;2.显示已保存的用户名 public class LoginUIServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username=""; String checked = ""; //显示已保存的用户名 Cookie cookies[] = request.getCookies(); for(int i=0;cookies!=null&&i<cookies.length;i++){ if("userInfo".equals(cookies[i].getName())){ username = cookies[i].getValue(); checked="checked='checked'"; break; } } //提供登陆的界面 response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write("<form action='"+request.getContextPath()+"/servlet/LoginServlet' method='post'>"); out.write("用户名:<input type='text' name='username' value='"+username+"'/><br/>"); out.write("密码:<input type='password' name='password'/><br/>"); out.write("<input type='checkbox' name='remember' "+checked+"/>记住用户名<br/>"); out.write("<input type='submit' value='登陆'/><br/>"); out.write("</form>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String username = request.getParameter("username"); String password = request.getParameter("password"); String remember = request.getParameter("remember"); //验证用户、密码暂略 out.write("欢迎您:"+username); // if(remember==null){ //当不选中 记住用户名 时,删除cookie Cookie cookie = new Cookie("userInfo", ""); cookie.setPath(request.getContextPath()); cookie.setMaxAge(0); response.addCookie(cookie); }else{ //当选中 记住用户名 时,则保存cookie Cookie cookie = new Cookie("userInfo", username); cookie.setPath(request.getContextPath()); cookie.setMaxAge(Integer.MAX_VALUE); response.addCookie(cookie); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
结果:
3、购物网站:记住最近的浏览产品记录
import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // 功能:1.列出所有的商品列表;2.列出用户近期的浏览记录;3.提供购买链接 // cookis以bookHistory命名 public class ShowAllBooksServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); // 显示左右的书,并提供购买链接 out.write("<a>本站有以下商品:</a><hr/>"); Map<String, Book> books = BookDB.findAllBooks(); for (Map.Entry<String, Book> me : books.entrySet()) { out.write(me.getValue().getName() + "  <a target='_blank' href='" + request.getContextPath() + "/servlet/ShowDetailsServlet?id=" + me.getKey() + "'>查看</a><hr/>"); } out.write("最近查看的商品如下<hr/>"); Cookie[] cookies = request.getCookies(); for (int i = 0; cookies != null && i < cookies.length; i++) { if ("bookHistory".equals(cookies[i].getName())) { String value = cookies[i].getValue(); String ids[] = value.split("\\-"); for (String id : ids) { Book book = BookDB.findBookById(id); out.write(book.getName() + "<br/>"); } break; } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.swing.plaf.basic.BasicScrollPaneUI.HSBChangeListener; // 1.显示书籍的详细内容;2.写cookie public class ShowDetailsServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); // 显示详细信息 out.write("本书的详细信息为: <br/>"); String id = request.getParameter("id"); Book book = BookDB.findBookById(id); out.write(book.toString()); // 写cookie String ids = makeIds(request, id); Cookie cookie = new Cookie("bookHistory", ids); cookie.setPath(request.getContextPath()); cookie.setMaxAge(Integer.MAX_VALUE); response.addCookie(cookie); } /* * 1.没有cookie * 2.有cookie,但是没有名为bookHistory的cookie * 3.有名为bookHistory的cookie * 原 新 组织后 * 1 2 2-1 * 1-2 2 2-1 * 1-2 3 3-1-2 * * 1-2-3 4 4-1-2 * 1-2-3 2 2-1-3 */ private String makeIds(HttpServletRequest request, String id) { Cookie[] cookies = request.getCookies(); // 没有cookie if (cookies == null) { return id; } boolean hasBookHistory = false; String value = ""; for (Cookie cookie : cookies) { if ("bookHistory".equals(cookie.getName())) {// 这里必须使用cookie.getName(),而不是cookie hasBookHistory = true; value = cookie.getValue(); } } if (!hasBookHistory) { return id; } String[] vs = value.split("\\-"); LinkedList<String> list = new LinkedList<String>(Arrays.asList(vs));//需要将vs传入 if (list.size() < 3) { if (list.contains(id)) { list.remove(id); list.addFirst(id); } else { list.addFirst(id); } } else { if (list.contains(id)) { list.remove(id); list.addFirst(id); } else { list.removeLast(); list.addFirst(id); } } StringBuffer sb = new StringBuffer(); for (int i = 0; i < list.size(); i++) { if (i > 0) sb.append("-"); sb.append(list.get(i));// 不是sb.append(id); } return sb.toString(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.util.HashMap; import java.util.Map; public class BookDB { private static Map<String,Book> books = new HashMap<String,Book> (); static{ books.put("1", new Book("1", "葵花宝典", "HMM", 5.00f, "欲练此功,必须练好基本功")); books.put("2", new Book("2", "辟邪剑法", "WDD", 4.00f, "欲练此功,必须练好基本功")); books.put("3", new Book("3", "JPM", "DJR", 15.00f, "古代爱情小说")); books.put("4", new Book("4", "Java面向对象编程", "WZT", 85.00f, "Java入门经典书籍")); books.put("5", new Book("5", "红高粱", "CYY", 7500000.00f, "买套房")); } public static Map<String, Book> findAllBooks(){ return books; } public static Book findBookById(String id){ return books.get(id); } }
public class Book { private String id; private String name; private String author; private float price; private String description; public Book() {} public Book(String id, String name, String author, float price, String description) { super(); this.id = id; this.name = name; this.author = author; this.price = price; this.description = description; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Book [id=" + id + ", name=" + name + ", author=" + author + ", price=" + price + ", description=" + description + "]"; } }
效果:
五、HttpSession概述
每个客户端都有自己对应的HttpSession对象,该对象存放在服务器的内存中。
得到HttpSession对象:
HttpServletRequest.getSession():
先根据你传递的JSESSIONID的值,在内存找id为此值的session对象。名称为JSESSIONID的Cookie如果不存在,或者找不到对应session对象,会新建一个HttpSession对象。
HttpServletReqeust.getSession(boolean b):
如果为true:效果等同没有参数的getSession()
如果为false:只会查找。
HttpSession.getId()
HttpSession实际上借助了Cookie技术,知不是过是写了一个特殊名称的cookie而已。
此Cookie的path是当前应用,age是会话范围。name是JSESSIONID,value是session对象的id。
六、HttpSession的原理
import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // 1.显示所有的商品;2.提供购买链接; public class ShowProductsServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); // 显示所有商品 out.write("本站有以下商品:<br/>"); Map<String, Book> books = BookDB.findAllBooks(); for (Map.Entry<String, Book> me : books.entrySet()) { out.write(me.getValue().getName() + "<a href='" + request.getContextPath() + "/servlet/BuyServlet?id=" + me.getKey() + "'>购买</a><hr/>");// 别忘了传入me.getKey(),否则找不到商品 } out.write("<a href='" + request.getContextPath() + "/servlet/ShowCartServlet'>查看购物车</a><br/>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
// 提供购买功能 public class BuyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String id = request.getParameter("id");// 获取到要购买商品的id Book book = BookDB.findBookById(id);// 找到要买的商品 // 获得session,如果没有,则创建 HttpSession session = request.getSession(); Object obj = session.getAttribute("cart");// 获取购物车 // 如果没有购物车,则创建一个容器来盛放要买的商品,并将数据传给购物车 if (obj == null) { List<Book> cart = new ArrayList<Book>(); cart.add(book); session.setAttribute("cart", cart); } else { List<Book> cart = (List<Book>) obj; cart.add(book);// 这里不是setAttribute,因为已有Attribute,所以只需添加元素 } out.write("商品已成功放入购物车!<a href='" + request.getContextPath() + "/servlet/ShowProductsServlet'>继续购物</a><br/>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; // 1.显示已加入购物车的商品 public class ShowCartServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); HttpSession session = request.getSession(false);// 只查看,不创建 if (session == null) { out.write("还没有购买任何物品!"); return; } List<Book> cart = (List<Book>) session.getAttribute("cart"); if (cart == null) { out.write("还没有购买任何物品!"); return; } System.out.println(cart); out.write("您已经购买了如下商品:<hr/>"); for (Book book : cart) { out.write(book.getName() + "<br/>"); } out.write("<a href='#'>去结算</a> <a href='" + request.getContextPath() + "/servlet/ShowProductsServlet'>继续购物</a>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
效果图:
2、实现用户一次登陆和验证码验证
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; /* * 需要一个主页(IndexServlet) * 1.如果已登录,则显示欢迎信息和注销链接 * 需要获取session,从session中获取username,显示在欢迎信息中; * 2.如果未登录,则显示登录链接 */ public class IndexServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write("这是主页<hr/>"); // 获取session HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); String username = null; if (user != null) { username = user.getUsername(); } if (username != null) { out.write("欢迎您," + username + "<br/>"); out.write("<a href='" + request.getContextPath() + "/servlet/LogoutServlet'>注销</a>"); } else { out.write("欢迎光临本站,如果想要浏览更多信息<br/>请<a href='" + request.getContextPath() + "/servlet/LoginUIServlet'>登录</a><br/>"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
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; /* * 需要一个主页(IndexServlet) * 1.如果已登录,则显示欢迎信息和注销链接 * 需要获取session,从session中获取username,显示在欢迎信息中; * 2.如果未登录,则显示登录链接 */ public class IndexServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write("这是主页<hr/>"); // 获取session HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); String username = null; if (user != null) { username = user.getUsername(); } if (username != null) { out.write("欢迎您," + username + "<br/>"); out.write("<a href='" + request.getContextPath() + "/servlet/LogoutServlet'>注销</a>"); } else { out.write("欢迎光临本站,如果想要浏览更多信息<br/>请<a href='" + request.getContextPath() + "/servlet/LoginUIServlet'>登录</a><br/>"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /* * 需要一个登录后台处理Servlet(LoginServlet) * 1.获取session,获取username、password、code的值,如果三者都匹配,则登录成功,跳转到主页; * 2.如果有一项不匹配,则输出错误信息; * 3.检测checkbox,如果checked=checked,则写cookie,否则,删除cookie */ public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String username = request.getParameter("username"); String password = request.getParameter("password"); String code = request.getParameter("code"); String remember = request.getParameter("remember"); HttpSession session = request.getSession(); String value = (String) session.getAttribute("code"); // 判断验证码 if (!code.equals(value)) { out.write("验证码输入错误!<br/>"); out.write("<a href='" + request.getContextPath() + "/servlet/LoginUIServlet'>重新登录</a>"); return; } // 根据username、password查找数据库中的用户 User user = UserDB.findUser(username, password); if (user == null) { out.write("用户名或密码输入错误!<br/>"); out.write("<a href='" + request.getContextPath() + "/servlet/LoginUIServlet'>重新登录</a>"); return; } else { Cookie cookie = new Cookie("userInfo", username); if (remember == null) { cookie.setPath(request.getContextPath()); cookie.setMaxAge(0); response.addCookie(cookie); }else{ cookie.setPath(request.getContextPath()); cookie.setMaxAge(Integer.MAX_VALUE); response.addCookie(cookie); } session = request.getSession(); session.setAttribute("user", user); out.write("登录成功!2秒后返回主页,如果长时间没有反应,请点击<a href='" + request.getContextPath() + "/servlet/IndexServlet'>这里</a>"); response.setHeader("Refresh", "2;URL=" + request.getContextPath() + "/servlet/IndexServlet"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; 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 ImageServlet extends HttpServlet { private static int WIDTH = 120; private static int HEIGHT = 25; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //验证码图片不缓存 response.setHeader("Expires", "-1"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); // 获取画布 BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); // 获取画笔 Graphics g = image.getGraphics(); // 画边框 g.setColor(Color.GRAY); g.drawRect(0, 0, WIDTH, HEIGHT); // 填充背景色 g.setColor(Color.YELLOW); g.fillRect(1, 1, WIDTH - 2, HEIGHT - 2); // 画干扰线 g.setColor(Color.RED); Random r = new Random(); for (int i = 0; i < 9; i++) { g.drawLine(r.nextInt(WIDTH), r.nextInt(HEIGHT), r.nextInt(WIDTH), r.nextInt(HEIGHT)); } // 画数字 g.setColor(Color.BLUE); g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 20)); int x = 20; StringBuffer sb = new StringBuffer(); for (int i = 0; i < 4; i++) { String num = r.nextInt(10) + ""; sb.append(num); g.drawString(num, x, 20); x += 20; } //获取session,存储code HttpSession session = request.getSession(); session.setAttribute("code", sb.toString()); ImageIO.write(image, "jpeg", response.getOutputStream()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
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 LogoutServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //删除session中的user HttpSession session = request.getSession(); session.removeAttribute("user"); out.write("注销成功!<a href='"+request.getContextPath()+"/servlet/IndexServlet'>返回主页</a>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
public class User { private String username; private String password; public User(){} public User(String username, String password) { super(); this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
import java.util.ArrayList; import java.util.List; public class UserDB { private static List<User> users = new ArrayList<User>(); static{ users.add(new User("chenchong","123")); users.add(new User("admin","admin")); } public static User findUser(String username,String password){ User user = null; for(User u:users){ if(u.getUsername().equals(username)&&u.getPassword().equals(password)){ user = u; } } return user; } }
效果图:
3、防止表单重复提交
import java.io.IOException; import java.io.PrintWriter; import java.util.Random; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.itheima.util.MD5Util; //提供注册界面,向RegisterServlet提交数据 //在这里产生唯一的id,防止表单重复提交 public class RegisterUIServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); // String s = System.currentTimeMillis()+new Random().nextInt()+"";//尽量获取唯一的id // String token = MD5Util.encode(s);//获取token String token = UUID.randomUUID().toString();//可以获取唯一的值 request.getSession().setAttribute("token", token);//将取到的位移token存放到session中 out.write("<hr/>"); out.write("<form action='"+request.getContextPath()+"/servlet/RegisterServlet' method='post'>"); out.write("用户名<input type='text' name='username'/><br/>"); out.write("密码<input type='password' name='password'/><hr/>"); out.write("token<input type='text' name='token' value='"+token+"'>");//这里的type本应为hidden,但是为了便于观察,设为text out.write("<input type='submit' name='提交'/><br/>"); out.write("</form>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
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; public class RegisterServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String username = request.getParameter("username"); String iToken = request.getParameter("token");//表单中提交过来的token String sToken = (String) request.getSession().getAttribute("token");//session中存储的token //在提交表单以后,删除session中token //对比两个token的值,如果相同,则表单尚未提交过;如果不同,则表单已经提交过 if(iToken.equals(sToken)){ try { Thread.sleep(2000); } catch (Exception e) { throw new RuntimeException(e); } out.write("表单提交成功!<br/>"); request.getSession().removeAttribute("token"); }else{ out.write("网页已过期!"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
import java.security.MessageDigest; import sun.misc.BASE64Encoder; //对一组数字进行MD5加密 public class MD5Util { public static String encode(String message){ try { MessageDigest md = MessageDigest.getInstance("md5"); byte[] md5 = md.digest(message.getBytes());//获取message的数据指纹,不一定是一个字符 //new String(b);//不可行,在转换为字符串时,会查码表,可能会出现乱码 BASE64Encoder base64 = new BASE64Encoder(); return base64.encode(md5);//将数据转为明文 } catch (Exception e) { throw new RuntimeException(e); } } }
效果图:
1.正常提交表单
2.重复提交