• 自己实现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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    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());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    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());
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    【LeetCode】【数组】【二分】4. 寻找两个正序数组的中位数 Java实现(四种方案,目前写了两种,还在更新)
    zabbix监控——监控应用
    sql注入
    进程,内核线程,用户线程,协程,纤程......操作系统世界观
    Apache Pulsar 在腾讯云上的最佳实践
    web3.0链游农民世界开发搭建0撸狼人杀玩法模式定制开发
    Dubbo的集群容错方案
    微服务项目:尚融宝(51)(核心业务流程:充值服务(1))
    Auracast 广播音频知识点
    基于Python和Pandas对主流婚恋网站数据可视化分析
  • 原文地址:https://blog.csdn.net/by2233/article/details/138142372