Архитектура приложения Spring Boot 3
Вопрос в большей части по архитектуре приложения. Я пишу приложения облачного хранилища. Есть 2 сущности:
User
- таблица, которая хранит в себе логин, пароль (в зашифр.виде), действующий токенUserFile
- таблица, которая хранит в себе данные файла (байты, название, размер)
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String email;
private String password;
private String userToken;
@OneToMany
@JoinColumn(name = "userId")
private List<UserFile> file;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority("USER"));
}
@Override
public String getUsername() {
return email;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class UserFile {
@Id
private String fileName;
private long fileSize;
@Lob
@Column(length = 100_000_000)
private byte[] file;
private long userId;
}
После того, как пользователь авторизовался, он может, к примеру, загрузить файл. Загрузкой файла занимается класс UserFileService
, который обращается к UserFileRepository
:
@Repository
public interface UserFileRepository extends JpaRepository<UserFile, String> {
Как проходит процесс загрузки: метод загрузки принимает MultipartFile multipartFile
, далее, используя сервис userService
, достается текущий пользователь из SecurityContextHolder
, после чего на основе multipartFile
создается объект UserFile
.
var user = userService.findUserByEmail(
SecurityContextHolder.
getContext().
getAuthentication().
getName()
);
var userFile = UserFile.builder().
fileName(multipartFile.getOriginalFilename()).
fileSize(multipartFile.getSize()).
file(multipartFile.getBytes()).
userId(user.getId()).
build();
userFileRepository.saveAndFlush(userFile);
И вот мой вопрос: как обойти проблему постоянного обращения к SecurityContextHolder
? Я вынужден в начале любой операции (удаление/обновление/скачивание/получения списка файлов) обращаться к контексту и вынимать авторизованного пользователя, чтобы понимать с каким именно пользователем я работаю. Я бы мог добавить зависимость к UserFileService
(private User user
) и инкрементировать ее, чтобы постоянно не лезть в контекст, но тогда получится ерунда по двум пунктам:
Для работы с
User
есть отдельный репозиторий (UserRepository
), и вся работа сentity User
должна проходить через негоПолучится, что я добавил в сервисный слой зависимость от модели, что не есть хорошо
Знаю, что можно добавить объект Principal
в контроллере, чтобы Spring автоматически инкрементировал его, а уже из него получать объект авторизации, но подумал, может есть другое решение?
Спасибо)