Session 、Cookie、自定义缓存和Filter

java哥 阅读:673 2021-03-31 14:15:00 评论:0

第一、Cookie

1.1 Cookie 技术特点

      会话数据保存在浏览器客户端。

1.2 Cookie 核心技术

Cookie类:用于存储会话数据 
 
		1)构造Cookie对象 
				Cookie(java.lang.String name, java.lang.String value) 
		2)设置cookie 
				void setPath(java.lang.String uri)   :设置cookie的有效访问路径 
				void setMaxAge(int expiry) : 设置cookie的有效时间 
				void setValue(java.lang.String newValue) :设置cookie的值 
		3)发送cookie到浏览器端保存 
				void response.addCookie(Cookie cookie)  : 发送cookie 
		4)服务器接收cookie 
				Cookie[] request.getCookies()  : 接收cookie

1.3 Cookie 原理

1)服务器创建cookie对象,把会话数据存储到cookie对象中。
      new Cookie("Cookie属性","Cookie 值");
2)服务器发送cookie信息到浏览器
      resp.addCookie(cookie);

示例代码:

package com.zzg.eshop.servlet; 
 
import java.io.IOException; 
 
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; 
 
@SuppressWarnings("serial") 
@WebServlet(urlPatterns = "/cookie", description = "cookie  功能演示") 
public class CookieServlet extends HttpServlet { 
 
	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		Cookie cookie = new Cookie("uuid",String.valueOf(System.currentTimeMillis())); 
		resp.addCookie(cookie); 
	} 
 
	@Override 
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		this.doGet(req, resp); 
	} 
	 
	 
 
} 

3)浏览器得到服务器发送的cookie,然后保存在浏览器端。
4)浏览器在下次访问服务器时,会带着cookie
             举例: cookie: uuid=1588432172709  (隐藏带着一个叫cookie名称的请求头)
5)服务器接收到浏览器带来的cookie信息
             req.getCookies();

示例代码:

package com.zzg.eshop.servlet; 
 
import java.io.IOException; 
 
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; 
 
@SuppressWarnings("serial") 
@WebServlet(urlPatterns = "/getCookie", description = "cookie  功能演示") 
public class CookieValueServlet extends HttpServlet { 
 
	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		Cookie[] cookies = req.getCookies(); 
		for(Cookie cookie:cookies) { 
			System.out.println(cookie.getValue()); 
		} 
	} 
 
	@Override 
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		this.doGet(req, resp); 
	} 
	 
	 
 
} 

1.4 Cookie 功能拓展

1)void setPath(java.lang.String uri)   :设置cookie的有效访问路径。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。 
			 
2)void setMaxAge(int expiry) : 设置cookie的有效时间。 
正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。 
负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!! 
零:表示删除同名的cookie数据 
 
3)Cookie数据类型只能保存非中文字符串类型的。可以保存多个cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

1.5 Cookie 功能实例

业务要求:显示上一次用户访问业务系统的时间

package com.zzg.eshop.servlet; 
 
import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
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; 
 
import org.apache.commons.lang3.ArrayUtils; 
import org.apache.commons.lang3.StringUtils; 
import org.springframework.util.CollectionUtils; 
 
/** 
 * 显示用户上一次访问系统时间 
 *  
 * @author Administrator 
 * 
 */ 
@SuppressWarnings("serial") 
@WebServlet("/lastAccessTime") 
public class LastAccessTimeServlet extends HttpServlet { 
 
	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		resp.setContentType("text/html;charset=utf-8");// 防止浏览器显示乱码 
		String lastAccessTime = null; 
		Cookie[] cookies = req.getCookies(); 
		if(!ArrayUtils.isEmpty(cookies)) { 
			for (Cookie cookie : cookies) { 
				String name = cookie.getName(); 
				if (name.equals("lastAccessTime")) { 
					lastAccessTime = cookie.getValue(); 
					break; 
				} 
			}	 
		} 
		if (StringUtils.isEmpty(lastAccessTime)) { 
			resp.getWriter().print("您是首次访问!"); 
		} else { 
			resp.getWriter().print("你上次访问时间:" + lastAccessTime); 
		} 
		// 保存访问时间 
		// 创建cookie 将当前时间作为cookie保存到浏览器 
		String currenttime = new SimpleDateFormat("yyyy-mm-dd").format(new Date()); 
		Cookie cookie = new Cookie("lastAccessTime", currenttime); 
		cookie.setMaxAge(60 * 60 * 24); 
		// 发送cookie 
		resp.addCookie(cookie); 
	} 
 
	@Override 
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		this.doGet(req, resp); 
	} 
	 
	 
 
} 

