Vaadin ThreadLocal для управления пользователями

В настоящее время я разрабатываю веб-приложение на Java, к которому будут обращаться одновременно несколько пользователей, и поэтому мне необходимо хранить пользовательские данные, чтобы адаптировать приложение к их индивидуальным требованиям (например, к какой компании они принадлежат и т. д.).

Есть 2 класса, которые я использую, чтобы справиться с этим. Пользователь, 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());
        }
    }}

Однако я обнаружил, что он представляет мне "нулевое" значение? Боюсь, я неправильно понял, как работает ThreadLocal. но по сути то, что я пытаюсь достичь, - это сохранить соответствующую экземпляру переменную User.Class в MainSystem для использования другими классами?

Любая помощь будет оценена по достоинству.

Мое решение:

Мое решение состояло в том, чтобы сохранить 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());
        }
    }
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
253
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема в том, что нет гарантии, что MainSystem.Login() и EditProfileView.enter() будут работать в одном потоке. Каждое действие пользователя обрабатывается как отдельный HTTP-запрос, который контейнер сервлета будет запускать в любом доступном потоке.

Для такого рода функций я бы рекомендовал хранить информацию о пользователе в сеансе HTTP. Если у вас нет настраиваемых сервлетов или чего-то подобного, вместо этого вы можете иметь поле, содержащее объект пользователя, в вашем собственном настраиваемом классе UI. Vaadin заботится о том, чтобы UI.getCurrent() всегда возвращал правильное значение во всем коде, который выполняется через Vaadin.

Если вы вместо этого также интегрируете с другими функциями сервлета, вы можете вместо этого сохранить пользователя в HttpSession. Общий код сервлета может найти сеанс с помощью метода getSession(), например, в запросы и ответы сервлетов. В коде, выполняемом Vaadin, вы можете использовать VaadinSession().getCurrent().getSession() для получения экземпляра WrappedSession, основанного на тех же данных HttpSession.

Итак, в классе пользовательского интерфейса, если я сохранил что-то похожее на обычную переменную, то есть loggedInUser = setLoggedInUser (userController.getUser (username)); тогда я мог бы просто использовать VaadinSession (). getCurrent (). getLoggedInUser ()? Как бы выглядела реализация?

James Palfrey 31.05.2018 14:11

Если вы добавите поле экземпляра в свой класс UI, а также добавите получатель для поля, вы можете сделать что-то вроде User loggedInUser = ((MyUI) UI.getCurrent()).getLoggedInUser();

Leif Åstrand 31.05.2018 23:42

Я собираюсь отметить ваш ответ как правильный, это не тот, который я использовал, но он определенно поставил меня на правильный путь и действительно соответствует критериям.

James Palfrey 01.06.2018 07:44

Есть и другой подход. Вместо этого можно было бы создать службу пользователя @SessionScoped и либо @Inject, или @Autowire, в зависимости от того, используете ли вы CDI или Spring. При этом именно bean-менеджер будет заботиться о привязке правильной сущности к вашему представлению.

Другие вопросы по теме