自己实现httpsession

package com.kongjs.emo.web.session;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import java.util.*;
// 实现类
public class Session implements HttpSession {
    private String id;
    private final long creationTime;
    private int maxInactiveInterval;
    private long lastAccessedTime;
    private final ServletContext servletContext;
    private Map<String, Object> attributes;
    private boolean isNew;
    private long responseEndTime;

    public Session(ServletContext servletContext, String id) {
        long now = System.currentTimeMillis();
        this.id = id;
        this.creationTime = now;
        this.maxInactiveInterval = servletContext.getSessionTimeout() * 60;
        this.lastAccessedTime = now;
        this.servletContext = servletContext;
        this.attributes = new HashMap<>();
        this.isNew = true;
        this.responseEndTime = now;
    }

    @Override
    public long getCreationTime() {
        return this.creationTime;
    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public long getLastAccessedTime() {
        return this.lastAccessedTime;
    }

    @Override
    public ServletContext getServletContext() {
        return this.servletContext;
    }

    @Override
    public void setMaxInactiveInterval(int i) {
        this.maxInactiveInterval = i;
    }

    @Override
    public int getMaxInactiveInterval() {
        return this.maxInactiveInterval;
    }

    @SuppressWarnings(value = "deprecated")
    @Override
    public HttpSessionContext getSessionContext() {
        throw new RuntimeException("不支持");
    }

    @Override
    public Object getAttribute(String name) {
        return this.attributes.get(name);
    }
    @SuppressWarnings(value = "deprecated")
    @Override
    public Object getValue(String name) {
        return this.attributes.get(null);
    }

    @Override
    public Enumeration<String> getAttributeNames() {
        return Collections.enumeration(this.attributes.keySet());
    }
    @SuppressWarnings(value = "deprecated")
    @Override
    public String[] getValueNames() {
        return this.attributes.keySet().toArray(new String[0]);
    }

    @Override
    public void setAttribute(String name, Object value) {
        this.attributes.put(name, value);
    }
    @SuppressWarnings(value = "deprecated")
    @Override
    public void putValue(String name, Object value) {
        this.attributes.put(name, value);
    }

    @Override
    public void removeAttribute(String name) {
        this.attributes.remove(name);
    }

    @Override
    public void removeValue(String name) {
        this.attributes.remove(name);
    }

    @Override
    public void invalidate() {
        this.attributes.clear();
    }

    @Override
    public boolean isNew() {
        return this.isNew;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setLastAccessedTime(long lastAccessedTime) {
        this.lastAccessedTime = lastAccessedTime;
        this.isNew = false;
    }

    public void setResponseEndTime(long responseEndTime) {
        this.responseEndTime = responseEndTime;
    }

    public long getResponseEndTime() {
        return this.responseEndTime;
    }

    public Map<String, Object> getAttributes() {
        return this.attributes;
    }

    public boolean isExpired() {
        return (System.currentTimeMillis() - this.creationTime) / 1000 >= this.maxInactiveInterval;
    }

    @Override
    public String toString() {
        return this.toMap().toString();
    }

    public Map<String, Object> toMap() {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("id", this.id);
        map.put("creationTime", this.creationTime);
        map.put("maxInactiveInterval", this.maxInactiveInterval);
        map.put("lastAccessedTime", this.lastAccessedTime);
        map.put("responseEndTime", this.responseEndTime);
        map.put("isNew", this.isNew);
        map.put("isExpired", this.isExpired());
        map.put("attributes", this.attributes);
        return map;
    }
}

package com.kongjs.emo.web.session.wrapper;

import com.kongjs.emo.web.session.Session;
import com.kongjs.emo.web.session.manager.SessionManager;

import javax.servlet.ServletContext;
import javax.servlet.SessionCookieConfig;
import javax.servlet.http.*;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
// 实现HttpServletRequestWrapper 托管session
public class RequestSessionWrapper extends HttpServletRequestWrapper {
    private final HttpServletRequest request;
    private final HttpServletResponse response;
    private final SessionManager sessionManager;
    private String requestedSessionId;
    private boolean requestedSessionCookie;
    private boolean requestedSessionURL;

    public RequestSessionWrapper(HttpServletRequest request, HttpServletResponse response, SessionManager sessionManager) {
        super(request);
        this.request = request;
        this.response = response;
        this.sessionManager = sessionManager;
    }

    @Override
    public HttpServletRequest getRequest() {
        return request;
    }

    public HttpServletResponse getResponse() {
        return response;
    }

    public SessionManager getSessionManager() {
        return sessionManager;
    }

    private String readCookieValue(ServletContext servletContext) {
        SessionCookieConfig cookieConfig = servletContext.getSessionCookieConfig();
        if (this.getCookies() != null) {
            for (Cookie cookie : this.getCookies()) {
                if (cookie.getName().equals(cookieConfig.getName())) {
                    this.requestedSessionCookie = true;
                    this.requestedSessionURL = false;
                    return cookie.getValue();
                }
            }
        }
        String id = this.getRequest().getParameter(cookieConfig.getName());
        if (id != null && id.length() > 0) {
            this.requestedSessionCookie = false;
            this.requestedSessionURL = true;
            return id;
        }
        return null;
    }

    private void writeCookieValue(ServletContext servletContext, String value) {
        SessionCookieConfig cookieConfig = servletContext.getSessionCookieConfig();
        StringBuilder sb = new StringBuilder();
        sb.append(cookieConfig.getName()).append('=');
        if (value != null && value.length() > 0) {
            sb.append(value);
        }
        int maxAge = cookieConfig.getMaxAge();
        if (maxAge > -1) {
            sb.append("; Max-Age=").append(maxAge);
            ZonedDateTime expires = (maxAge != 0) ? ZonedDateTime.now(ZoneId.systemDefault()).plusSeconds(maxAge) : Instant.EPOCH.atZone(ZoneOffset.UTC);
            sb.append("; Expires=").append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
        }
        String domain = cookieConfig.getDomain();
        if (domain != null && domain.length() > 0) {
            sb.append("; Domain=").append(domain);
        }
        String path = cookieConfig.getPath();
        if (path != null && path.length() > 0) {
            sb.append("; Path=").append(path);
        }
        //sb.append("; Secure");
        sb.append("; HttpOnly");
        sb.append("; SameSite=").append("Lax");
        response.addHeader("Set-Cookie", sb.toString());
    }

    private HttpSession newSession() {
        Session session = this.getSessionManager().createSession(this.getServletContext());
        this.getSessionManager().save(session);
        this.writeCookieValue(this.getServletContext(), session.getId());
        this.requestedSessionId = session.getId();
        return session;
    }

    @Override
    public HttpSession getSession(boolean create) {
        String authorization = this.getRequest().getHeader("Authorization");
        String id = this.readCookieValue(this.getServletContext());
        if (id != null) {
            Session session = this.getSessionManager().findById(id);
            if (session != null) {
                if (session.isExpired()) {
                    this.sessionManager.deleteById(id);
                    HttpSession httpSession = this.newSession();
                    this.requestedSessionId = httpSession.getId();
                    return httpSession;
                }
                session.setLastAccessedTime(System.currentTimeMillis());
                this.getSessionManager().save(session);
                this.requestedSessionId = id;
                return session;
            }
        }
        if (create) {
            HttpSession httpSession = this.newSession();
            this.requestedSessionId = httpSession.getId();
            return httpSession;
        }
        return null;
    }

    @Override
    public HttpSession getSession() {
        return this.getSession(true);
    }

    @Override
    public String getRequestedSessionId() {
        return this.requestedSessionId;
    }

    @Override
    public String changeSessionId() {
        HttpSession httpSession = this.getSession();
        Session session = (Session) httpSession;
        session.setId(this.getSessionManager().idGenerator());
        this.getSessionManager().save(session);
        this.requestedSessionId = session.getId();
        return session.getId();
    }

    @Override
    public boolean isRequestedSessionIdValid() {
        return this.requestedSessionId != null;
    }

    @Override
    public boolean isRequestedSessionIdFromCookie() {
        return this.requestedSessionCookie;
    }

    @Override
    public boolean isRequestedSessionIdFromURL() {
        return this.requestedSessionURL;
    }

    @Override
    public boolean isRequestedSessionIdFromUrl() {
        return this.isRequestedSessionIdFromURL();
    }
}

package com.kongjs.emo.web.session.manager;

import cn.hutool.core.util.IdUtil;
import com.kongjs.emo.web.session.Session;
import com.kongjs.emo.web.session.manager.SessionManager;
import org.springframework.stereotype.Component;

import javax.servlet.ServletContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
// session 容器管理
public interface SessionManager {
    String idGenerator();

    Session createSession(ServletContext servletContext);

    void save(Session session);

    Session findById(String id);

    Session deleteById(String id);

    List<Session> findAll();

    List<Session> findByAttributeEquals(String name, String value);

    List<Session> findByAttributeContain(String name, String value);
}
@Component
public class MapSessionManager implements SessionManager {
    private final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    @Override
    public String idGenerator() {
        return IdUtil.getSnowflakeNextIdStr();
    }

    @Override
    public Session createSession(ServletContext servletContext) {
        return new Session(servletContext, idGenerator());
    }

    @Override
    public void save(Session session) {
        this.sessionMap.put(session.getId(), session);
    }

    @Override
    public Session findById(String id) {
        return this.sessionMap.get(id);
    }

    @Override
    public Session deleteById(String id) {
        return this.sessionMap.remove(id);
    }

    @Override
    public List<Session> findAll() {
        return new ArrayList<>(this.sessionMap.values());
    }

    @Override
    public List<Session> findByAttributeEquals(String name, String value) {
        return this.sessionMap.values().stream().filter(m -> m.getAttribute(name) != null && m.getAttribute(name).equals(value)).collect(Collectors.toList());
    }

    @Override
    public List<Session> findByAttributeContain(String name, String value) {
        return this.sessionMap.values().stream().filter(m -> m.getAttribute(name) != null && m.getAttribute(name).toString().contains(value)).collect(Collectors.toList());
    }
}

package com.kongjs.emo.web.session.filter;

import com.kongjs.emo.web.session.Session;
import com.kongjs.emo.web.session.wrapper.RequestSessionWrapper;
import com.kongjs.emo.web.session.wrapper.ResponseSessionWrapper;
import com.kongjs.emo.web.session.manager.SessionManager;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Order(SessionFilter.DEFAULT_ORDER)
@Component
public class SessionFilter extends OneFilter {
    public static final int DEFAULT_ORDER = Integer.MIN_VALUE + 50;

    private final SessionManager sessionManager;

    public SessionFilter(SessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }
// 拦截session 
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        final RequestSessionWrapper requestSessionWrapper = new RequestSessionWrapper(request, response, sessionManager);
        final ResponseSessionWrapper responseSessionWrapper = new ResponseSessionWrapper(request, response);
        Session session = (Session) requestSessionWrapper.getSession(false);
        try {
            filterChain.doFilter(requestSessionWrapper, responseSessionWrapper);
        } finally {
            if (session != null) {
                session.setResponseEndTime(System.currentTimeMillis());
            }
        }
    }
}
package com.kongjs.emo.web.controller;

import com.kongjs.emo.web.session.Session;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
// 测试
@RestController
@RequestMapping("/session")
public class SessionController {
    @RequestMapping("/info")
    public Object session(HttpServletRequest request) {
        Session session = (Session) request.getSession();
        return session.toMap();
    }
}

相关推荐