第二、Session 

2.1 引入Sessio 原因和Cookie 的局限性

Cookie的局限:
    1)Cookie只能存字符串类型。不能保存对象
    2)只能存非中文。
    3)1个Cookie的容量不超过4KB

Session 的特点

      会话数据保存在服务器端。(内存中)

2.2 Session 核心技术

HttpSession类:用于保存会话数据

1)创建或得到session对象
                HttpSession getSession()  
                HttpSession getSession(boolean create)  
 2)设置session对象
                void setMaxInactiveInterval(int interval)  : 设置session的有效时间
                void invalidate()     : 销毁session对象
                java.lang.String getId()  : 得到session编号
3)保存会话数据到session对象
                void setAttribute(java.lang.String name, java.lang.Object value)  : 保存数据
                java.lang.Object getAttribute(java.lang.String name)  : 获取数据
                void removeAttribute(java.lang.String name) : 清除数据

 

2.3 Session 原理

1)第一次访问创建session对象,给session对象分配一个唯一的ID,叫JSESSIONID
        new HttpSession();
2)把JSESSIONID作为Cookie的值发送给浏览器保存
        Cookie cookie = new Cookie("JSESSIONID", sessionID);
        response.addCookie(cookie);

package com.zzg.eshop.servlet; 
 
import java.io.IOException; 
 
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; 
import javax.servlet.http.HttpSession; 
 
import org.springframework.beans.factory.annotation.Autowired; 
 
import com.zzg.eshop.global.GlobalCache; 
 
 
@SuppressWarnings("serial") 
@WebServlet("/login") 
public class SessionServlet extends HttpServlet { 
	@Autowired 
	private GlobalCache globalCache; 
 
	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		 
		HttpSession session = req.getSession(); 
		globalCache.getMap().put( session.getId(), session); 
		Cookie cookie = new Cookie("JSESSIONID", session.getId()); 
		resp.addCookie(cookie); 
		 
	} 
 
	@Override 
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		this.doGet(req, resp); 
	} 
	 
	 
 
} 


3)第二次访问的时候,浏览器带着JSESSIONID的cookie访问服务器
4)服务器得到JSESSIONID,在服务器的内存中搜索是否存放对应编号的session对象。
    if(找到){
        return map.get(sessionID);
    }
    
5)如果找到对应编号的session对象,直接返回该对象
6)如果找不到对应编号的session对象,创建新的session对象,继续走1的流程

package com.zzg.eshop.servlet; 
 
import java.io.IOException; 
import java.util.Date; 
 
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; 
import javax.servlet.http.HttpSession; 
 
import org.apache.commons.lang3.ArrayUtils; 
import org.apache.commons.lang3.StringUtils; 
import org.springframework.beans.factory.annotation.Autowired; 
 
import com.zzg.eshop.global.GlobalCache; 
 
@SuppressWarnings("serial") 
@WebServlet("/validate") 
public class SessionValidateServlet extends HttpServlet { 
	@Autowired 
	private GlobalCache globalCache; 
 
	@Override 
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		// 判断用户是否已经登入 
		boolean target = false; 
 
		Cookie[] cookies = req.getCookies(); 
		if (!ArrayUtils.isEmpty(cookies)) { 
			for (Cookie cookie : cookies) { 
				String value = cookie.getValue(); 
				if (!StringUtils.isEmpty(value)) { 
					if (globalCache.getMap().get(value) != null) { 
						target = true; 
					} 
 
				} 
			} 
		} 
 
		if (target) { 
			resp.setCharacterEncoding("utf-8");// 内容编码,防止出现中文乱码 
			resp.setContentType("text/html;charset=utf-8"); // 向浏览器输出内容 
			resp.getWriter().write("用户已经登入:"); 
		} else { 
			resp.setCharacterEncoding("utf-8");// 内容编码,防止出现中文乱码 
			resp.setContentType("text/html;charset=utf-8"); // 向浏览器输出内容 
			resp.getWriter().write("用户未登入:"); 
		} 
 
	} 
 
	@Override 
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
		// TODO Auto-generated method stub 
		this.doGet(req, resp); 
	} 
 
} 

全局缓存对象定义:

