Ответы пользователя по тегу Spring
  • Как правильно вставлять картинки в html представления и настраивать Thymeleaf?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день!
    Картинки проекта нужно добавлять в директорию resources/static Можно создать директорию images и соответственно, путь будет /resources/static/images
    А уже все последующие загружаемые файлы через фронт можно хранить либо на распределеных файловых системах, либо где-нибудь на хостинге.
    Ответ написан
  • Как работает Spring Security JWT?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    Вот, пример Spring Security JWT
    https://github.com/hantsy/spring-webmvc-jwt-sample
    Вот, тут схематическое изображение того, как JWT AUTH работает
    https://www.javainuse.com/spring/boot-jwt
    Надеюсь, что смог помочь вам
    Ответ написан
    Комментировать
  • Платформа для обучения сотрудиков, как лучше реализовать?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день!
    Никто не даст совета по поводу архитектуры сайта не зная полного технического задания.
    Для фронт-энда, если вы планируете использовать фреймворк попроще, то можете выбрать VueJS
    Готовые бесплатные шаблоны есть. Можете тут выбрат шаблоны не только для Vue, но и для других фреймворков - https://www.creative-tim.com/templates/vuejs-free
    Но разумеется, что если вам нужен более юзабельный шаблон, то стоит обратиться к дизайнеру, верстальщику, а затем уже перенести его в выбранный вами фреймворк.
    Бывают разные электронные платформы подготовки специалистов. Например, тот же udemy.com поддерживает стриминг видео и генерирует сертификаты. В общем, в первую очередь определитесь с функционалом, а затем уже точняйте детали архитектуры.
    Ответ написан
    2 комментария
  • Как сделать DTO с валидацией данных в Java Spring?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    Если честно, то меня сама строка настораживает
    @NotNull(message = "123")
        @NotEmpty(message = "456")
        private String proxy;

    NotEmpty и так проверяет строку на NULL и на пустоту и соответственно, аннотация @NotNull не нужна.
    Попробуйте удалить эту аннотацию и проверьте заново.
    Ответ написан
  • Почему Hibernate разрешает удалять сущность, на которую ссылается FK?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    Наверное, помимо ограничений на уровне БД можно использовать проверку средствами Java. Т.е. создать метод, который проверяет наличие курсов у юзера и выбрасывает соответствующее исключение. Соответственно, исключение будет выброшено до вызова метода delete() и будет выброшено то исключение, которе вам нужно.
    Я конечно не отвечу вам наверняка, но думаю этот ответ будет для вас полезен
    https://stackoverflow.com/questions/14875793/jpa-h...

    JPA does offer possibility to cascade operations (merge, persist, refresh, remove) to associated entities. Logic is in JPA and does not utilize database cascades.
    There is no JPA standard compliant way to do cascades with database cascades.

    Т.е. скорее всего вы каскады не указали при создании сущности ManyToMany. Проверьте ваш код

    Дополнено:
    There is no clean cut means to do this in JPA. The following will get you what you want... You can use CascadeType.DELETE, however this annotation only applies to the objects in the EntityManager, not the database. You want to be sure that ON DELETE CASCADE is added to the database constraint. To verify, you can configure JPA to generate a ddl file. Take a look at the ddl file, you'll notice that ON DELETE CASCADE is not part of the constraint. Add ON DELETE CASCADE to actual SQL in the ddl file, then update your database schema from the ddl. This will fix your problem .
    Ответ написан
  • Как к entity присоединить список других entity и потом работать с ними и со списком?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!
    Во-первых, на основании ваших слов:
    Есть сертификат(Certificate), у него может быть много тегов (Tag).
    Предполагается что в таблице тегов может быть куча дубликатов по имени, т.е. 3 сертификата могут иметь один и тот же тег "Java" ну или как-то так.

    Могу предположить, что связь OneToMany & ManyToOne не очень подходит.
    Вот, смотрите: один сертификат может иметь несколько тегов, но при этом один тег может относится к разным сертификатам. Тут явно связь ManyToMany.
    https://vladmihalcea.com/the-best-way-to-use-the-m...
    https://www.baeldung.com/jpa-many-to-many
    Соответственно, получится, что со стороны Certificate вы сможете получить список его тегов, а со тороны тега, можете получить список сертификатов, к которым он принадлежит.
    А то у вас получается, что и со стороны тега и сертификата OneToMany связь, но при этом с обеих сторон используется List
    При использовании ManyToMany будет создана новая таблица вида certificate_id | tag_id, где вы сможете хранить данные. И соответственно,
    Как к entity присоединить список других entity и потом работать с ними и со списком?

    Этот вопрос устранится само собой
    Ответ написан
    7 комментариев
  • Как создать разные классы под разные роли в Spring Security?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Я бы не создавал классы для каждой из роли, а реализовал бы следующим образом:
    1) Создать класс User. Пометить @MappedSuperclass. Вынести туда общие поля: username, password и др.
    2) Далее создать нужные классы и расширить класс User. Например, Customer, Author и др. И все поля специфичные для каждого из классов указать в них.
    3) Далее можно например, создать паттерн Builder, который при создание сущности по дефолту будет назначать соответствующие классу роли.

    P.S. Не забудьте также имплементировать интерфейс UserDetails нужный для Spring Security.
    Ответ написан
    2 комментария
  • Как работать с изображениями в веб-приложениях на Java?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!

    Как хранить изображение? Насколько я знаю, их можно запихивать прямо в PostgreSQL, но я склоняюсь в сторону того, что изображения надо сохранять в ресурсы, а в бд хранить только ссылки.

    Не самая лучшая идея хранить картинки в виде binary в БД. Лучше, как вы отметили в БД хранить ссылку на объект, а ресурс в файловой системе. Можно хранить файлы в распределенных файловых системах (AWS, Google), но вряд ли вы располагаете таким бюджетом.

    Вот, простая реализация хранения картинок в FS.

    Entity
    @Entity
    @Data
    @NoArgsConstructor
    @Table(name = "attachments")
    public class Attachment {
    
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE)
      private Long attachId;
    
      private String attachTitle;
    
      @Column(nullable = false, updatable = false)
      private LocalDate uploadDate;
    
      private String extension;
    
      private String downloadLink;
    
    }


    Repository
    @Repository
    public interface AttachmentRepository extends JpaRepository<Attachment, Long> {}


    Service
    public interface AttachmentService {
    
      /**
       * Загрузить новый файл
       *
       * @param file
       * @param user
       * @throws IOException
       */
      Attachment addAttachment(MultipartFile file, User user) throws IOException;
    
    
      /**
       * Найти Вложение по его ID
       *
       * @param attachId
       * @return
       */
      Attachment findAttachById(Long attachId);	
    
      /**
       * Скачать файл
       *
       * @param uploadYear
       * @param fileName
       * @return
       * @throws MalformedURLException
       */
      Resource loadFileAsResource(String uploadYear, String fileName) throws MalformedURLException;
    
    }


    ServiceImpl
    @Service
    @RequiredArgsConstructor
    public class AttachmentServiceImpl implements AttachmentService {
    
      private final AttachmentRepository attachmentRepository;
      private final AppProperties appProperties;
      private final FileTools fileTools;
    
      /**
       * Загрузить новый файл
       *
       * @param file
       * @param user
       * @throws IOException
       */
      @Override
      public Attachment addAttachment(MultipartFile file, User user) throws IOException {
        // Создаем директорию если ее не существует
        File uploadDir = new File(appProperties.getUploadPath());
        // Если директория uploads не существует, то создаем ее
        if (!uploadDir.exists()) {
          uploadDir.mkdirs();
        }
        String curDate = LocalDateTime.now().toString();
        // Создаем уникальное название для файла и загружаем файл
        String fileName =
            "attach_" + curDate + "_" + file.getOriginalFilename().toLowerCase().replaceAll(" ", "-");
        file.transferTo(new File(uploadDir + "/" + fileName));
        Attachment attachment = Attachment.builder()
            .attachTitle(fileName)
            .uploadDate(LocalDate.now())
            .extension(fileTools.getFileExtension(file.getOriginalFilename()))
            .downloadLink("/attachments/get/" + Year.now() + "/" + fileName)
            .build();
        attachmentRepository.save(attachment);
        return attachment;
      }
    
    
      /**
       * Найти Вложение по его ID
       *
       * @param attachId
       * @return
       */
      @Override
      public Attachment findAttachById(Long attachId) {
        return attachmentRepository
            .findById(attachId)
            .orElseThrow(() -> new AttachmentNotFoundException("Attachment not found!"));
      }
    
    
      /**
       * Скачать файл
       *
       * @param fileName
       * @return
       * @throws MalformedURLException
       */
      @Override
      public Resource loadFileAsResource( String fileName)
          throws MalformedURLException {
        Path fileStorageLocation =
            Paths.get(appProperties.getUploadPath()).toAbsolutePath().normalize();
        Path filePath = fileStorageLocation.resolve(fileName).normalize();
        return new UrlResource(filePath.toUri());
      }
    
    }


    Conroller
    @Controller
    @RequiredArgsConstructor
    @RequestMapping("/attachments")
    public class AttachmentController {
    
      private final AttachmentService attachmentService;
      private final UserService userService;
    
      /**
       * Загрузить новое вложение
       *
       * @param file
       * @return
       * @throws IOException
       */
      @PostMapping(value = "/add", produces = "application/json")
      @ResponseBody
      public ResponseEntity<Map<String, String>> uploadAttachment(
          @RequestPart(value = "file") MultipartFile file)
          throws IOException {
        Attachment attachment = attachmentService.addAttachment(file);
        Map<String, String> attachmentStatus = new HashMap<>();
        attachmentStatus.put("status", "ok");
        attachmentStatus.put("attachId", attachment.getAttachId().toString());
        return ResponseEntity.ok(attachmentStatus);
      }
    
      /**
       * Получить ссылку на скачивание загруженного файла
       *
       * @param filename
       * @param request
       * @return
       * @throws IOException
       */
      @GetMapping("/get/{filename:.+}")
      public ResponseEntity<Resource> serveFile(
           @PathVariable String filename, HttpServletRequest request)
          throws IOException {
        Resource resource = attachmentService.loadFileAsResource(filename);
        String contentType;
        contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
        if (contentType == null) {
          contentType = "application/octet-stream";
        }
        return ResponseEntity.ok()
            .contentType(MediaType.parseMediaType(contentType))
            .header(
                HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"" + resource.getFilename() + "\"")
            .body(resource);
      }
    }
    Ответ написан
    4 комментария
  • По какому принципу Spring DataJPA обновляет записи в связанных таблицах?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую, коллега!
    Позволь, внести небольшую лепту в ваш код и отметить следующее:
    CrudCourseRepository

    Наверное, указывать Crud в названии не нужно, так как в репозиторий в будущем могут быть добавлены другие методы и соответственно, с точки зрения clean code название не будет корректным.

    Как JpaRepository производит обновление связей в таблице student_courses?

    Как говорится, лучше один раз увидеть, чем сто раз услышать. Так что лучше включить в properties
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.format_sql=true


    Предположу, что вы увидите примерно следующее:
    Запрос на SELECT (выборку) из двух таблиц вместе с JOIN, а далее запрос на вставку новой записи (INSERT)

    Насколько я понимаю, если я попытаюсь обновить сущность Student, передав в CrudStudentRepository#save() студента с пустым списком курсов, то в таблице student_courses будут удалены все записи, в которых фигурирует обновляемый студент, но по моему опыту этого не происходит. Как мне тогда удалять/обновлять эти записи?

    Тут пожалуй, вам стоит обратить внимание на CascadeType.

    Например, если в связи OneToMany вы постараетесь сохранить список со стороны самой сущности, то элементы списка будут сохранены, но id у них будет null, так как сама сущность еще не сохранена и ей не присвоен идентификатор. Чтобы избежать этого можно как вариант, указать CascadeType.All или PERSIST & MERGE

    В случае с ManyToMany, думаю, что будет корректным указать тип каскада. Например, CascadeType.PERSIST CascadeType.MERGE

    К слову, есть хороший источник, откуда я также время от времени черпаю информацию. Вот ссылка - link
    Можешь глянуть.
    Ответ написан
    3 комментария
  • Каким образом лучше создать администратора в Spring Boot проекте?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую, коллега!
    Да, Spring посложнее, чем Django. Но раз тебе удобно писать именно на нем, то конечно же стоит писать backend на нем.
    И да, если уж делать проект по-хорошему, то тебе нужен Spring Security. Тебе нужно создать роль ADMIN.
    Так как проект простой, то можешь использовать In-Memory Auth.
    Так как ты пишешь REST, то скорее всего тебе нужно будет реализовать jwt auth.
    Чтобы по умолчанию при старте приложения создать пользователя, можешь имплементировать интерфейс CommandLineRunner и в методе run() создать юзеров и сохранить в БД.

    P.S. БД необязательно.
    Ответ написан
    Комментировать
  • Java Spring MVC не видит представления, почему (Inteliji Idea)?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую, коллега!
    Я посмотрел ваш репозиторий и могу предположить следующие причины того, почему вам не удается использовать thymeleaf.
    1) У вас 2 модуля и оба модуля являются war. Соответственно, можно предположить, что вы запускаете первый модуль (firstapp), вместо второго (MVCFirstApp). А шаблонизатор thymeleaf у вас подключен во втором модуле.
    Таким образом вам нужно запустить второй модуль через Tomcat. А также рекомендую прочитать про модули maven, чтобы понять как они устроены и как работают. Например, в родительском pom.xml нужно указать packaging - pom, для модулей, которые являются библиотекой - jar, ну и для основного модуля, который содержит файлы запуска приложения - указать war или jar в зависимости от того, что вам нужно.

    2) Вторая причина того, почему вы не можете открыть страницу может заключаться в контроллере. Возможно, что вы пытаетесь открыть шаблон через базовый URL (/), а метод, для которого назначен шаблон - /hello-world
    Сниппет вашего кода?:
    @Controller
    @RequestMapping("/")
    public class HelloController {
    
        @GetMapping("/hello-world")
        public String sayHello() {
            return "hello_world";
        }
    }


    Таким образом, исходя из текущего проекта, вам достаточно запустить второй модуль через томкат и открыть урл /hello-world, чтобы открыть нужный шаблон
    Ответ написан
  • Как настроить WebSecurityConfig правильно?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Приветствую!
    1)
    Хочу сделать чтоб вход на страницы админа /adminPageProduct /adminPageUser

    наверное, лучше сделать общий префикс для админ панели, что-то типа /admin/** и на этом уровне ограничивать доступ, чем перечислять каждую ссылку в настройках конфигурации. А урл делать следующей структуры:/admin/products /admin/users. Вам же в любом случае нужно закрыть доступ ко всей админке

    Мне кажется, что проблема у вас может быть тут:
    .antMatchers("/admin*")
    Других явных проблем не вижу, если все остальное настроено корректно
    Ответ написан
    Комментировать
  • Как вынести конфиг из Spring приложения(внешний настраевыемый)?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Ответ легко находится поисковиком.
    Вот, полезная статья - https://www.baeldung.com/spring-properties-file-ou...

    Пути по которым Спринг по умолчанию ищет файлы конфигурации:
    A /config subdirectory of the current directory
        The current directory
        A classpath /config package
        The classpath root


    Вот, похожий вопрос на SO
    https://stackoverflow.com/questions/26744060/exclu...
    Ответ написан
    Комментировать
  • Почему-то BindingResult не ловит ошибку, как исправить?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    В первую очередь небольшая рекомендация - вместо того, чтобы из view напрямую получить объект User и сохранить его, создайте UserDto класс и далее получив данные из вью замаппите его в User().
    По поводу возможных ошибок валидации загляните по этой ссылке - https://stackoverflow.com/questions/42423553/sprin...
    Ответ написан
    Комментировать
  • Spring + JPA как заставить работать запросы?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день!

    - Уточните какие именно библиотеки у вас подключены в pom.xml? В частности интересует библиотека spring data jpa
    - Уточните есть ли у вас в классе City геттеры, сеттеры и конструктор без аргументов? Если нет, то добавьте их.
    Если у вас подключен lombok, то можно прописать@Data @NoArgsConstructor
    - Далее подключитесь к вашей БД и просмотрите записи в БД. Возможно, что они не сохраняются в UTF-8, потому и не находится город по названию. Вместо данных в таблице увидите крякозябры. Если эта проблема наблюдается, то пропишите
    jdbc:mysql://localhost:3306/ticket_system?useUnicode=yes&characterEncoding=UTF-8

    - Также обратите внимание на то создается ли у вас таблица cities.
    Еще есть подозрение, что вы используете слово name, которое зарезервировано в mysql и из-за этого могут наблюдаться проблемы. Попробуйте экранировать его
    @Column(name = "`name`", length = 50,nullable = false)

    https://dev.mysql.com/doc/refman/8.0/en/keywords.html
    https://stackoverflow.com/questions/2224503/how-to...
    Ответ написан
  • Как получить данные со стороннего ресурса?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Здравствуйте!
    Так как вы работаете со Spring, то посмотрите в сторону RestTemplate
    https://www.baeldung.com/rest-template
    Ответ написан
    Комментировать
  • Почему не создается бин jpaRepository?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Здравствуйте!
    Удалось ли вам решить проблему?
    Если нет, то поделюсь некоторыми мыслями, а вы уже продебажьте ваш код.
    Первый раз деплою. через идею все нормально отрабатывает, но при попытке задеплоить на vps выдает ошибку

    Если у вас локально отрабатывает корректно, а на VPS нет, то проверьте конфигурацию сервера. В вашем проекте на гитхаб application.yaml пустой и соответственно, непонятно что именно у вас прописано в конфигах для production. Если у вас есть профили, то проверьте установлен ли hibernate.ddl-auto: validate и если установлен, то импортировали ли вы ddl & dml на сервер. Или у вас он на production должен создать ddl сам?
    Как минимум, это первый момент на что стоит обратить внимание.

    Далее стоит уточнить деплоите ли вы приложение на внешний томкат или используете embedded?
    Далее попробуйте добавить такой класс в ваш проект:

    public class ServletInitializer extends SpringBootServletInitializer {
    
      @Override
      protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(App.class);
      }
    }


    Далее обратите внимание на то, как именно вы собираете build и что в него добавляете. Например, war exploded или war или jar. Есть ли все необходимые классы в нем и т.д.

    Если сборка происходит через Gradle, то используйте bootWar. В общем, нужно проводить дебаг и смотреть что не так
    Ответ написан
  • Парсинг (скрапинг) получение информации с сайтов, авторизация, инструменты, примеры?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Здравствуйте!
    Начнем с простого, когда контент сайта загружается без фреймворков. Соответственно, нет никаких аяксов, не нужно никуда скроллить, чтобы получить следующую страницу или кликать на кнопки и т.д. для получения материалов. Т.е. вам достаточно отправить GET запрос на некий сайт и получить данные.
    В этом случае для парсинга будет достаточно библиотеки jsoup. Либо для своей кастомной реализации используйте DOM & SAX Parser.

    Теперь, чуть усложним задачу сайт точно также формируется без фреймворков, но для получения доступа к информации нужна авторизация. Если тут используется какая-то простая авторизация, то достаточно будет единожды получить кукисы и при каждом запросе указывать на сервер. Также не забывайте про referrer & User-agent.

    Теперь, еще усложним задачу - контент формируется динамически (посредством js-фреймворков или аякс запроса и т.д.). В этом случае jsoup не поможет, так как для загрузки контента вам нужно прокликать на кнопку (Загрузить еще) или проскроллить вниз, чтобы тригернуть загрузку контента и т.д. Т.е. вам нужна некая интерактивность. Для этого стоит посмотреть в сторону Selenium + (любой браузер). В качестве браузера можно использовать - firefox, chromium и др. Для быстродействия желательно использовать headless браузеры.

    Усложняем задачу дальше. Понадобилось авторизоваться и решить некую капчу. В часности рекапчу. Тут скажу заранее, что я сам когда-то давно искал возможные пути обхода и самое простое решение - использовать платный сервис.
    Ссылка на сайт - https://anti-captcha.com/
    После ввода имени пользователя и пароля селениум триггерит клик на капче, а дальше данные пересылаем на сервер и получаем решение капчи.

    Усложним задачу еще больше - различные honeypot. Тут как говорится кто на что горазд. Все зависит от конкретного сайта и конкретной реализации (софта) honeypot. Некоторые могут заблокировать по ip, если запрос был произведен на несуществующий урл. Например, на сайте всего 100 страниц, а вы запросили 101 страницу и попались в ловушку. Или например, вы заполнили невидимое input поле, которое в норме пользователь не видит и соответственно, не заполняет.

    Идем дальше - если вам нужна некая интерактивность (т.е. пользователь сайта должен иметь возможность самостоятельно парсить сайт), то вам нужна клиентская часть написанная на javascript. Подобные онлайн-сервисы имеются. Наберите в гугл web scraping online и увидите различные сервисы. Как правило, они предлагают установить некое расширение, при клике на котором он получает доступ к элементам DOM, а далее уже можно при помощи селекторов (id, xpath, class ) определить что нужно спарсить. Определить тип навигации / пагинации (например, пагинация при помощи нумерации страниц или пагинация при помощи кнопки Далее и др.). Тут могут свои подводные камни. Например, некоторые сайты при достижении максимальной страницы могут выдавать ошибку (404), некоторые не выдают ошибку и лишь показывают контент заново. Иногда нужно проверять страницу на наличие пустоты на странице (на отсутствие элементов по селектору). Иногда нужно проверять страницу на наличие ошибки 404 и т.д. В общем, это уже работа фронтэндера.

    Некоторые динамически формируемые страницы могут подгружать контент при помощи json или xml. Соответственно, для парсинга некоторых сайтов можно обойтись без использования selenium. А лишь запросить материалы по их внутреннему API, а затем при помощи gson или jackson спарсить их.

    Одним из универсальных инструментов парсинга, с которым мне приходилось сталкиваться была программа Visual Web Ripper. Стоит примерно 250-300 долларов. Программа подгружает контент сайта внутри себя через IE (может уже и обновили этот момент). А далее уже можно задавать условия парсинга и экспортировать данные.
    Ответ написан
    Комментировать
  • Что делать: ошибка в компиляции, связанная с Spring Data репозиторием (Не создаётся бин)?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    IllegalArgumentException: Validation failed for query for method findByBody(String body)

    Вот, краткий лог ошибки. Ошибка валидации метода.
    Могу предположить тут 2 проблемы:

    Вот, ваш код:
    public interface ExpressionRepository extends CrudRepository<ExpressionEntity, Long> {
    
        @Query("FROM ExpressionEntity WHERE ExpressionEntity.body = body")
        public Optional<ExpressionEntity> findByBody(String body);
    
    }


    Скорее всего должно быть так:
    SELECT e FROM ExpressionEntity e WHERE e.body = ?1
    Ответ написан
  • Как реализовать роли пользователей для Spring security?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Здравствуйте!
    добавлять роли для пользователей (non-user, user, admin) со своими паролями и логинами.

    У ролей не бывает логинов и паролей. Они есть у пользователей.
    Роль лишь определяет то, кем данный пользователь является. ADMIN, USER, etc.
    Также есть Privilege (привилегия). Т.е. что данному пользователю разрешено согласно выданному ему ролю. Например, право на комментирование, право на публикацию и т.д.
    Вот, тут наглядный туториал по ролям и привилегиям
    https://www.baeldung.com/role-and-privilege-for-sp...
    Вот, неплохой курс с торрента:
    https://rutracker.org/forum/viewtopic.php?t=5864776
    Рекомендую приобрести данный курс на оф. сайте baeldung.com
    Ответ написан
    Комментировать