Spring Boot 示例
Spring Boot框架示例,包括REST API、依赖注入、JPA、安全和现代Spring Boot功能
💻 Spring Boot Hello World java
🟢 simple
⭐
Spring Boot应用程序设置和Hello World REST API与依赖注入
⏱️ 20 min
🏷️ spring boot, java, rest, web
Prerequisites:
Java basics, Maven/Gradle, REST API concepts
// Spring Boot Hello World Examples
// 1. Maven Dependencies (pom.xml)
/*
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello-spring-boot</name>
<description>Hello World Spring Boot Application</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
*/
// 2. Main Application Class
package com.example.hellospringboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class HelloWorldApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(HelloWorldApplication.class, args);
// Display application information
String[] beanNames = context.getBeanDefinitionNames();
System.out.println("Application started with " + beanNames.length + " beans");
// You can access beans here if needed
// HelloWorldController controller = context.getBean(HelloWorldController.class);
}
}
// 3. Basic REST Controller
package com.example.hellospringboot.controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class HelloWorldController {
// Basic Hello World endpoint
@GetMapping("/hello")
public String helloWorld() {
return "Hello, World!";
}
// Hello with path variable
@GetMapping("/hello/{name}")
public ResponseEntity<Map<String, String>> helloName(@PathVariable String name) {
Map<String, String> response = new HashMap<>();
response.put("message", "Hello, " + name + "!");
response.put("status", "success");
return ResponseEntity.ok(response);
}
// Hello with query parameters
@GetMapping("/greet")
public ResponseEntity<Map<String, Object>> greet(
@RequestParam(defaultValue = "World") String name,
@RequestParam(defaultValue = "en") String lang) {
Map<String, Object> response = new HashMap<>();
String greeting;
switch (lang.toLowerCase()) {
case "es":
greeting = "Hola";
break;
case "fr":
greeting = "Bonjour";
break;
case "de":
greeting = "Hallo";
break;
default:
greeting = "Hello";
}
response.put("greeting", greeting + ", " + name + "!");
response.put("language", lang);
response.put("timestamp", System.currentTimeMillis());
return ResponseEntity.ok(response);
}
// POST endpoint example
@PostMapping("/hello")
public ResponseEntity<Map<String, Object>> postHello(@RequestBody Map<String, String> request) {
Map<String, Object> response = new HashMap<>();
String name = request.getOrDefault("name", "World");
response.put("message", "Hello, " + name + "!");
response.put("received", request);
response.put("timestamp", System.currentTimeMillis());
return new ResponseEntity<>(response, HttpStatus.CREATED);
}
// PUT endpoint example
@PutMapping("/hello/{id}")
public ResponseEntity<Map<String, Object>> updateHello(
@PathVariable String id,
@RequestBody Map<String, String> request) {
Map<String, Object> response = new HashMap<>();
response.put("id", id);
response.put("updated", true);
response.put("data", request);
response.put("message", "Hello updated successfully!");
return ResponseEntity.ok(response);
}
// DELETE endpoint example
@DeleteMapping("/hello/{id}")
public ResponseEntity<Map<String, String>> deleteHello(@PathVariable String id) {
Map<String, String> response = new HashMap<>();
response.put("id", id);
response.put("message", "Hello deleted successfully!");
response.put("status", "deleted");
return ResponseEntity.ok(response);
}
}
// 4. Service Layer Example
package com.example.hellospringboot.service;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
@Service
public class HelloService {
private final AtomicLong counter = new AtomicLong();
private final List<String> greetings = new ArrayList<>();
public HelloService() {
// Initialize with some default greetings
greetings.add("Hello, World!");
greetings.add("Bonjour le monde!");
greetings.add("¡Hola mundo!");
}
public String getSimpleHello() {
return "Hello from service! Counter: " + counter.incrementAndGet();
}
public String getPersonalizedHello(String name) {
return "Hello, " + name + "! Service called at " + LocalDateTime.now();
}
public List<String> getAllGreetings() {
return new ArrayList<>(greetings);
}
public String addGreeting(String greeting) {
greetings.add(greeting);
return "Greeting added: " + greeting;
}
public String getGreetingStats() {
return String.format("Total greetings: %d, Service calls: %d",
greetings.size(), counter.get());
}
}
// 5. Controller with Service Injection
package com.example.hellospringboot.controller;
import com.example.hellospringboot.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/service")
public class HelloServiceController {
private final HelloService helloService;
// Constructor injection (recommended)
@Autowired
public HelloServiceController(HelloService helloService) {
this.helloService = helloService;
}
@GetMapping("/hello")
public String getServiceHello() {
return helloService.getSimpleHello();
}
@GetMapping("/hello/{name}")
public String getPersonalizedServiceHello(@PathVariable String name) {
return helloService.getPersonalizedHello(name);
}
@GetMapping("/greetings")
public List<String> getAllGreetings() {
return helloService.getAllGreetings();
}
@PostMapping("/greetings")
public Map<String, String> addGreeting(@RequestBody Map<String, String> request) {
String greeting = request.get("greeting");
String result = helloService.addGreeting(greeting);
return Map.of(
"message", result,
"status", "success"
);
}
@GetMapping("/stats")
public Map<String, String> getStats() {
return Map.of(
"statistics", helloService.getGreetingStats(),
"status", "success"
);
}
}
// 6. Application Configuration
package com.example.hellospringboot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class AppConfig {
// CORS configuration
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
// 7. Custom Exception Handler
package com.example.hellospringboot.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<Object> handleIllegalArgumentException(
IllegalArgumentException ex, WebRequest request) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("status", HttpStatus.BAD_REQUEST.value());
body.put("error", "Bad Request");
body.put("message", ex.getMessage());
body.put("path", request.getDescription(false));
return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
body.put("error", "Internal Server Error");
body.put("message", ex.getMessage());
body.put("path", request.getDescription(false));
return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// 8. Health Check Controller
package com.example.hellospringboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/health")
public class HealthController {
@GetMapping
public Map<String, Object> health() {
Map<String, Object> health = new HashMap<>();
health.put("status", "UP");
health.put("timestamp", LocalDateTime.now());
health.put("application", "Hello Spring Boot");
health.put("version", "1.0.0");
return health;
}
@GetMapping("/detailed")
public Map<String, Object> detailedHealth() {
Map<String, Object> health = new HashMap<>();
health.put("status", "UP");
health.put("timestamp", LocalDateTime.now());
health.put("application", "Hello Spring Boot");
health.put("version", "1.0.0");
// Database check (simulated)
health.put("database", Map.of(
"status", "UP",
"details", "Connection successful"
));
// Memory check
Runtime runtime = Runtime.getRuntime();
health.put("memory", Map.of(
"total", runtime.totalMemory(),
"free", runtime.freeMemory(),
"used", runtime.totalMemory() - runtime.freeMemory(),
"max", runtime.maxMemory()
));
return health;
}
}
// 9. Model/DTO Classes
package com.example.hellospringboot.model;
public class HelloRequest {
private String name;
private String language;
private String message;
// Constructors
public HelloRequest() {}
public HelloRequest(String name, String language, String message) {
this.name = name;
this.language = language;
this.message = message;
}
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.example.hellospringboot.model;
import java.time.LocalDateTime;
public class HelloResponse {
private String message;
private String status;
private LocalDateTime timestamp;
private Object data;
// Constructors
public HelloResponse() {
this.timestamp = LocalDateTime.now();
}
public HelloResponse(String message, String status) {
this();
this.message = message;
this.status = status;
}
// Getters and Setters
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public LocalDateTime getTimestamp() {
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
// 10. Application Properties (src/main/resources/application.yml)
/*
spring:
application:
name: hello-spring-boot
server:
port: 8080
servlet:
context-path: /
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: when-authorized
logging:
level:
com.example.hellospringboot: DEBUG
org.springframework.web: INFO
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
info:
app:
name: Hello Spring Boot Application
version: 1.0.0
description: A simple Spring Boot Hello World application
*/
💻 Spring Boot with JPA和Hibernate java
🟡 intermediate
⭐⭐⭐⭐
带有JPA/Hibernate的Spring Boot应用程序,用于数据库操作、实体、存储库和数据访问
⏱️ 45 min
🏷️ spring boot, jpa, hibernate, database, orm
Prerequisites:
Spring Boot basics, SQL concepts, Entity relationships
// Spring Boot JPA and Hibernate Examples
// 1. Maven Dependencies (pom.xml additions)
/*
<dependencies>
<!-- Existing dependencies -->
<!-- JPA and Database -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 Database (for development) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MySQL Database (for production) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
*/
// 2. User Entity
package com.example.hellospringboot.entity;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Name is required")
@Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
@Column(nullable = false)
private String name;
@NotBlank(message = "Email is required")
@Email(message = "Email should be valid")
@Column(nullable = false, unique = true)
private String email;
@Column(name = "phone_number")
private String phoneNumber;
private Integer age;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private UserRole role = UserRole.USER;
@Column(name = "is_active")
private Boolean active = true;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
// One-to-Many relationship
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Post> posts = new HashSet<>();
// Constructors
public User() {
this.createdAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
}
public User(String name, String email) {
this();
this.name = name;
this.email = email;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public UserRole getRole() {
return role;
}
public void setRole(UserRole role) {
this.role = role;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
public LocalDateTime getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(LocalDateTime updatedAt) {
this.updatedAt = updatedAt;
}
public Set<Post> getPosts() {
return posts;
}
public void setPosts(Set<Post> posts) {
this.posts = posts;
}
@PreUpdate
protected void onUpdate() {
this.updatedAt = LocalDateTime.now();
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + ''' +
", email='" + email + ''' +
", role=" + role +
", active=" + active +
'}';
}
}
// 3. User Role Enum
package com.example.hellospringboot.entity;
public enum UserRole {
USER,
ADMIN,
MODERATOR
}
// 4. Post Entity
package com.example.hellospringboot.entity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
@Entity
@Table(name = "posts")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Title is required")
@Size(max = 200, message = "Title must not exceed 200 characters")
@Column(nullable = false)
private String title;
@NotBlank(message = "Content is required")
@Column(columnDefinition = "TEXT")
private String content;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private PostStatus status = PostStatus.DRAFT;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
// Constructors
public Post() {
this.createdAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
}
public Post(String title, String content, User user) {
this();
this.title = title;
this.content = content;
this.user = user;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public PostStatus getStatus() {
return status;
}
public void setStatus(PostStatus status) {
this.status = status;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
public LocalDateTime getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(LocalDateTime updatedAt) {
this.updatedAt = updatedAt;
}
@PreUpdate
protected void onUpdate() {
this.updatedAt = LocalDateTime.now();
}
}
// 5. Post Status Enum
package com.example.hellospringboot.entity;
public enum PostStatus {
DRAFT,
PUBLISHED,
ARCHIVED
}
// 6. User Repository
package com.example.hellospringboot.repository;
import com.example.hellospringboot.entity.User;
import com.example.hellospringboot.entity.UserRole;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// Find by email
Optional<User> findByEmail(String email);
// Find by name (case insensitive)
List<User> findByNameIgnoreCase(String name);
// Find by role and active status
List<User> findByRoleAndActive(UserRole role, Boolean active);
// Find by age range
List<User> findByAgeBetween(Integer minAge, Integer maxAge);
// Custom query with pagination
@Query("SELECT u FROM User u WHERE " +
"(:name IS NULL OR LOWER(u.name) LIKE LOWER(CONCAT('%', :name, '%'))) AND " +
"(:email IS NULL OR LOWER(u.email) LIKE LOWER(CONCAT('%', :email, '%'))) AND " +
"(:role IS NULL OR u.role = :role)")
Page<User> findUsersWithFilters(@Param("name") String name,
@Param("email") String email,
@Param("role") UserRole role,
Pageable pageable);
// Count users by role
long countByRole(UserRole role);
// Check if email exists
boolean existsByEmail(String email);
// Native SQL query
@Query(value = "SELECT * FROM users WHERE created_at >= :startDate", nativeQuery = true)
List<User> findUsersCreatedAfter(@Param("startDate") String startDate);
// Find users with most posts
@Query("SELECT u FROM User u LEFT JOIN u.posts p GROUP BY u ORDER BY COUNT(p) DESC")
List<User> findUsersWithMostPosts(Pageable pageable);
}
// 7. Post Repository
package com.example.hellospringboot.repository;
import com.example.hellospringboot.entity.Post;
import com.example.hellospringboot.entity.PostStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.List;
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
// Find by user
List<Post> findByUserId(Long userId);
// Find by status
List<Post> findByStatus(PostStatus status);
// Find by user and status
List<Post> findByUserIdAndStatus(Long userId, PostStatus status);
// Search posts by title or content
@Query("SELECT p FROM Post p WHERE " +
"LOWER(p.title) LIKE LOWER(CONCAT('%', :keyword, '%')) OR " +
"LOWER(p.content) LIKE LOWER(CONCAT('%', :keyword, '%'))")
Page<Post> searchPosts(@Param("keyword") String keyword, Pageable pageable);
// Find posts created within date range
@Query("SELECT p FROM Post p WHERE p.createdAt BETWEEN :startDate AND :endDate")
List<Post> findPostsByDateRange(@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate);
// Count posts by user
long countByUserId(Long userId);
// Find recently published posts
@Query("SELECT p FROM Post p WHERE p.status = :status ORDER BY p.createdAt DESC")
List<Post> findRecentPosts(@Param("status") PostStatus status, Pageable pageable);
}
// 8. User Service
package com.example.hellospringboot.service;
import com.example.hellospringboot.entity.User;
import com.example.hellospringboot.entity.UserRole;
import com.example.hellospringboot.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
@Transactional
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User createUser(User user) {
if (userRepository.existsByEmail(user.getEmail())) {
throw new IllegalArgumentException("Email already exists: " + user.getEmail());
}
return userRepository.save(user);
}
public User updateUser(Long id, User userDetails) {
User user = getUserById(id);
user.setName(userDetails.getName());
user.setEmail(userDetails.getEmail());
user.setPhoneNumber(userDetails.getPhoneNumber());
user.setAge(userDetails.getAge());
user.setRole(userDetails.getRole());
user.setActive(userDetails.getActive());
return userRepository.save(user);
}
public void deleteUser(Long id) {
User user = getUserById(id);
userRepository.delete(user);
}
@Transactional(readOnly = true)
public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("User not found with id: " + id));
}
@Transactional(readOnly = true)
public Optional<User> getUserByEmail(String email) {
return userRepository.findByEmail(email);
}
@Transactional(readOnly = true)
public Page<User> getAllUsers(Pageable pageable) {
return userRepository.findAll(pageable);
}
@Transactional(readOnly = true)
public Page<User> searchUsers(String name, String email, UserRole role, Pageable pageable) {
return userRepository.findUsersWithFilters(name, email, role, pageable);
}
@Transactional(readOnly = true)
public List<User> getUsersByRole(UserRole role) {
return userRepository.findByRoleAndActive(role, true);
}
@Transactional(readOnly = true)
public List<User> getUsersByAgeRange(Integer minAge, Integer maxAge) {
return userRepository.findByAgeBetween(minAge, maxAge);
}
@Transactional(readOnly = true)
public long getUserCount() {
return userRepository.count();
}
@Transactional(readOnly = true)
public long getUserCountByRole(UserRole role) {
return userRepository.countByRole(role);
}
}
// 9. User Controller
package com.example.hellospringboot.controller;
import com.example.hellospringboot.entity.User;
import com.example.hellospringboot.entity.UserRole;
import com.example.hellospringboot.service.UserService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User createdUser = userService.createUser(user);
return new ResponseEntity<>(createdUser, HttpStatus.CREATED);
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
@GetMapping
public ResponseEntity<Page<User>> getAllUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id") String sortBy,
@RequestParam(defaultValue = "asc") String sortDir) {
Sort sort = sortDir.equalsIgnoreCase("desc") ?
Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
Pageable pageable = PageRequest.of(page, size, sort);
Page<User> users = userService.getAllUsers(pageable);
return ResponseEntity.ok(users);
}
@GetMapping("/search")
public ResponseEntity<Page<User>> searchUsers(
@RequestParam(required = false) String name,
@RequestParam(required = false) String email,
@RequestParam(required = false) UserRole role,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size);
Page<User> users = userService.searchUsers(name, email, role, pageable);
return ResponseEntity.ok(users);
}
@GetMapping("/email/{email}")
public ResponseEntity<User> getUserByEmail(@PathVariable String email) {
Optional<User> user = userService.getUserByEmail(email);
return user.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@GetMapping("/role/{role}")
public ResponseEntity<List<User>> getUsersByRole(@PathVariable UserRole role) {
List<User> users = userService.getUsersByRole(role);
return ResponseEntity.ok(users);
}
@GetMapping("/age-range")
public ResponseEntity<List<User>> getUsersByAgeRange(
@RequestParam Integer minAge,
@RequestParam Integer maxAge) {
List<User> users = userService.getUsersByAgeRange(minAge, maxAge);
return ResponseEntity.ok(users);
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @Valid @RequestBody User userDetails) {
User updatedUser = userService.updateUser(id, userDetails);
return ResponseEntity.ok(updatedUser);
}
@DeleteMapping("/{id}")
public ResponseEntity<Map<String, String>> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.ok(Map.of(
"message", "User deleted successfully",
"status", "success"
));
}
@GetMapping("/stats")
public ResponseEntity<Map<String, Object>> getUserStats() {
Map<String, Object> stats = Map.of(
"totalUsers", userService.getUserCount(),
"adminCount", userService.getUserCountByRole(UserRole.ADMIN),
"userCount", userService.getUserCountByRole(UserRole.USER),
"moderatorCount", userService.getUserCountByRole(UserRole.MODERATOR)
);
return ResponseEntity.ok(stats);
}
}
// 10. Database Configuration (application.yml)
/*
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password: password
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.H2Dialect
defer-datasource-initialization: true
h2:
console:
enabled: true
path: /h2-console
sql:
init:
mode: always
data-locations: classpath:data.sql
*/
// 11. Sample Data (src/main/resources/data.sql)
/*
INSERT INTO users (name, email, phone_number, age, role, is_active, created_at, updated_at) VALUES
('John Doe', '[email protected]', '123-456-7890', 30, 'USER', true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Jane Smith', '[email protected]', '098-765-4321', 25, 'ADMIN', true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Bob Johnson', '[email protected]', '555-123-4567', 35, 'USER', true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Alice Brown', '[email protected]', '555-987-6543', 28, 'MODERATOR', true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Charlie Wilson', '[email protected]', '555-246-8135', 42, 'USER', false, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
INSERT INTO posts (title, content, status, user_id, created_at, updated_at) VALUES
('First Post', 'This is my first blog post content.', 'PUBLISHED', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Draft Article', 'This is still a draft and needs more work.', 'DRAFT', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Spring Boot Tutorial', 'Learn how to create Spring Boot applications.', 'PUBLISHED', 2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Java Programming', 'Advanced Java programming concepts and best practices.', 'PUBLISHED', 3, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('Web Development', 'Modern web development with JavaScript frameworks.', 'ARCHIVED', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
*/
💻 Spring Boot Security和JWT java
🔴 complex
⭐⭐⭐⭐⭐
带有Spring Security、JWT身份验证、授权和安全API端点的Spring Boot应用程序
⏱️ 60 min
🏷️ spring boot, security, jwt, authentication, authorization
Prerequisites:
Spring Boot basics, Security concepts, JWT tokens
// Spring Boot Security and JWT Examples
// 1. Maven Dependencies (pom.xml additions)
/*
<dependencies>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT Support -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- Existing dependencies -->
</dependencies>
*/
// 2. JWT Utility Class
package com.example.hellospringboot.security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;
@Component
public class JwtTokenProvider {
@Value("${app.jwt.secret:mySecretKey}")
private String jwtSecret;
@Value("${app.jwt.expiration:86400}")
private int jwtExpirationInMs;
private SecretKey getSigningKey() {
return Keys.hmacShaKeyFor(jwtSecret.getBytes());
}
public String generateToken(Authentication authentication) {
UserDetails userPrincipal = (UserDetails) authentication.getPrincipal();
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtExpirationInMs * 1000);
return Jwts.builder()
.setSubject(userPrincipal.getUsername())
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(getSigningKey(), SignatureAlgorithm.HS512)
.compact();
}
public String getUsernameFromToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public Date getExpirationDateFromToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
return claims.getExpiration();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException ex) {
// Log error
return false;
}
}
public String refreshToken(String token) {
final Date createdDate = new Date();
final Date expirationDate = calculateExpirationDate(createdDate);
final Claims claims = getAllClaimsFromToken(token);
claims.setIssuedAt(createdDate);
claims.setExpiration(expirationDate);
return Jwts.builder()
.setClaims(claims)
.signWith(getSigningKey(), SignatureAlgorithm.HS512)
.compact();
}
private Date calculateExpirationDate(Date createdDate) {
return new Date(createdDate.getTime() + jwtExpirationInMs * 1000);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
}
}
// 3. JWT Authentication Filter
package com.example.hellospringboot.security;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenProvider tokenProvider;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
String username = tokenProvider.getUsernameFromToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
// 4. Custom User Details Service
package com.example.hellospringboot.security;
import com.example.hellospringboot.entity.User;
import com.example.hellospringboot.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String usernameOrEmail) throws UsernameNotFoundException {
User user = userRepository.findByEmail(usernameOrEmail)
.orElseThrow(() -> new UsernameNotFoundException("User not found with email: " + usernameOrEmail));
if (!user.getActive()) {
throw new UsernameNotFoundException("User account is disabled");
}
return UserPrincipal.create(user);
}
}
// 5. User Principal Class
package com.example.hellospringboot.security;
import com.example.hellospringboot.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class UserPrincipal implements UserDetails {
private Long id;
private String email;
private String password;
private Collection<? extends GrantedAuthority> authorities;
public UserPrincipal(Long id, String email, String password, Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.email = email;
this.password = password;
this.authorities = authorities;
}
public static UserPrincipal create(User user) {
List<GrantedAuthority> authorities = Collections.singletonList(
new SimpleGrantedAuthority("ROLE_" + user.getRole().name())
);
return new UserPrincipal(
user.getId(),
user.getEmail(),
user.getPassword(),
authorities
);
}
public Long getId() {
return id;
}
@Override
public String getUsername() {
return email;
}
@Override
public String getPassword() {
return password;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
// 6. Security Configuration
package com.example.hellospringboot.config;
import com.example.hellospringboot.security.JwtAuthenticationFilter;
import com.example.hellospringboot.security.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(customUserDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeHttpRequests(authz -> authz
// Public endpoints
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/h2-console/**").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/products/**").permitAll()
// Admin endpoints
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/users/**").hasAnyRole("ADMIN", "MODERATOR")
// Protected endpoints
.requestMatchers("/api/profile/**").authenticated()
.requestMatchers("/api/posts/**").authenticated()
// Everything else requires authentication
.anyRequest().authenticated()
)
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
// Allow H2 console frames
http.headers().frameOptions().disable();
return http.build();
}
}
// 7. Authentication DTOs
package com.example.hellospringboot.dto;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class LoginRequest {
@NotBlank
@Email
private String email;
@NotBlank
@Size(min = 6, max = 40)
private String password;
// Getters and Setters
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.example.hellospringboot.dto;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class SignUpRequest {
@NotBlank
@Size(min = 2, max = 50)
private String name;
@NotBlank
@Size(max = 60)
@Email
private String email;
@NotBlank
@Size(min = 6, max = 40)
private String password;
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.example.hellospringboot.dto;
public class JwtAuthenticationResponse {
private String accessToken;
private String tokenType = "Bearer";
private Long expiresIn;
public JwtAuthenticationResponse(String accessToken, Long expiresIn) {
this.accessToken = accessToken;
this.expiresIn = expiresIn;
}
// Getters and Setters
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public Long getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Long expiresIn) {
this.expiresIn = expiresIn;
}
}
// 8. Authentication Service
package com.example.hellospringboot.service;
import com.example.hellospringboot.dto.JwtAuthenticationResponse;
import com.example.hellospringboot.dto.LoginRequest;
import com.example.hellospringboot.dto.SignUpRequest;
import com.example.hellospringboot.entity.User;
import com.example.hellospringboot.entity.UserRole;
import com.example.hellospringboot.repository.UserRepository;
import com.example.hellospringboot.security.JwtTokenProvider;
import com.example.hellospringboot.security.UserPrincipal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AuthService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private JwtTokenProvider tokenProvider;
@Transactional
public JwtAuthenticationResponse authenticateUser(LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getEmail(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
return new JwtAuthenticationResponse(jwt, 86400L); // 24 hours
}
@Transactional
public User registerUser(SignUpRequest signUpRequest) {
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
throw new RuntimeException("Email is already taken!");
}
User user = new User();
user.setName(signUpRequest.getName());
user.setEmail(signUpRequest.getEmail());
user.setPassword(passwordEncoder.encode(signUpRequest.getPassword()));
user.setRole(UserRole.USER);
user.setActive(true);
return userRepository.save(user);
}
@Transactional(readOnly = true)
public User getCurrentUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof UserPrincipal) {
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
return userRepository.findById(userPrincipal.getId())
.orElseThrow(() -> new RuntimeException("User not found"));
}
throw new RuntimeException("User not authenticated");
}
}
// 9. Authentication Controller
package com.example.hellospringboot.controller;
import com.example.hellospringboot.dto.JwtAuthenticationResponse;
import com.example.hellospringboot.dto.LoginRequest;
import com.example.hellospringboot.dto.SignUpRequest;
import com.example.hellospringboot.entity.User;
import com.example.hellospringboot.service.AuthService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private AuthService authService;
@PostMapping("/login")
public ResponseEntity<JwtAuthenticationResponse> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
JwtAuthenticationResponse response = authService.authenticateUser(loginRequest);
return ResponseEntity.ok(response);
}
@PostMapping("/register")
public ResponseEntity<User> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
User user = authService.registerUser(signUpRequest);
return new ResponseEntity<>(user, HttpStatus.CREATED);
}
@GetMapping("/me")
public ResponseEntity<User> getCurrentUser() {
User user = authService.getCurrentUser();
return ResponseEntity.ok(user);
}
}
// 10. Protected Resource Example
package com.example.hellospringboot.controller;
import com.example.hellospringboot.entity.User;
import com.example.hellospringboot.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/profile")
public class ProfileController {
@Autowired
private AuthService authService;
@GetMapping
public ResponseEntity<User> getProfile() {
User user = authService.getCurrentUser();
return ResponseEntity.ok(user);
}
@GetMapping("/info")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<Map<String, Object>> getProfileInfo() {
User user = authService.getCurrentUser();
Map<String, Object> info = new HashMap<>();
info.put("user", user);
info.put("message", "This is your protected profile information");
info.put("accessLevel", "Authenticated User");
return ResponseEntity.ok(info);
}
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<Map<String, String>> getAdminInfo() {
return ResponseEntity.ok(Map.of(
"message", "This is admin-only information",
"accessLevel", "Administrator"
));
}
@GetMapping("/moderator")
@PreAuthorize("hasAnyRole('ADMIN', 'MODERATOR')")
public ResponseEntity<Map<String, String>> getModeratorInfo() {
return ResponseEntity.ok(Map.of(
"message", "This is moderator+ level information",
"accessLevel", "Moderator or Administrator"
));
}
}
// 11. Application Properties (application.yml)
/*
app:
jwt:
secret: mySecretKey123456789012345678901234567890
expiration: 86400 # 24 hours in seconds
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password: password
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.H2Dialect
default_schema: PUBLIC
h2:
console:
enabled: true
path: /h2-console
settings:
web-allow-others: true
# Logging
logging:
level:
com.example.hellospringboot: DEBUG
org.springframework.security: DEBUG
org.springframework.web: INFO
io.jsonwebtoken: DEBUG
*/