1. 浏览器禁用Cookie后的session处理:
1.2解决方案:URL重写
response.encodeRedirectURL(java.lang.String url)
用于对重定向sendRedirect方法后的url地址进行重写。
response.encodeURL(java.lang.String url)
用于对表单action和超链接的url地址进行重写
1.3 案例:禁用Cookie后servlet共享Session中的数据
package com.zuoyueer.session;
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;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* @author Zuoyueer
* Date: 2019/10/26
* Time: 20:19
* @projectName HomeWork
* @description: 前提是浏览器进禁止了cookie.
* 在超链接后面追加session的id, url = response.encodeURL(url);
*/
@WebServlet(urlPatterns = "/IndexServlet", name = "IndexServlet")
public class IndexServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//咋看之下这个servlet中没有使用到session,实际这句不能省略,因为必须在这里创建session对象,才能保证url后面有session的id,并且他们的id一样
HttpSession session = request.getSession();
writer.write("本网站有如下书籍:<br>");
Set<Map.Entry<String, Book>> entries = DB.getAll().entrySet();
for (Map.Entry<String, Book> entry : entries) {
Book book = entry.getValue();
String url = request.getServletContext().getContextPath() + "/BuyServlet?id=" + book.getId();
System.out.println("前:"+url);//前:/day_25_Servlet_Web_exploded/BuyServlet?id=1
//调用了该方法之后,url地址后面追加了session的id,这个id就是上面创建的那个session的id,如果不创建session对象,那么该方法没任何作用
url = response.encodeURL(url);
System.out.println("后:"+url);//后:/day_25_Servlet_Web_exploded/BuyServlet;jsessionid=191B10C0F2614D165306C62200FF4349?id=1
writer.println(book.getName() + "<a href=\""+url+"\">购买</a><br>");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
/**
* 模拟数据库
*/
class DB {
private static Map<String, Book> map = new LinkedHashMap<>();
static {
map.put("1", new Book("1", "javaee开发"));
map.put("2", new Book("2", "spring开发"));
map.put("3", new Book("3", "hibernate开发"));
map.put("4", new Book("4", "struts开发"));
map.put("5", new Book("5", "ajax开发"));
}
public static Map<String, Book> getAll() {
return map;
}
}
/**
* 模拟javaBean
*/
class Book implements Serializable {
private String id;
private String name;
public Book() {
}
public Book(String id, String name) {
this.id = id;
this.name = name;
}
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;
}
}
package com.zuoyueer.session;
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;
import java.util.ArrayList;
import java.util.List;
/**
* @author Zuoyueer
* Date: 2019/10/26
* Time: 20:43
* @projectName HomeWork
* @description: 前提是浏览器进禁止了cookie.
* 在请求重定向的时候,在url后面追加session的id, String url = response.encodeRedirectURL(request.getContextPath() + "/ListCartServlet");
*/
@WebServlet(urlPatterns = "/BuyServlet", name = "BuyServlet")
public class BuyServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String id = request.getParameter("id");
//获得要买的书
Book book = DB.getAll().get(id);
//注意,这里不再是创建session,而是获取之前在IndexServlet中创建的session对象,因为超链接请求的url后面带有session的id
HttpSession session = request.getSession();
//下面这种存储数据的方式非常的妙,避免多次每次访问都创建list集合,导致覆盖上一次请求的数据
List<Book> list = (List) session.getAttribute("list");
if (list == null) {
//只有第一次访问的时候才创建list集合,其他的时候直接session域中获取
list = new ArrayList<Book>();
session.setAttribute("list", list);
}
//session中添加书
list.add(book);
//请求重定向的url后面追加session的id
String url = response.encodeRedirectURL(request.getContextPath() + "/ListCartServlet");
System.out.println(url);///day_25_Servlet_Web_exploded/ListCartServlet;jsessionid=191B10C0F2614D165306C62200FF4349
//重定向
response.sendRedirect(url);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
package com.zuoyueer.session;
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;
import java.io.PrintWriter;
import java.util.List;
/**
* @author Zuoyueer
* Date: 2019/10/26
* Time: 21:38
* @projectName HomeWork
* @description: 显示session的中的数据信息
*/
@WebServlet(urlPatterns="/ListCartServlet", name="ListCartServlet")
public class ListCartServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//获取之前的session对象
HttpSession session = request.getSession();
List<Book> list = (List) session.getAttribute("list");
if (list==null||list.size()==0){
writer.write("对不起,你还没有购买任何商品!");
return;
}
writer.write("您买过如下商品:<br>");
for(Book book : list){
writer.write(book.getName()+"<br>");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
总结: url重写可以就是在url后面添加或者隐藏参数,满足需要的功能,本文使用了两种方法重写url,使得超链接和重定向的url后面带上了session的id,保证浏览器在禁止了cookie的情况下也能正常使用session.
另外我想强调的是,request.getSession()
方法不一定是创建session对象: 只有客户端没有jsessionid或者服务端没有jsessionid所对应的session对象的时候,才会创建. 万万不可自以为第一次请求的时候创建,这种认知是不准确的!甚至可以说是错误的!