首页 文章

访问servlet外部的会话变量

提问于
浏览
5

我正在开发一个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;
        }
}

In data layer package

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 回答

  • 1

    您正在寻找的解决方案是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();
    }
    

    请注意,您无需更改数据层的方法签名 .

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

  • 2

    我想你可以轻松使用

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

    所以不需要改变签名 . 这样您就可以使用shiros内置实用程序,而不是依赖于您自己的逻辑和概率 .

    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;
    
    }
    
  • 0

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

  • 0

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

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

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

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

相关问题