Session 、Cookie、自定义缓存和Filter
第一、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.作者投稿可能会经我们编辑修改或补充。