package com.zzg.eshop.global; 
 
import java.util.HashMap; 
import java.util.Map; 
 
import javax.servlet.http.HttpSession; 
 
import org.springframework.stereotype.Component; 
 
@Component 
public class GlobalCache { 
	private Map<String, HttpSession> map = new HashMap<String,HttpSession>(); 
 
	public Map<String, HttpSession> getMap() { 
		return map; 
	} 
 
	public void setMap(Map<String, HttpSession> map) { 
		this.map = map; 
	} 
	 
	 
 
} 

2.4 Session 功能拓展

1)java.lang.String getId()  : 得到session编号 
2)两个getSession方法: 
	getSession(true) / getSession()  : 创建或得到session对象。没有匹配的session编号,自动创建新的session对象。 
	getSession(false): 得到session对象。没有匹配的session编号,返回null 
3)void setMaxInactiveInterval(int interval)  : 设置session的有效时间 
	session对象销毁时间: 
		3.1 默认情况30分服务器自动回收 
		3.2 修改session回收时间 
		3.3 全局修改session有效时间 
        <!-- 修改session全局有效时间:分钟 --> 
	    <session-config> 
		    <session-timeout>1</session-timeout> 
	    </session-config> 
        3.4.手动销毁session对象 
            void invalidate()     : 销毁session对象 
4)如何避免浏览器的JSESSIONID的cookie随着浏览器关闭而丢失的问题 
		/** 
		 * 手动发送一个硬盘保存的cookie给浏览器 
		 */ 
		Cookie c = new Cookie("JSESSIONID",session.getId()); 
		c.setMaxAge(60*60); 
		response.addCookie(c);

第三、自定义缓存

package com.zzg.cache; 
 
/** 
 * 缓存对象实体定义 
 *  
 * @author Administrator 
 * 
 */ 
public class Cache { 
	public Cache(String key, Object value, Long timeOut) { 
		super(); 
		this.key = key; 
		this.value = value; 
		this.timeOut = timeOut; 
	} 
 
	public Cache() { 
 
	} 
 
	/** 
	 * key 
	 */ 
	private String key; 
	/** 
	 * 缓存数据 
	 */ 
	private Object value; 
	/** 
	 * 超时时间 
	 */ 
	private Long timeOut; 
 
	public String getKey() { 
 
		return key; 
	} 
 
	public void setKey(String key) { 
 
		this.key = key; 
	} 
 
	public Object getValue() { 
 
		return value; 
	} 
 
	public void setValue(Object value) { 
 
		this.value = value; 
	} 
 
	public Long getTimeOut() { 
 
		return timeOut; 
	} 
 
	public void setTimeOut(Long timeOut) { 
 
		this.timeOut = timeOut; 
	} 
} 
package com.zzg.cache; 
 
import java.util.HashMap; 
import java.util.Map; 
 
/** 
 * 缓存管理器 
 * @author Administrator 
 * 
 */ 
public class CacheManager { 
	private Map<String, Cache> cacheMap = new HashMap<>(); 
 
	/** 
	 *  
	 * @methodDesc: 功能描述:(往缓存存值) 
	 */ 
	public void put(String key, Object oj) { 
		put(key, oj, null); 
	} 
 
	/** 
	 *  
	 * @methodDesc: 功能描述:(往缓存存值) 
	 */ 
	public synchronized void put(String key, Object oj, Long timeOut) { 
		if (oj == null) { 
			return; 
		} 
		Cache cache = new Cache(); 
		cache.setKey(key); 
		if (timeOut != null) 
			cache.setTimeOut(timeOut + System.currentTimeMillis()); 
		cache.setValue(oj); 
		cacheMap.put(key, cache); 
	} 
 
	/** 
	 *  
	 * @methodDesc: 功能描述:(删除) 
	 */ 
	public synchronized void deleteCache(String key) { 
		cacheMap.remove(key); 
	} 
 
	/** 
	 *  
	 * @methodDesc: 功能描述:(获取缓存中数据) 
	 */ 
	public synchronized Object get(String key) { 
		Cache cache = cacheMap.get(key); 
		Object oj = null; 
		if (cache != null) { 
			oj = cache.getValue(); 
		} 
		return oj; 
	} 
 
