简体   繁体   English

访问servlet外部的会话变量

[英]Accessing session variables outside servlet

I'm working on a java webapp where I need to access records from database based on user login id.I set the login details in session variable after successful login. 我正在开发一个java webapp,我需要根据用户登录ID访问数据库中的记录。我在成功登录后在会话变量中设置登录详细信息。

I want to do is something like this 我想做的就是这样

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

Right now I'm passing username as a parameter, but I believe it's not a good practice. 现在我将用户名作为参数传递,但我认为这不是一个好习惯。 Is there a better way of accessing session variables outside servlet ? 有没有更好的方法来访问servlet之外的会话变量?

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;

}

The problem is I have to modify all my methods with userid. 问题是我必须用userid修改我的所有方法。 Is there a way I can set user details into some static class and access the details where ever i want in the application without modifying the method signature? 有没有办法可以将用户详细信息设置为某个静态类,并在不修改方法签名的情况下访问应用程序中我想要的详细信息? But I believe static classes are share between different user requests. 但我相信静态类是在不同的用户请求之间共享的。

The solution that you are looking for is Thread Local (google it). 您正在寻找的解决方案是Thread Local(google it)。 It allows you to access thread-specific data using static method. 它允许您使用静态方法访问特定于线程的数据。

You can start reading http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/ . 您可以开始阅读http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/ Using examples from there, you need to create: 使用那里的示例,您需要创建:

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();
    }
}

in your servlet, do this: 在您的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();
    }
}

in your data layer, you can retrieve the user by doing this: 在您的数据层中,您可以通过执行以下操作来检索用户:

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

Notice that you don't need to change the method signature of the data layer. 请注意,您无需更改数据层的方法签名。

Thread Local is a bit confusing at first, but you will get familiar very quickly once you read the article. 线程本地起初有点令人困惑,但是一旦你阅读了这篇文章,你就会很快熟悉。

I think u can easily use 我想你可以轻松使用

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

so no need to change signature. 所以不需要改变签名。 This way you can use shiros inbuilt utility instead of relying on your own logics and probabilties. 这样您就可以使用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;

}

You can always get the user id from the session inside servlet and pass that to your data layer, there is no point using session directly in the data layer. 您始终可以从servlet中的会话中获取用户标识并将其传递给数据层,在数据层中直接使用会话是没有意义的。 You extract your objects and pass the buck to the next layer. 您提取对象并将降压传递到下一层。 Using HTTP specific objects in the data layer is actually the bad practice. 在数据层中使用HTTP特定对象实际上是不好的做法。

With strict separation of concerns, the data layer should have nothing to do with the session or request. 通过严格分离关注点,数据层应该与会话或请求无关。 But you need the username ( user_id from you example) in service or data layer. 但是您需要服务或数据层中的用户名(来自您示例的user_id )。 The simplest is effectively to collect it in controller (controller has access to request and session), pass it to service layer, and forward it to data layer. 最简单的是有效地在控制器中收集它(控制器可以访问请求和会话),将其传递给服务层,并将其转发到数据层。

An alternative (used by security framework like Spring Security or Apache Shiro) is to store it in thread storage at beginning of the request treatement, and carefully clean it out at end (in a filter). 另一种方法(由Spring Security或Apache Shiro等安全框架使用)是在请求处理开始时将其存储在线程存储中,并在结束时(在过滤器中)仔细清理它。 Then a static method of an utility class can give it to any part of your application. 然后,实用程序类的静态方法可以将其提供给应用程序的任何部分。 But you get a dependency to the framework each time you use the utility class. 但是每次使用实用程序类时,都会获得对框架的依赖。 To reduce undue dependances, you can have your own Holder class, with a static method that calls the one of the framework : the dependance is limited to the holder class. 为了减少不必要的依赖,你可以拥有自己的Holder类,使用一个静态方法来调用框架之一:依赖性仅限于holder类。

There is a third solution if you use Spring. 如果你使用Spring,还有第三种解决方案。 You can have a session scoped bean, with aop proxying, that you can inject in any bean that need access to your variable. 您可以使用具有aop代理的会话范围bean,您可以在任何需要访问您的变量的bean中注入。 Thanks to aop proxying you will have access to the data from current session, even from a singleton bean. 感谢aop代理,您可以访问当前会话中的数据,甚至可以访问单个bean。

In my own apps, I use first method in simple cases (few classes) and third method when I want to avoid repeating over and over the same parameters in many methods. 在我自己的应用程序中,我在简单情况下使用第一种方法(少数类)和第三种方法,当我想避免在许多方法中重复使用相同的参数时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM