You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Play Framework(Java)中修改或延长session.maxAge会话超时值

嘿,刚接触Play Framework时我也踩过会话超时的坑,刚好有几个实用的方案能解决你的问题——核心就是在用户每次操作时重置会话的过期时间,下面给你详细讲讲:

方案1:全局过滤器自动刷新会话(推荐)

这种方式最省心,不用改每个控制器代码,所有用户请求都会自动刷新会话超时(仅限已登录用户)。

步骤1:编写自定义过滤器

创建一个过滤器类,拦截所有请求,判断用户已登录后重置会话超时:

import play.mvc.Filter;
import play.mvc.Http;
import play.mvc.Result;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;

public class SessionRefreshFilter extends Filter {
    @Override
    public CompletionStage<Result> apply(Function<Http.RequestHeader, CompletionStage<Result>> next, Http.RequestHeader request) {
        return next.apply(request).thenApply(result -> {
            // 这里假设你用"loggedInUser"作为会话中存储的登录标识,根据你的实际字段修改
            if (request.session().containsKey("loggedInUser")) {
                // 重置会话超时为30分钟
                return result.withSession(request.session().setMaxAge(java.time.Duration.ofMinutes(30)));
            }
            return result;
        });
    }
}

步骤2:注册过滤器

在application.conf里添加过滤器配置,让Play加载它:

play.filters.enabled += "com.yourproject.filters.SessionRefreshFilter"

(记得把包路径改成你自己项目的实际路径)

方案2:自定义ActionBuilder,按需应用

如果不想全局生效,只想给特定控制器/Action添加刷新逻辑,可以用自定义Action:

步骤1:编写Action类

import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

public class RefreshSessionAction extends Action.Simple {
    @Override
    public CompletionStage<Result> call(Http.Context ctx) {
        // 仅对已登录用户刷新会话
        if (ctx.session().containsKey("loggedInUser")) {
            ctx.session().setMaxAge(java.time.Duration.ofMinutes(30));
        }
        return delegate.call(ctx);
    }
}

步骤2:在控制器中使用

在需要刷新会话的控制器或Action上添加@With注解:

import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.With;

@With(RefreshSessionAction.class)
public class DashboardController extends Controller {
    public Result dashboard() {
        return ok(views.html.dashboard.render());
    }

    // 其他需要刷新会话的Action...
}
方案3:前端心跳请求(适合单页应用)

如果你的项目是SPA(单页应用),用户可能长时间停留在同一个页面但有操作,可以用前端定时发心跳请求到后端,触发会话刷新:

前端代码(JS)

// 每25分钟发送一次心跳(比30分钟超时短5分钟,避免刚好在超时前没触发)
setInterval(() => {
    // 发送请求到后端刷新会话接口
    fetch('/api/refresh-session', {
        method: 'GET',
        credentials: 'include' // 携带会话Cookie
    });
}, 25 * 60 * 1000);

后端接口

在控制器里加一个处理心跳的Action:

public Result refreshSession() {
    if (session().containsKey("loggedInUser")) {
        session().setMaxAge(java.time.Duration.ofMinutes(30));
        return ok();
    }
    return unauthorized();
}

路由配置

在routes文件中添加路由:

GET     /api/refresh-session       controllers.SessionController.refreshSession()
注意事项
  • 会话标识:上面的示例用loggedInUser作为已登录的判断依据,你需要改成自己项目中实际存储的登录用户字段(比如userId、username)。
  • Play版本兼容性:以上代码基于Play 2.8+,如果是更低版本,Duration的用法可能略有不同,比如用旧的时间API适配。
  • 安全性:Play的会话Cookie是签名过的,修改后会自动重新签名,不用担心篡改问题。

这样配置后,用户每次操作(或心跳请求)都会把会话超时重置为30分钟,就不会出现用户还在操作就被踢下线的情况啦!

内容的提问来源于stack exchange,提问作者Ravindra More

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:00:43