🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

स्प्रिंग बूट 3 गाइड 2026: रेस्ट एपीआई, जेपीए, सुरक्षा और वर्चुअल थ्रेड्स

⏱️4 min read  ·  850 words

स्प्रिंग बूट 2026 में एंटरप्राइज़ बैकएंड के लिए प्रमुख जावा फ्रेमवर्क है। स्प्रिंग बूट 3.3 के साथ, ग्रेलवीएम के माध्यम से मूल संकलन, प्रोजेक्ट लूम के माध्यम से वर्चुअल थ्रेड और स्प्रिंग एआई स्टार्टर, बिल्डिंग प्रोडक्शन जावा एपीआई कभी तेज नहीं रहा। यह मार्गदर्शिका आपको हैलो वर्ल्ड से प्रोडक्शन-ग्रेड REST API तक ले जाती है।

स्प्रिंग बूट क्यों?

  • ऑटो-विन्यास– समझदार डिफ़ॉल्ट, सामान्य पैटर्न के लिए शून्य बॉयलरप्लेट
  • एंबेडेड सर्वर– टॉमकैट/नेटी शामिल, कोई परिनियोजन WAR फ़ाइलें नहीं
  • उत्पादन के लिए तैयार– एक्चुएटर, माइक्रोमीटर मेट्रिक्स, स्वास्थ्य जांच अंतर्निहित
  • GraalVM मूलनिवासी– मूल बाइनरी में संकलित, <50 एमएस में शुरू होता है, 50% कम रैम का उपयोग करता है
  • विशाल पारिस्थितिकी तंत्र– स्प्रिंग डेटा, सुरक्षा, क्लाउड, बैच, एआई

प्रोजेक्ट सेटअप

# Spring Initializr (start.spring.io)
# Or via curl:
curl https://start.spring.io/starter.zip   -d dependencies=web,data-jpa,postgresql,security,actuator,validation,lombok   -d type=maven-project   -d language=java   -d javaVersion=21   -d name=techpulse-api   -d groupId=com.techpulse   -d artifactId=api   -o techpulse-api.zip

unzip techpulse-api.zip
cd techpulse-api
mvn spring-boot:run

application.yml कॉन्फ़िगरेशन

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/techpulse_db
    username: ${DB_USER}
    password: ${DB_PASSWORD}
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5

  jpa:
    hibernate:
      ddl-auto: validate  # use Flyway/Liquibase for production
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
        format_sql: true

  flyway:
    enabled: true
    locations: classpath:db/migration

server:
  port: 8080
  compression:
    enabled: true

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,info,prometheus
  endpoint:
    health:
      show-details: always

इकाई और भंडार

// User.java
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    @Size(min = 2, max = 50)
    private String name;

    @Column(unique = true, nullable = false)
    @Email
    private String email;

    @Column(nullable = false)
    @JsonIgnore
    private String passwordHash;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private Role role = Role.USER;

    @Column(nullable = false)
    private boolean active = true;

    @CreationTimestamp
    private LocalDateTime createdAt;

    @UpdateTimestamp
    private LocalDateTime updatedAt;

    public enum Role { USER, ADMIN, MODERATOR }
}

// UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
    Page<User> findByActiveTrue(Pageable pageable);
    List<User> findByRole(User.Role role);
    boolean existsByEmail(String email);

    @Query("SELECT u FROM User u WHERE u.name ILIKE %:name%")
    List<User> searchByName(@Param("name") String name);
}

सेवा परत

// UserService.java
@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class UserService {
    private final UserRepository userRepo;
    private final PasswordEncoder passwordEncoder;

    @Transactional(readOnly = true)
    public Page<UserDTO> listUsers(Pageable pageable) {
        return userRepo.findByActiveTrue(pageable)
            .map(UserDTO::from);
    }

    @Transactional(readOnly = true)
    public UserDTO getUser(Long id) {
        return userRepo.findById(id)
            .map(UserDTO::from)
            .orElseThrow(() -> new ResourceNotFoundException("User not found: " + id));
    }

    public UserDTO createUser(CreateUserRequest request) {
        if (userRepo.existsByEmail(request.email())) {
            throw new ConflictException("Email already exists: " + request.email());
        }
        User user = User.builder()
            .name(request.name())
            .email(request.email())
            .passwordHash(passwordEncoder.encode(request.password()))
            .build();
        User saved = userRepo.save(user);
        log.info("Created user: {} ({})", saved.getEmail(), saved.getId());
        return UserDTO.from(saved);
    }

    public UserDTO updateUser(Long id, UpdateUserRequest request) {
        User user = userRepo.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("User not found"));
        if (request.name() != null) user.setName(request.name());
        return UserDTO.from(userRepo.save(user));
    }

    public void deleteUser(Long id) {
        User user = userRepo.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("User not found"));
        user.setActive(false);  // soft delete
        userRepo.save(user);
    }
}

