From f89ccf5c31522680a278fd05e52adee8876f0419 Mon Sep 17 00:00:00 2001 From: kishida Date: Sun, 10 Apr 2016 21:44:48 +0900 Subject: [PATCH 1/3] Session Scope base --- .../java/kis/di/annotation/SessionScoped.java | 16 +++++++++++ src/main/java/kis/di/mvc/BeanSession.java | 27 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/main/java/kis/di/annotation/SessionScoped.java create mode 100644 src/main/java/kis/di/mvc/BeanSession.java diff --git a/src/main/java/kis/di/annotation/SessionScoped.java b/src/main/java/kis/di/annotation/SessionScoped.java new file mode 100644 index 0000000..6e0da71 --- /dev/null +++ b/src/main/java/kis/di/annotation/SessionScoped.java @@ -0,0 +1,16 @@ +package kis.di.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author naoki + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface SessionScoped { + +} diff --git a/src/main/java/kis/di/mvc/BeanSession.java b/src/main/java/kis/di/mvc/BeanSession.java new file mode 100644 index 0000000..73fde12 --- /dev/null +++ b/src/main/java/kis/di/mvc/BeanSession.java @@ -0,0 +1,27 @@ +package kis.di.mvc; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * + * @author naoki + */ +public class BeanSession { + private ThreadLocal sessionId = new InheritableThreadLocal<>(); + private Map> beans = new HashMap<>(); + + public void setSessionId(String id) { + sessionId.set(id); + beans.put(id, new HashMap<>()); + } + + public Optional getBean(String name) { + return Optional.ofNullable(beans.get(sessionId.get()).get(name)); + } + + public void register(String name, Object bean) { + beans.get(sessionId.get()).put(name, bean); + } +} From 1e9df5e619ee19b8437abd18a20e132f91ffd2c3 Mon Sep 17 00:00:00 2001 From: kishida Date: Tue, 12 Apr 2016 05:09:08 +0900 Subject: [PATCH 2/3] Session Scope almost implemented --- src/main/java/kis/di/Context.java | 23 +++++++++- src/main/java/kis/di/mvc/BeanSession.java | 20 +++++---- src/main/java/kis/di/mvc/Server.java | 21 ++++++++-- .../kis/di/sample/mvc/LoginController.java | 42 +++++++++++++++++++ .../java/kis/di/sample/mvc/LoginSession.java | 20 +++++++++ 5 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 src/main/java/kis/di/sample/mvc/LoginController.java create mode 100644 src/main/java/kis/di/sample/mvc/LoginSession.java diff --git a/src/main/java/kis/di/Context.java b/src/main/java/kis/di/Context.java index 7587153..cff30f6 100644 --- a/src/main/java/kis/di/Context.java +++ b/src/main/java/kis/di/Context.java @@ -28,6 +28,8 @@ import javassist.NotFoundException; import kis.di.annotation.InvokeLog; import kis.di.annotation.RequestScoped; +import kis.di.annotation.SessionScoped; +import kis.di.mvc.BeanSession; /** * @author naoki @@ -38,6 +40,12 @@ public class Context { static Map beans = new HashMap<>(); static ThreadLocal> requestBeans = new InheritableThreadLocal<>(); + static BeanSession beanSession; + + public static void setBeanSession(BeanSession beanSession) { + Context.beanSession = beanSession; + } + public static void autoRegister() { try { URL res = Context.class.getResource( @@ -87,6 +95,8 @@ public static Object getBean(String name) { scope = new HashMap<>(); requestBeans.set(scope); } + } else if (type.isAnnotationPresent(SessionScoped.class)) { + scope = beanSession.getBeans(); } else { scope = beans; } @@ -139,6 +149,16 @@ private static Class wrap(Class type) { } } + private static int scopeRank(Class type) { + if (type.isAnnotationPresent(RequestScoped.class)) { + return 0; + } + if (type.isAnnotationPresent(SessionScoped.class)) { + return 5; + } + return 10; + } + private static void inject(Class type, T object) throws IllegalArgumentException, IllegalAccessException { for (Field field : type.getDeclaredFields()) { if (!field.isAnnotationPresent(Inject.class)) { @@ -146,7 +166,8 @@ private static void inject(Class type, T object) throws IllegalArgumentEx } field.setAccessible(true); Object bean; - if (!type.isAnnotationPresent(RequestScoped.class) && field.getType().isAnnotationPresent(RequestScoped.class)) { + + if (scopeRank(type) > scopeRank(field.getType())) { bean = scopeWrapper(field.getType(), field.getName()); } else { bean = getBean(field.getName()); diff --git a/src/main/java/kis/di/mvc/BeanSession.java b/src/main/java/kis/di/mvc/BeanSession.java index 73fde12..d0cf573 100644 --- a/src/main/java/kis/di/mvc/BeanSession.java +++ b/src/main/java/kis/di/mvc/BeanSession.java @@ -2,26 +2,28 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; /** * * @author naoki */ public class BeanSession { - private ThreadLocal sessionId = new InheritableThreadLocal<>(); - private Map> beans = new HashMap<>(); + private final ThreadLocal sessionId = new InheritableThreadLocal<>(); + private final Map> beans = new HashMap<>(); public void setSessionId(String id) { sessionId.set(id); - beans.put(id, new HashMap<>()); + if (!beans.containsKey(id)) { + beans.put(id, new HashMap<>()); + } } - public Optional getBean(String name) { - return Optional.ofNullable(beans.get(sessionId.get()).get(name)); + public Map getBeans() { + return beans.get(sessionId.get()); } - - public void register(String name, Object bean) { - beans.get(sessionId.get()).put(name, bean); + + public boolean isSessionRegistered(String id) { + return beans.containsKey(id); } + } diff --git a/src/main/java/kis/di/mvc/Server.java b/src/main/java/kis/di/mvc/Server.java index 960328e..cacdd26 100644 --- a/src/main/java/kis/di/mvc/Server.java +++ b/src/main/java/kis/di/mvc/Server.java @@ -41,6 +41,8 @@ static String trimSlash(String str) { public static void main(String[] args) throws IOException { Context.autoRegister(); + BeanSession beanSession = new BeanSession(); + Context.setBeanSession(beanSession); Map methods = new HashMap<>(); Context.registeredClasses().forEach(entry -> { Class cls = entry.getValue(); @@ -73,7 +75,7 @@ public static void main(String[] args) throws IOException { Pattern pattern = Pattern.compile("([A-Z]+) ([^ ]+) (.+)"); Pattern patternHeader = Pattern.compile("([A-Za-z-]+): (.+)"); - AtomicLong lastSessionId = new AtomicLong(); + AtomicLong lastSessionId = new AtomicLong(10); ServerSocket serverSoc = new ServerSocket(8989); ExecutorService executors = Executors.newFixedThreadPool(10); for (;;) { @@ -113,8 +115,18 @@ public static void main(String[] args) throws IOException { } } } - String sessionId = cookies.getOrDefault("jsessionid", - Long.toString(lastSessionId.incrementAndGet())); + + + String sessionId = cookies.get("jsessionid"); + if (sessionId != null) { + if (!beanSession.isSessionRegistered(sessionId)) { + sessionId = null; + } + } + if (sessionId == null) { + sessionId = Long.toString(lastSessionId.incrementAndGet()); + } + beanSession.setSessionId(sessionId); info.setSessionId(sessionId); try (OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os)) @@ -137,11 +149,12 @@ public static void main(String[] args) throws IOException { pw.println(); pw.println(output); } catch (Exception ex) { - pw.println("HTTP/1.0 200 OK"); + pw.println("HTTP/1.0 500 Internal Server Error"); pw.println("Content-Type: text/html"); pw.println(); pw.println("

500 Internal Server Error

"); pw.println(ex); + ex.printStackTrace(); } } } catch (IOException ex) { diff --git a/src/main/java/kis/di/sample/mvc/LoginController.java b/src/main/java/kis/di/sample/mvc/LoginController.java new file mode 100644 index 0000000..5f7ea74 --- /dev/null +++ b/src/main/java/kis/di/sample/mvc/LoginController.java @@ -0,0 +1,42 @@ +package kis.di.sample.mvc; + +import java.time.LocalDateTime; + +import javax.inject.Inject; +import javax.inject.Named; + +import kis.di.annotation.Path; + +/** + * + * @author naoki + */ +@Named +@Path("login") +public class LoginController { + + @Inject + LoginSession loginSession; + + @Path("index") + public String index() { + String title = "

Login

"; + if (loginSession.isLogined()) { + return title + "Login at " + loginSession.getLoginTime(); + } else { + return title + "Not Login"; + } + } + + @Path("login") + public String login() { + loginSession.setLogined(true); + loginSession.setLoginTime(LocalDateTime.now()); + return "

Login

login"; + } + @Path("logout") + public String logout() { + loginSession.setLogined(false); + return "

Login

logout"; + } +} diff --git a/src/main/java/kis/di/sample/mvc/LoginSession.java b/src/main/java/kis/di/sample/mvc/LoginSession.java new file mode 100644 index 0000000..a3cfed4 --- /dev/null +++ b/src/main/java/kis/di/sample/mvc/LoginSession.java @@ -0,0 +1,20 @@ +package kis.di.sample.mvc; + +import java.time.LocalDateTime; + +import javax.inject.Named; + +import kis.di.annotation.SessionScoped; +import lombok.Data; + +/** + * + * @author naoki + */ +@Named +@SessionScoped +@Data +public class LoginSession { + boolean logined; + LocalDateTime loginTime; +} From becc4131ed369c59156e42343f67b86c521329e0 Mon Sep 17 00:00:00 2001 From: kishida Date: Tue, 12 Apr 2016 23:32:50 +0900 Subject: [PATCH 3/3] ThreadLocal problem with thread pool --- src/main/java/kis/di/mvc/Server.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/kis/di/mvc/Server.java b/src/main/java/kis/di/mvc/Server.java index cacdd26..b8b2601 100644 --- a/src/main/java/kis/di/mvc/Server.java +++ b/src/main/java/kis/di/mvc/Server.java @@ -11,8 +11,6 @@ import java.net.Socket; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,10 +75,9 @@ public static void main(String[] args) throws IOException { Pattern patternHeader = Pattern.compile("([A-Za-z-]+): (.+)"); AtomicLong lastSessionId = new AtomicLong(10); ServerSocket serverSoc = new ServerSocket(8989); - ExecutorService executors = Executors.newFixedThreadPool(10); for (;;) { Socket s = serverSoc.accept(); - executors.execute(() -> { + new Thread(() -> { try (InputStream is = s.getInputStream(); BufferedReader bur = new BufferedReader(new InputStreamReader(is))) { @@ -116,7 +113,6 @@ public static void main(String[] args) throws IOException { } } - String sessionId = cookies.get("jsessionid"); if (sessionId != null) { if (!beanSession.isSessionRegistered(sessionId)) { @@ -160,7 +156,7 @@ public static void main(String[] args) throws IOException { } catch (IOException ex) { System.out.println(ex); } - }); + }).start(); } } }