	/** 
	 *  
	 * @methodDesc: 功能描述:(检查数据是否在有效期内) 
	 */ 
	public synchronized void checkValidityData() { 
		for (String key : cacheMap.keySet()) { 
			Cache cache = cacheMap.get(key); 
			Long timeOut = cache.getTimeOut(); 
			if (timeOut == null) { 
				return; 
			} 
			long currentTime = System.currentTimeMillis(); 
			long endTime = timeOut; 
			long result = (currentTime - endTime); 
			if (result > 0) { 
				System.out.println("清除:"+key); 
				cacheMap.remove(key); 
			} 
		} 
	} 
} 
package com.zzg.cache; 
 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 
 
public class CacheTest { 
 
	public static void main(String[] args) throws InterruptedException { 
		CacheManager cacheManager = new CacheManager(); 
		cacheManager.put("zhangsan", "lisi", 5000l); 
		ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); 
		scheduledThreadPool.schedule(new Runnable() { 
			public void run() { 
				cacheManager.checkValidityData(); 
			} 
		}, 5000, TimeUnit.MILLISECONDS); 
		Thread.sleep(5000); 
		System.out.println(cacheManager.get("zhangsan")); 
	} 
 
} 

第四:Filter

Filter 功能简介:

          Filter 也称之为过滤器,它是 Servlet 技术中最实用的技术,Web 开发人员通过 Filter 技术,对 web 服务器管理的所有 web 资源:例如 Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现 URL 级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
          它主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后处理。使用 Filter 的完整流程:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再对服务器响应进行后处理。

 示例:

package com.zzg.eshop.filter; 
 
import java.io.IOException; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
/** 
 * 拦截器输出请求url 地址 
 * @author Administrator 
 * 
 */ 
public class FilterDemo implements Filter { 
 
	@Override 
	public void doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) 
			throws IOException, ServletException { 
		HttpServletRequest request = (HttpServletRequest) paramServletRequest; 
		// 请求地址 
		String requestURI = request.getRequestURI(); 
		System.out.println("requestURI:"+requestURI); 
		 
	} 
 
} 
package com.zzg.eshop.config; 
 
import org.springframework.boot.web.servlet.FilterRegistrationBean; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
 
import com.zzg.eshop.filter.FilterDemo; 
/** 
 * Filter 配置参数对象 
 * @author Administrator 
 * 
 */ 
@Configuration 
public class FilterInitConfig { 
	@Bean 
	public FilterRegistrationBean testFilterRegistration() { 
		FilterRegistrationBean registration = new FilterRegistrationBean(new FilterDemo()); 
		registration.addUrlPatterns("/*"); // 拦截url 路径 
		registration.setName("filterDemo"); // 拦截器名称 
		return registration; 
	} 
 
} 

功能需求,基于Filter 防止XSS 注入脚本攻击

package com.zzg.eshop.filter; 
 
import java.io.IOException; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
 
import com.zzg.eshop.xss.XssAndSqlHttpServletRequestWrapper; 
 
/** 
 * 防止xss 脚本注入攻击拦截器 
 * @author Administrator 
 * 
 */ 
public class XSSFilter implements Filter { 
 
	@Override 
	public void doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) 
			throws IOException, ServletException { 
		HttpServletRequest request = (HttpServletRequest) paramServletRequest; 
		XssAndSqlHttpServletRequestWrapper xssRequestWrapper = new XssAndSqlHttpServletRequestWrapper(request); 
		paramFilterChain.doFilter(xssRequestWrapper, paramServletResponse); 
		 
	} 
 
} 
 
package com.zzg.eshop.xss; 
 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletRequestWrapper; 
 
import org.apache.commons.lang3.StringEscapeUtils; 
import org.apache.commons.lang3.StringUtils; 
 
public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper { 
	HttpServletRequest request; 
	public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) { 
		super(request); 
		this.request = request; 
	} 
	@Override 
	public String getParameter(String name) { 
		String value = request.getParameter(name); 
		System.out.println("name:" + name + "," + value); 
		if (!StringUtils.isEmpty(value)) { 
			// 转换Html 
			value = StringEscapeUtils.escapeHtml4(value); 
		} 
		return value; 
	} 
 
} 
 
 
-- springboot 配置Filter 
@Bean 
	public FilterRegistrationBean xssFilterRegistration() { 
		FilterRegistrationBean registration = new FilterRegistrationBean(new XSSFilter()); 
		registration.addUrlPatterns("/*"); // 拦截url 路径 
		registration.setName("xssFilter"); // 拦截器名称 
		return registration; 
	}

 

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号