बाकी नियंत्रक

// UserController.java
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
@Validated
@Slf4j
public class UserController {
    private final UserService userService;

    @GetMapping
    public ResponseEntity<Page<UserDTO>> listUsers(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size,
        @RequestParam(defaultValue = "createdAt") String sortBy,
        @RequestParam(defaultValue = "DESC") Sort.Direction direction
    ) {
        Pageable pageable = PageRequest.of(page, size, Sort.by(direction, sortBy));
        return ResponseEntity.ok(userService.listUsers(pageable));
    }

    @GetMapping("/{id}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long id) {
        return ResponseEntity.ok(userService.getUser(id));
    }

    @PostMapping
    public ResponseEntity<UserDTO> createUser(
        @Valid @RequestBody CreateUserRequest request
    ) {
        UserDTO created = userService.createUser(request);
        URI location = URI.create("/api/v1/users/" + created.id());
        return ResponseEntity.created(location).body(created);
    }

    @PatchMapping("/{id}")
    public ResponseEntity<UserDTO> updateUser(
        @PathVariable Long id,
        @Valid @RequestBody UpdateUserRequest request
    ) {
        return ResponseEntity.ok(userService.updateUser(id, request));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.noContent().build();
    }
}

// DTOs (Java records)
public record UserDTO(Long id, String name, String email, User.Role role, LocalDateTime createdAt) {
    public static UserDTO from(User user) {
        return new UserDTO(user.getId(), user.getName(), user.getEmail(),
                           user.getRole(), user.getCreatedAt());
    }
}

public record CreateUserRequest(
    @NotBlank @Size(min=2, max=50) String name,
    @NotBlank @Email String email,
    @NotBlank @Size(min=8) String password
) {}

वैश्विक अपवाद हैंडलर

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ProblemDetail handleNotFound(ResourceNotFoundException ex) {
        ProblemDetail problem = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
        problem.setTitle("Resource Not Found");
        return problem;
    }

    @ExceptionHandler(ConflictException.class)
    public ProblemDetail handleConflict(ConflictException ex) {
        return ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ProblemDetail handleValidation(MethodArgumentNotValidException ex) {
        Map<String, String> errors = ex.getBindingResult().getFieldErrors().stream()
            .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
        ProblemDetail problem = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "Validation failed");
        problem.setProperty("errors", errors);
        return problem;
    }
}

JWT के साथ स्प्रिंग सुरक्षा

// JwtService.java
@Service
public class JwtService {
    @Value("${app.jwt.secret}")
    private String secret;
    private static final long EXPIRY = 86400000L; // 24h

    public String generateToken(UserDetails user) {
        return Jwts.builder()
            .subject(user.getUsername())
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + EXPIRY))
            .signWith(Keys.hmacShaKeyFor(secret.getBytes()))
            .compact();
    }

    public String extractUsername(String token) {
        return Jwts.parser()
            .verifyWith(Keys.hmacShaKeyFor(secret.getBytes()))
            .build()
            .parseSignedClaims(token)
            .getPayload()
            .getSubject();
    }
}

वर्चुअल थ्रेड्स (जावा 21 + स्प्रिंग बूट 3.3)

# application.yml — enable virtual threads
spring:
  threads:
    virtual:
      enabled: true  # uses Project Loom virtual threads for Tomcat

वर्चुअल थ्रेड के साथ, प्रत्येक HTTP अनुरोध को प्लेटफ़ॉर्म थ्रेड के बजाय एक हल्का वर्चुअल थ्रेड मिलता है। यह बिना किसी कोड परिवर्तन के I/O-बाउंड एप्लिकेशन (डेटाबेस क्वेरी, बाहरी एपीआई कॉल) के लिए थ्रूपुट में नाटकीय रूप से सुधार करता है।

GraalVM मूल छवि

# Add to pom.xml
# <plugin>spring-boot-maven-plugin with native goal</plugin>

# Build native image (requires GraalVM 22+)
mvn -Pnative native:compile

# Run (starts in ~50ms, uses ~60MB RAM vs 300MB JVM)
./target/techpulse-api

2026 में स्प्रिंग बूट 3.3 उत्पादन के लिए तैयार, तेज़ और डेवलपर-अनुकूल है। वर्चुअल थ्रेड अधिकांश उपयोग के मामलों के लिए प्रतिक्रियाशील प्रोग्रामिंग की आवश्यकता को समाप्त कर देते हैं। GraalVM मूल छवियां जावा को कंटेनरीकृत माइक्रोसर्विसेज के लिए एक गंभीर दावेदार बनाती हैं जहां स्टार्टअप समय और मेमोरी मायने रखती है।

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা