-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
x-hansong
committed
Apr 29, 2016
1 parent
1d3aa48
commit f18b7c2
Showing
17 changed files
with
996 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio | ||
|
||
|
||
## Directory-based project format: | ||
.idea/ | ||
.gradle/ | ||
gradle/ | ||
# if you remove the above rule, at least ignore the following: | ||
|
||
# User-specific stuff: | ||
# .idea/workspace.xml | ||
# .idea/tasks.xml | ||
# .idea/dictionaries | ||
# .idea/shelf | ||
|
||
# Sensitive or high-churn files: | ||
# .idea/dataSources.ids | ||
# .idea/dataSources.xml | ||
# .idea/sqlDataSources.xml | ||
# .idea/dynamic.xml | ||
# .idea/uiDesigner.xml | ||
|
||
# Gradle: | ||
# .idea/gradle.xml | ||
# .idea/libraries | ||
|
||
# Mongo Explorer plugin: | ||
# .idea/mongoSettings.xml | ||
|
||
## File-based project format: | ||
*.ipr | ||
*.iws | ||
*.iml | ||
*.log | ||
|
||
## Plugin-specific files: | ||
|
||
# IntelliJ | ||
out/ | ||
gen/ | ||
build/ | ||
|
||
# mpeltonen/sbt-idea plugin | ||
.idea_modules/ | ||
|
||
# JIRA plugin | ||
atlassian-ide-plugin.xml | ||
|
||
# Crashlytics plugin (for Android Studio and IntelliJ) | ||
com_crashlytics_export_strings.xml | ||
crashlytics.properties | ||
crashlytics-build.properties | ||
fabric.properties | ||
|
||
|
||
# gradle files | ||
gradlew* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
group 'hansong' | ||
version '1.0-SNAPSHOT' | ||
|
||
apply plugin: 'java' | ||
|
||
sourceCompatibility = 1.5 | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
compile ( | ||
'javax:javaee-api:7.0', | ||
'redis.clients:jedis:2.8.0', | ||
"ch.qos.logback:logback-classic:1.0.13", | ||
'com.fasterxml.jackson.core:jackson-core:2.7.3', | ||
'com.fasterxml.jackson.core:jackson-databind:2.7.3', | ||
'commons-lang:commons-lang:2.3' | ||
) | ||
testCompile group: 'junit', name: 'junit', version: '4.11' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"cluster":"false", | ||
|
||
"connectionConfig": { | ||
"maxTotal": "10", | ||
"maxIdle": "10", | ||
"maxWait": "10000", | ||
"timeout": "10000" | ||
}, | ||
|
||
"redisServers":[ | ||
{ | ||
"ip":"112.74.215.22", | ||
"port":"63679", | ||
"password":"a12shg" | ||
} | ||
] | ||
|
||
} |
207 changes: 207 additions & 0 deletions
207
Core/src/main/java/com/hansong/session/RedisHttpSession.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
package com.hansong.session; | ||
|
||
import com.hansong.session.redis.RedisConnection; | ||
|
||
import javax.servlet.ServletContext; | ||
import javax.servlet.http.HttpSession; | ||
import javax.servlet.http.HttpSessionContext; | ||
import java.io.Serializable; | ||
import java.util.*; | ||
|
||
/** | ||
* Created by xhans on 2016/4/27. | ||
*/ | ||
public class RedisHttpSession implements HttpSession{ | ||
|
||
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800; | ||
|
||
private static final String SESSION_PREFIX = "session:"; | ||
private static final String SESSION_ATTR = "sessionAttr:"; | ||
private static final String CREATION_TIME = "creationTime"; | ||
private static final String LAST_ACCESSED_TIME = "lastAccessedTime"; | ||
private static final String MAX_INACTIVE_INTERVAL = "maxInactiveInterval"; | ||
|
||
private String key; | ||
private String id; | ||
private long creationTime; | ||
private long lastAccessedTime; | ||
private int maxInactiveInterval; | ||
|
||
private ServletContext servletContext; | ||
|
||
private RedisConnection redisConnection; | ||
|
||
private RedisHttpSession(){} | ||
|
||
|
||
private RedisHttpSession(ServletContext servletContext, RedisConnection redisConnection) { | ||
this.servletContext = servletContext; | ||
this.redisConnection = redisConnection; | ||
id = UUID.randomUUID().toString(); | ||
key = SESSION_PREFIX + id; | ||
creationTime = System.currentTimeMillis(); | ||
lastAccessedTime = creationTime; | ||
maxInactiveInterval = DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS; | ||
//save to redis | ||
saveSession(); | ||
} | ||
|
||
public static RedisHttpSession createNew(ServletContext servletContext, RedisConnection redisConnection){ | ||
return new RedisHttpSession(servletContext, redisConnection); | ||
} | ||
|
||
public static RedisHttpSession createWithExistSession(String token, ServletContext servletContext, RedisConnection redisConnection){ | ||
RedisHttpSession redisHttpSession= new RedisHttpSession(); | ||
redisHttpSession.setId(token); | ||
redisHttpSession.setKey(SESSION_PREFIX + token); | ||
redisHttpSession.setServletContext(servletContext); | ||
redisHttpSession.setRedisConnection(redisConnection); | ||
|
||
return redisHttpSession; | ||
} | ||
|
||
public void setId(String id) { | ||
this.id = id; | ||
} | ||
|
||
|
||
public void setServletContext(ServletContext servletContext) { | ||
this.servletContext = servletContext; | ||
} | ||
|
||
@Override | ||
public long getCreationTime() { | ||
return (long) redisConnection.hget(key, CREATION_TIME); | ||
} | ||
|
||
@Override | ||
public String getId() { | ||
return id; | ||
} | ||
|
||
@Override | ||
public long getLastAccessedTime() { | ||
return (long) redisConnection.hget(key, LAST_ACCESSED_TIME); | ||
} | ||
|
||
@Override | ||
public ServletContext getServletContext() { | ||
return servletContext; | ||
} | ||
|
||
@Override | ||
public void setMaxInactiveInterval(int interval) { | ||
redisConnection.hset(key, MAX_INACTIVE_INTERVAL, interval); | ||
} | ||
|
||
@Override | ||
public int getMaxInactiveInterval() { | ||
return (int) redisConnection.hget(key, MAX_INACTIVE_INTERVAL); | ||
} | ||
|
||
@Override | ||
public HttpSessionContext getSessionContext() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public Object getAttribute(String name) { | ||
return redisConnection.hget(key, SESSION_ATTR + name); | ||
} | ||
|
||
@Override | ||
public Object getValue(String name) { | ||
return getAttribute(name); | ||
} | ||
|
||
@Override | ||
public Enumeration<String> getAttributeNames() { | ||
return Collections.enumeration(getAttributeKeys()); | ||
} | ||
|
||
private Set<String> getAttributeKeys(){ | ||
Set<String> keys = redisConnection.hkeys(key); | ||
Set<String> attrNames = new HashSet<>(); | ||
for (String key : keys){ | ||
if (key.startsWith(SESSION_ATTR)){ | ||
attrNames.add(key.substring(SESSION_ATTR.length())); | ||
} | ||
} | ||
return attrNames; | ||
} | ||
|
||
|
||
@Override | ||
public String[] getValueNames() { | ||
return getAttributeKeys().toArray(new String[0]); | ||
} | ||
|
||
@Override | ||
public void setAttribute(String name, Object value) { | ||
redisConnection.hset(key, SESSION_ATTR + name, (Serializable) value); | ||
} | ||
|
||
@Override | ||
public void putValue(String name, Object value) { | ||
setAttribute(name, value); | ||
} | ||
|
||
@Override | ||
public void removeAttribute(String name) { | ||
redisConnection.hdel(key, name); | ||
} | ||
|
||
@Override | ||
public void removeValue(String name) { | ||
removeAttribute(name); | ||
} | ||
|
||
@Override | ||
public void invalidate() { | ||
redisConnection.del(key); | ||
} | ||
|
||
@Override | ||
public boolean isNew() { | ||
return false; | ||
} | ||
|
||
private void saveSession(){ | ||
redisConnection.hset(key, LAST_ACCESSED_TIME, lastAccessedTime); | ||
redisConnection.hset(key, CREATION_TIME, creationTime); | ||
redisConnection.hset(key, MAX_INACTIVE_INTERVAL, maxInactiveInterval); | ||
refresh(); | ||
} | ||
|
||
/** | ||
* 更新过期时间 | ||
*/ | ||
public void refresh(){ | ||
redisConnection.expire(key, maxInactiveInterval); | ||
} | ||
|
||
public RedisConnection getRedisConnection() { | ||
return redisConnection; | ||
} | ||
|
||
public void setRedisConnection(RedisConnection redisConnection) { | ||
this.redisConnection = redisConnection; | ||
} | ||
|
||
public void setLastAccessedTime(long lastAccessedTime) { | ||
redisConnection.hset(key, LAST_ACCESSED_TIME, lastAccessedTime); | ||
} | ||
|
||
public String getKey() { | ||
return key; | ||
} | ||
|
||
public void setKey(String key) { | ||
this.key = key; | ||
} | ||
|
||
public boolean isInvalidated() { | ||
return redisConnection.exists(key); | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
Core/src/main/java/com/hansong/session/RedisHttpSessionFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.hansong.session; | ||
|
||
import javax.servlet.*; | ||
import java.io.IOException; | ||
|
||
/** | ||
* Created by xhans on 2016/4/27. | ||
*/ | ||
public class RedisHttpSessionFilter implements Filter { | ||
|
||
@Override | ||
public void init(FilterConfig filterConfig) throws ServletException { | ||
|
||
} | ||
|
||
@Override | ||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | ||
|
||
} | ||
|
||
@Override | ||
public void destroy() { | ||
|
||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
Core/src/main/java/com/hansong/session/RedisHttpSessionProxy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.hansong.session; | ||
|
||
import com.hansong.session.redis.RedisConnection; | ||
|
||
import java.lang.reflect.InvocationHandler; | ||
import java.lang.reflect.Method; | ||
import java.lang.reflect.Proxy; | ||
|
||
/** | ||
* Created by xhans on 2016/4/29. | ||
*/ | ||
public class RedisHttpSessionProxy implements InvocationHandler { | ||
private Object originalObj; | ||
|
||
private RedisHttpSessionRepository repository = RedisHttpSessionRepository.getInstance(); | ||
|
||
public Object bind(Object originalObj) { | ||
this.originalObj = originalObj; | ||
return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this); | ||
} | ||
|
||
@Override | ||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | ||
RedisHttpSession session = (RedisHttpSession) originalObj; | ||
//check redis connection | ||
RedisConnection connection = session.getRedisConnection(); | ||
if (!connection.isConnected()){ | ||
connection.close(); | ||
session.setRedisConnection(repository.getRedisConnection()); | ||
} | ||
//For every methods of interface, check it valid or not | ||
if (!session.isInvalidated()){ | ||
throw new IllegalStateException("The HttpSession has already be invalidated."); | ||
} else { | ||
Object result = method.invoke(originalObj, args); | ||
//if not invalidate method, refresh expireTime and lastAccessedTime; | ||
if (!method.getName().equals("invalidate")) { | ||
session.refresh(); | ||
session.setLastAccessedTime(System.currentTimeMillis()); | ||
} | ||
return result; | ||
} | ||
} | ||
} |
Oops, something went wrong.