  1. 自己实现httpsession

    2024-04-24 07:02:03       13 阅读
  2. HttpSession

    2024-04-24 07:02:03       35 阅读
  3. 自己实现一个Feign

    2024-04-24 07:02:03       10 阅读
  4. 深入了解HttpSession:Web开发中的用户状态管理

    2024-04-24 07:02:03       31 阅读
  5. Servlet技术之Cookie对象与HttpSession对象

    2024-04-24 07:02:03       27 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-24 07:02:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-24 07:02:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-24 07:02:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-24 07:02:03       18 阅读

热门阅读

  1. TinyWebServer学习笔记(一):WSL编译运行

    2024-04-24 07:02:03       12 阅读
  2. union节省内存

    2024-04-24 07:02:03       11 阅读
  3. c# ?? 、?.、??=、?[]运算符的使用

    2024-04-24 07:02:03       15 阅读
  4. 【贪心算法】Leetcode 763. 划分字母区间【中等】

    2024-04-24 07:02:03       14 阅读
  5. stl_list

    stl_list

    2024-04-24 07:02:03      11 阅读
  6. uniapp同步开发h5+小程序双平台踩坑记录

    2024-04-24 07:02:03       10 阅读
  7. 景区ar导览实景导航小程序系统开发源码搭建

    2024-04-24 07:02:03       14 阅读
  8. 深入了解 npm

    2024-04-24 07:02:03       14 阅读
  9. windows驱动开发-I/O请求(三)

    2024-04-24 07:02:03       14 阅读
  10. 计算机网络 2.3数据交换技术

    2024-04-24 07:02:03       11 阅读