访问servlet外部的会话变量

时间:2014-06-20 14:22:15

标签: java session servlets

我正在使用java webapp,我需要根据用户登录ID访问数据库中的记录。我在成功登录后在会话变量中设置登录详细信息。

我想做的就像这样

从proj_recs中选择*,其中user_id = user_id(来自会话)

现在我将用户名作为参数传递,但我认为这不是一个好习惯。有没有更好的方法来访问servlet之外的会话变量?

Servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub

        User user = (User) request.getSession().getAttribute("userInfo");

        System.out.println(user);

        if(user != null){
            Gson gson = new Gson();
            returnJsonResponse(response,gson.toJson(user));
            return;
        }
}

在数据图层包中

public Accrual getAccruals(String accrualID,String userid) throws AccrualNotFoundException{

    String sql = Select * from db_acc where acc_id= accrualID and user_id=userid;

}

问题是我必须用userid修改我的所有方法。有没有办法可以将用户详细信息设置为某个静态类,并在不修改方法签名的情况下访问应用程序中我想要的详细信息?但我相信静态类在不同的用户请求之间共享。

4 个答案:

答案 0 :(得分:2)

您正在寻找的解决方案是Thread Local(google it)。它允许您使用静态方法访问特定于线程的数据。

您可以开始阅读http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/。使用那里的示例,您需要创建:

public class MyThreadLocal {

    public static final ThreadLocal userThreadLocal = new ThreadLocal();

    public static void set(User user) {
        userThreadLocal.set(user);
    }

    public static void unset() {
        userThreadLocal.remove();
    }

    public static User get() {
        return userThreadLocal.get();
    }
}
在你的servlet中,执行以下操作:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    User user = (User) request.getSession().getAttribute("userInfo");
    MyThreadLocal.set(user);
    try {
       // call data layer
    } finally {
        MyThreadLocal.unset();
    }
}

在您的数据层中,您可以通过执行以下操作来检索用户:

public void dataLayerMethod(ExistingParameters parameters) {
    User user = MyThreadLocal.get();
}

请注意,您不需要更改数据层的方法签名。

线程本地起初有点令人困惑,但是一旦你阅读这篇文章,你就会很快熟悉。

答案 1 :(得分:1)

我想你可以轻松使用

SecurityUtils.getSubject().getSession().getAttribute("userInfo");

因此无需更改签名。这样您就可以使用shiros内置实用程序,而不是依赖于您自己的逻辑和概率。<​​/ p>

public Accrual getAccruals(String accrualID) throws AccrualNotFoundException{
    User user = (User) SecurityUtils.getSubject().getSession().getAttribute("userInfo");
    String userid= user.getUserId();
    String sql = Select * from db_acc where acc_id= accrualID and user_id=userid;

}

答案 2 :(得分:0)

您始终可以从servlet中的会话中获取用户ID并将其传递给数据层,在数据层中直接使用会话是没有意义的。您提取对象并将降压传递到下一层。在数据层中使用HTTP特定对象实际上是不好的做法。

答案 3 :(得分:0)

通过严格分离关注点,数据层应该与会话或请求无关。但是您需要服务或数据层中的用户名(示例中为user_id)。最简单的是有效地在控制器中收集它(控制器可以访问请求和会话),将其传递给服务层,并将其转发到数据层。

另一种选择(由Spring Security或Apache Shiro等安全框架使用)是在请求处理开始时将其存储在线程存储中,并在结束时(在过滤器中)仔细清理它。然后,实用程序类的静态方法可以将其提供给应用程序的任何部分。但是每次使用实用程序类时,都会获得对框架的依赖。 为了减少不必要的依赖,你可以拥有自己的Holder类,使用一个静态方法来调用框架之一:依赖只限于holder类。

如果使用Spring,还有第三种解决方案。您可以使用具有aop代理的会话范围bean,您可以在任何需要访问您的变量的bean中注入。感谢aop代理,您可以访问当前会话中的数据,甚至可以访问单个bean。

在我自己的应用程序中,我在简单情况下使用第一种方法(少数类)和第三种方法,当我想避免在许多方法中重复使用相同的参数时。