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

Ответ

Проект: RESTful API для управления задачами (To-Do List) на Spring Boot.

Цель: Создать backend-сервис с полным циклом аутентификации, авторизации и CRUD-операций.

Стек технологий:

  • Backend: Java 17, Spring Boot 3
  • Безопасность: Spring Security, JWT (JSON Web Token)
  • База данных: PostgreSQL, Spring Data JPA (Hibernate)
  • Документация: OpenAPI 3 (Springdoc)
  • Тестирование: JUnit 5, Mockito, Testcontainers

Ключевые компоненты и реализация:

  1. JWT Аутентификация и Авторизация:

    • Реализован фильтр для проверки JWT-токена в каждом запросе.
      @Component
      public class JwtAuthenticationFilter extends OncePerRequestFilter {
      @Override
      protected void doFilterInternal(HttpServletRequest request,
                                      HttpServletResponse response,
                                      FilterChain chain) throws IOException, ServletException {
          String authHeader = request.getHeader("Authorization");
          if (authHeader != null && authHeader.startsWith("Bearer ")) {
              String jwt = authHeader.substring(7);
              String username = jwtUtil.extractUsername(jwt); // Утилита для работы с JWT
              if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                  if (jwtUtil.validateToken(jwt, username)) {
                      // Создание объекта Authentication и установка в SecurityContext
                      UsernamePasswordAuthenticationToken authToken =
                          new UsernamePasswordAuthenticationToken(username, null, authorities);
                      SecurityContextHolder.getContext().setAuthentication(authToken);
                  }
              }
          }
          chain.doFilter(request, response);
      }
      }
  2. Слой данных (Repository):

    • Использовал Spring Data JPA для декларативного доступа к данным.
      @Repository
      public interface TaskRepository extends JpaRepository<Task, Long> {
      List<Task> findByUserIdAndCompleted(Long userId, boolean completed);
      @Query("SELECT t FROM Task t WHERE t.dueDate < :date AND t.completed = false")
      List<Task> findOverdueTasks(@Param("date") LocalDate date);
      }
  3. Обработка больших данных (отдельный модуль):

    • Парсер CSV-файлов с использованием Java Stream API и многопоточности (ForkJoinPool) для импорта задач.
      public List<Task> parseCsvFile(Path filePath) throws IOException {
      return Files.lines(filePath)
                  .skip(1) // Пропуск заголовка
                  .parallel() // Параллельная обработка строк
                  .map(line -> line.split(","))
                  .filter(parts -> parts.length == 3)
                  .map(parts -> new Task(parts[0], parts[1], LocalDate.parse(parts[2])))
                  .collect(Collectors.toList());
      }

Что было реализовано:

  • Регистрация и вход пользователя с выдачей JWT.
  • CRUD для задач с привязкой к пользователю.
  • Фильтрация и пагинация задач.
  • Интеграционные и unit-тесты.
  • Docker-контейнеризация приложения и БД.

Итог: Проект продемонстрировал навыки работы с ключевыми Spring-технологиями, проектированием API, безопасностью и эффективной обработкой данных.

Ответ 18+ 🔞

Слушай, смотри, я тут наспрингбутил один проект — типа умный список дел, REST API. Ну, чтобы таски создавать, удалять, всё такое. В общем, обычная история, но я её, блядь, так закрутил, что сам от себя офигеваю.

Чё за хрень получилась: Ну, бэкенд, ясен пень, на Java 17 и Spring Boot 3. База — PostgreSQL, потому что нахуй эти игрушечные H2 для прода. Безопасность — Spring Security с JWT, чтобы эти, блядь, токены по заголовкам летали. Документацию на OpenAPI накрутил, чтобы не тыкаться вслепую. И тесты, мать их, JUnit с Testcontainers, чтобы всё как у больших.

А теперь про самое сокровенное, как я это всё ебал:

  1. JWT — ебать его в сраку, этот токен. Сделал фильтр, который каждый запрос ловит и смотрит: а есть ли там в заголовках этот самый Bearer? Если есть — выковыривает оттуда токен и начинает его проверять. Если всё чисто — пускает дальше, а если нет — нахуй. Код вот, смотри, не трогай его:

    @Component
    public class JwtAuthenticationFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response,
                                        FilterChain chain) throws IOException, ServletException {
            String authHeader = request.getHeader("Authorization");
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                String jwt = authHeader.substring(7);
                String username = jwtUtil.extractUsername(jwt); // Утилита для работы с JWT
                if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                    if (jwtUtil.validateToken(jwt, username)) {
                        // Создание объекта Authentication и установка в SecurityContext
                        UsernamePasswordAuthenticationToken authToken =
                            new UsernamePasswordAuthenticationToken(username, null, authorities);
                        SecurityContextHolder.getContext().setAuthentication(authToken);
                    }
                }
            }
            chain.doFilter(request, response);
        }
    }

    Всё, больше в этот код не лезь, он работает, ёпта.

  2. База данных — тут вообще магия. Взял Spring Data JPA и просто объявил интерфейс. А он, сука, сам все методы из названия понимает! Хочешь найти все задачи пользователя по айди и статусу? Пожалуйста, пиши findByUserIdAndCompleted. Хочешь просроченные задачи? На, держи кастомный запрос с @Query. Вообще охуенно.

    @Repository
    public interface TaskRepository extends JpaRepository<Task, Long> {
        List<Task> findByUserIdAndCompleted(Long userId, boolean completed);
        @Query("SELECT t FROM Task t WHERE t.dueDate < :date AND t.completed = false")
        List<Task> findOverdueTasks(@Param("date") LocalDate date);
    }

    Красота, блядь, а не код. Ни одной лишней строчки.

  3. А вот это вообще пиздец — обработка CSV-файлов. Представь, тебе заливают файл на овердохуища задач. Надо всё распарсить и в базу запихнуть. Я сделал это с помощью Java Stream API и параллельной обработки. Читаем файл построчно, первую строку (заголовок) — нахуй, а дальше в параллель всё обрабатываем. Скорость — просто улёт.

    public List<Task> parseCsvFile(Path filePath) throws IOException {
        return Files.lines(filePath)
                    .skip(1) // Пропуск заголовка
                    .parallel() // Параллельная обработка строк
                    .map(line -> line.split(","))
                    .filter(parts -> parts.length == 3)
                    .map(parts -> new Task(parts[0], parts[1], LocalDate.parse(parts[2])))
                    .collect(Collectors.toList());
    }

    Вот так вот, чих-пых, и миллион записей обработан.

В итоге что получилось: Человек регистрируется, логинится, получает свой JWT-токен. Потом с этим токеном может делать с задачами что хочет: создавать, читать, обновлять, удалять — всё только свои, чужие не увидит. Можно фильтровать, по страницам листать. Всё затестировано, ёбта, и даже в Docker завернуто, чтобы одним махом поднималось.

Вывод: Проект, конечно, учебный, но я в нём все ключевые плюшки Spring'а попробовал — от безопасности до работы с данными. Получилось, вроде, неплохо, даже самому не стыдно.