用户管理的Vaadin ThreadLocal

时间:2018-05-31 11:33:26

标签: java vaadin thread-local

我目前正在开发一个Java应用程序,同时由多个用户访问,因此需要存储用户数据,以便根据个人需求定制应用程序(例如他们是哪家公司)除了等)。

我用两个类来管理它。 User,MainSystem详细说明如下:

用户

@Entity
public class User implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private String username;
    private String password;
    private String type;
    private String company;
    private String DOB;
    private String email;
    private int PayrollId;

    public User(String firstName, String lastName, String username, String password, String type, String company, String DOB, String email) {
        this.firstName = firstName;
        this. lastName = lastName;
        this.username = username;
        this.password = password;
        this.type = type;
        this.company = company;
        this.DOB = DOB;
        this.email = email;
    }

MainSystem:

public class MainSystem   {

    public UserController userController;
    private UserRepository userRepository;
    private static ThreadLocal<User> loggedInUser = new ThreadLocal<>();
    public DbController dbController;


public MainSystem(){
userController = new UserController(userRepository);
loggedInUser.set(new User());
}

 public Boolean Login(String username, String password) {
        if(userController.checkUser(username,password)){
            User aUser = userController.getUser(username);
            setLoggedInUser(userController.getUser(username));
            VaadinSession.getCurrent().setAttribute("username",loggedInUser.get().getUsername());
            System.out.println("Logged in User:  "+loggedInUser.get().getUsername());
               return true;
        }
        else {
            return false;
        }
        }

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

    public static User  getLoggedInUser() {
        return loggedInUser.get();
    }

理想情况下,我想要做的是从另一个类访问ThreadLocal变量,例如ViewProfile.View:

public class EditProfileView extends VerticalLayout implements View {

    MainSystem main = new MainSystem();
    NavigatorUI aUI = new NavigatorUI();
    User aUser = main.getLoggedInUser();
    TextField username = new TextField("Username");
    TextField Id = new TextField("Id");
    TextField email = new TextField("Email");
    TextField firstName = new TextField("First name");
    TextField lastName = new TextField("Last name");
    TextField type = new TextField("Type");
    PasswordField oldPassword = new PasswordField("Current Password");
    PasswordField changePassword1 = new PasswordField("New Password");
    PasswordField changePassword2 = new PasswordField("Confirm Password");
    private UserController userController;
    private UserRepository userRepository;

    public EditProfileView() {
        setDefaultComponentAlignment(Alignment.MIDDLE_CENTER);
        userController = new UserController(userRepository);
     setStyleName("backgroundImage");
     setMargin(true);
     setSizeFull();
     addComponent(aUI.getHeader());
     FormLayout content = new FormLayout(generateInfo());
     Panel aPanel = new Panel("Edit User",content);
     aPanel.setWidthUndefined();
    content.setMargin(true);
    aPanel.setStyleName(ValoTheme.PANEL_WELL);
    addComponent(aPanel);
    }
 @Override
    public void enter(ViewChangeListener.ViewChangeEvent event) {
       try {
           aUser = main.getLoggedInUser();
        System.out.println( aUser.getUsername());
        Id.setValue(aUser.getId().toString());
        username.setValue(aUser.getUsername());
        firstName.setValue(aUser.getFirstName());
        lastName.setValue(aUser.getLastName());
        type.setValue(aUser.getType());
        email.setValue(aUser.getEmail());
        aUI.setUserMenu();
        aUI.refreshPayroll();}
        catch (Exception e){
           System.out.println(e.getMessage());
        }
    }}

然而,我发现它正在向我展示一个&#34; null&#34;值?我担心我可能会错过了解ThreadLocal的工作原理。但基本上我想要实现的是在MainSystem中存储User.Class的实例相关变量以供其他类使用?

任何帮助都将不胜感激。

我的解决方案:

我的解决方案是将User.class存储在VaadinSession属性中,如下所示:

public Boolean Login(String username, String password) {
        if(userController.checkUser(username,password)){
            User aUser = userController.getUser(username);
            VaadinSession.getCurrent().setAttribute("user",aUser);
                          VaadinSession.getCurrent().setAttribute("username",loggedInUser.get().getUsername());
            System.out.println("Logged in User:  "+loggedInUser.get().getUsername());
               return true;
        }
        else {
            return false;
        }
        }

然后在其他类中,如果我想使用该属性,我会像这样检索它:

@Override
    public void enter(ViewChangeListener.ViewChangeEvent event) {
       try {
           aUser = (User)VaadinSession.getCurrent().getAttribute("user");
       }
        catch (Exception e){
           System.out.println(e.getMessage());
        }
    }

2 个答案:

答案 0 :(得分:2)

问题在于,无法保证MainSystem.Login()EditProfileView.enter()将在同一个线程上发生。每个用户操作都作为单独的HTTP请求处理,servlet容器将在任何可用的线程上运行。

对于这种功能,我建议将用户信息存储在HTTP会话中。如果您没有任何自定义servlet等,则可以在自定义UI类中包含一个包含用户对象的字段。 Vaadin负责使UI.getCurrent()始终在通过Vaadin运行的所有代码中返回正确的值。

如果您正在与其他servlet功能集成,则可以将用户存储在HttpSession中。通用servlet代码可以通过例如getSession()方法找到会话。 servlet请求和响应。在Vaadin运行的代码中,您可以使用VaadinSession().getCurrent().getSession()获取基于相同WrappedSession数据的HttpSession实例。

答案 1 :(得分:0)

还有另一种方法。相反,它可以使@SessionScoped用户服务,以及@Inject或@Autowire取决于您是否使用CDI或Spring。这样做的时候,bean管理器会负责用你的视图绑定正确的实体。