В настоящее время я разрабатываю веб-приложение на 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());
}
}




Проблема в том, что нет гарантии, что MainSystem.Login() и EditProfileView.enter() будут работать в одном потоке. Каждое действие пользователя обрабатывается как отдельный HTTP-запрос, который контейнер сервлета будет запускать в любом доступном потоке.
Для такого рода функций я бы рекомендовал хранить информацию о пользователе в сеансе HTTP. Если у вас нет настраиваемых сервлетов или чего-то подобного, вместо этого вы можете иметь поле, содержащее объект пользователя, в вашем собственном настраиваемом классе UI. Vaadin заботится о том, чтобы UI.getCurrent() всегда возвращал правильное значение во всем коде, который выполняется через Vaadin.
Если вы вместо этого также интегрируете с другими функциями сервлета, вы можете вместо этого сохранить пользователя в HttpSession. Общий код сервлета может найти сеанс с помощью метода getSession(), например, в запросы и ответы сервлетов. В коде, выполняемом Vaadin, вы можете использовать VaadinSession().getCurrent().getSession() для получения экземпляра WrappedSession, основанного на тех же данных HttpSession.
Если вы добавите поле экземпляра в свой класс UI, а также добавите получатель для поля, вы можете сделать что-то вроде User loggedInUser = ((MyUI) UI.getCurrent()).getLoggedInUser();
Я собираюсь отметить ваш ответ как правильный, это не тот, который я использовал, но он определенно поставил меня на правильный путь и действительно соответствует критериям.
Есть и другой подход. Вместо этого можно было бы создать службу пользователя @SessionScoped и либо @Inject, или @Autowire, в зависимости от того, используете ли вы CDI или Spring. При этом именно bean-менеджер будет заботиться о привязке правильной сущности к вашему представлению.
Итак, в классе пользовательского интерфейса, если я сохранил что-то похожее на обычную переменную, то есть loggedInUser = setLoggedInUser (userController.getUser (username)); тогда я мог бы просто использовать VaadinSession (). getCurrent (). getLoggedInUser ()? Как бы выглядела реализация?