关于会话状态，一般是用于保存用户的会话状态。已适配的插件有：

| 插件 | 数据存储 | 补充说明 |
| -------- | -------- | -------- |
| [solon-sessionstate-local](/article/131)     | 保存在本地内存   | 通过 Cookie 传递客户端标识      |
| [solon-sessionstate-jedis](/article/130)     | 保存在 Redis 里（分布式）     | 通过 Cookie 传递客户端标识     |
| [solon-sessionstate-redisson](/article/237)     | 保存在 Redis 里（分布式）     | 通过 Cookie 传递客户端标识     |
| [solon-sessionstate-jwt](/article/132)     | 保存在 jwt 字符串中     | 通过 Cookie、Header、接口等...进行来回传递 jwt   |


Solon 的会话状态是外部化的，即不需要Http容器支持（如果Http容器自带，也可以使用其自带的），同时也非常方便定制。其中 [solon-sessionstate-jwt](/article/132)  是比较另类的定制方案，把 jwt 的使用改装成 SessionState 接口进行使用。插件的具体使用，请参考生态频道的具体插件使用说明。


### 1、接口使用示例

写入 session

```java
@Controller
public class LoginController{
    @Mapping("login")
    public void login(Context ctx){
        ctx.sessionSet("logined", true);
        ctx.sessionSet("name", "world");
    }
}
```

读取 session 数据

```java
@Controller
@Mapping("test")
public class UserController{
    @Mapping("case1")
    public String login(Context ctx){
        return ctx.session("name");
        //return ctx.session("name", "world"); //带默认值
    }
}
```

### 2、在模板里的使用

目前对模板引擎的适配，并未直接添加上下文或会话状态的变量。所以需要自己添加一下。。。一般不建议直接在模板里使用会话状态。


控制器

```java
@Controller
@Mapping("test")
public class UserController{
    @Mapping("case1")
    public ModelAndView login(Context ctx){
        Map<String,Object> model = new HashMap<>();
        model.put("ctx", ctx);
        
        return ModelAndView("test/cace1.ftl", model);
    }
}
```

模板 `test/cace1.ftl`

```xml
<html>
<head>
    <title>test</title>
</head>
<body>
 你好 ${ctx.session("name")!}
</body>
</html>
```


### 3、会话状态相关的接口


| 会话相关接口 | 说明 | 
| -------- | -------- | 
| -sessionState()->SessionState     | 获取 sessionState     | 
| -sessionId()->String     | 获取 sessionId     | 
| -session(String)->Object     | 获取 session 状态     | 
| -session(String, T)->T     | 获取 session 状态（类型转换，存在风险）     | 
| -sessionAsInt(String)->int     | 获取 session 状态以 int 型输出     | 
| -sessionAsInt(String, int)->int     | 获取 session 状态以 int 型输出, 并给定默认值     | 
| -sessionAsLong(String)->long     | 获取 session 状态以 long 型输出     | 
| -sessionAsLong(String, long)->long     | 获取 session 状态以 long 型输出, 并给定默认值     | 
| -sessionAsDouble(String)->double     | 获取 session 状态以 double 型输出     | 
| -sessionAsDouble(String, double)->double     | 获取 session 状态以 double 型输出, 并给定默认值     | 
| -sessionSet(String, Object)     | 设置 session 状态     | 
| -sessionRemove(String)     | 移除 session 状态     | 
| -sessionClear()     | 清空 session 状态     | 



### 4、自定义会话状态（不推荐）

非要自定义的话，建议用高性能的存储来做。以 JedisSessionState 实现为例，代码可参考：[仓库源码](https://gitee.com/noear/solon/tree/master/_solon_extend/solon.sessionstate.jedis)

#### a) 实现 SessionState 接口

```java
public class JedisSessionState implements SessionState { //也可以扩展自：SessionStateBase
    //...
}
```

#### b) 实现 SessionStateFactory 接口

```java
public class JedisSessionStateFactory implements SessionStateFactory {
    //...
}
```

#### c) 进行注册

```java
public class App{
    public static void main(String[] args){
        Solon.start(App.class, args, app->{
            Bridge.sessionStateFactorySet(new JedisSessionStateFactory());
        });    
    }
}
```

