Spring Boot
Spring Boot tạo Bean Instance bằng cách nào ?
🔹 1. Dựa trên Cơ chế Dependency Injection (DI)
Spring Boot dùng IoC Container để quản lý và tạo Bean.
🔹 2. Cách Spring Boot tạo Bean Instance:
✅ a. Annotation-Based (phổ biến nhất):
Spring Boot tự scan các class có annotation như:
@Component
@Service
@Repository
@Controller
→ Sau đó tự động khởi tạo Bean từ các class đó và đưa vào context.
@Component
public class MyService {
// Bean sẽ được Spring quản lý
}
✅ b. Manual via @Bean
trong @Configuration
class:
Khi cần custom cách khởi tạo Bean (vd: khởi tạo bằng constructor phức tạp):
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService("custom config");
}
}
✅ c. Constructor Injection / Field Injection / Setter Injection:
Khi khởi tạo, Spring tự resolve dependency và inject vào constructor:
@Service
public class OrderService {
private final ProductService productService;
public OrderService(ProductService productService) {
this.productService = productService;
}
}
🔹 3. Lifecycle khi tạo Bean:
Scan class & detect annotation
Instantiate (bằng constructor)
Dependency Injection
Gọi các lifecycle method (vd:
@PostConstruct
,InitializingBean
, ...)Đưa vào ApplicationContext
🔹 4. Cơ chế mặc định trong Spring Boot
Spring Boot auto-configures thông qua:
@SpringBootApplication
→ kết hợp@ComponentScan
,@EnableAutoConfiguration
Các
starter
giúp tự động tạo và cấu hình Bean mà không cần cấu hình tay.
✅ Tóm lại:
Spring Boot tạo Bean instance chủ yếu qua annotation + IoC container, tự động inject dependencies và quản lý lifecycle đầy đủ. Điều này giúp giảm cấu hình, tăng khả năng mở rộng và maintain.
Có những cách nào để Inject Dependency ? Cách nào được khuyến khích nhất ?
✅ Có những cách nào để Inject Dependency trong Spring?
Có 3 cách chính:
🔹 1. Constructor Injection ✅ [Khuyến khích nhất]
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Ưu điểm:
Immutable dependency
Dễ viết Unit Test (dễ mock)
Dễ phát hiện thiếu dependency (Compile-time error)
Chuẩn Clean Code + được Spring khuyến khích
🔹 2. Setter Injection
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository repo) {
this.userRepository = repo;
}
}
Ưu điểm:
Linh hoạt, có thể thay đổi sau khi khởi tạo.
Nhược điểm:
Có thể gây ra trạng thái không nhất quán nếu setter không được gọi.
🔹 3. Field Injection ❌ [Không khuyến khích trong production]
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
Nhược điểm:
Khó test (không inject mock được)
Không rõ ràng dependency
Không hỗ trợ cho final field
Vi phạm nguyên tắc SOLID (DIP)
✅ Tổng kết:
Constructor
✅ Rất khuyến khích
Tốt cho test & maintainability
Setter
⚠️ Dùng khi cần thiết
Khi dependency là optional
Field
❌ Tránh dùng
Khó test, khó maintain
Nếu trong project dùng Lombok, có thể dùng:
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
}
→ Vừa gọn, vừa chuẩn constructor injection.
Em hiểu @RestController và @Controller khác nhau thế nào ?
Dạ, em xin trả lời ngắn gọn, đúng trọng tâm như khi đi phỏng vấn:
✅ Sự khác nhau giữa @RestController
và @Controller
trong Spring Boot:
@RestController
và @Controller
trong Spring Boot:Thuộc tính
@Controller
@RestController
Dùng cho
Web MVC (Trả về HTML, JSP, Thymeleaf)
REST API (Trả về JSON/XML)
Trả về mặc định
View name (template page)
Object → JSON
Cần @ResponseBody
✅ Cần dùng nếu muốn trả về JSON
❌ Không cần – đã bao gồm sẵn
Kết hợp thực tế
@Controller + @ResponseBody
= REST API
@RestController
= gộp sẵn
🔹 Ví dụ:
1. @Controller
:
@Controller
public class PageController {
@GetMapping("/home")
public String home() {
return "home"; // trả về file home.html
}
}
2. @RestController
:
@RestController
public class ApiController {
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll(); // tự động trả về JSON
}
}
✅ Tóm lại:
@RestController
được dùng cho RESTful API → trả JSON/XML.@Controller
dùng cho ứng dụng có giao diện web, cần trả về HTML template.
Nếu dùng API thì nên chọn @RestController
để viết ngắn gọn, rõ ràng hơn ạ.
Em đã sử dụng AOP làm gì trong dự án ? Có ví dụ cụ thể không ?
Dạ, em xin trả lời câu này ngắn gọn và cụ thể như sau:
✅ Em đã sử dụng AOP (Aspect-Oriented Programming) để làm gì trong dự án?
Trong dự án thực tế, em sử dụng AOP chủ yếu cho các tác vụ cross-cutting concerns – tức là những logic dùng chung, lặp lại ở nhiều nơi, ví dụ:
🔹 1. Ghi log toàn bộ request/response
Log method name, parameters, response, execution time, v.v.
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.myapp.service..*(..))")
public Object logExecution(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // Gọi phương thức gốc
long duration = System.currentTimeMillis() - start;
System.out.println("Method: " + joinPoint.getSignature() +
" executed in " + duration + "ms");
return result;
}
}
🔹 2. Kiểm tra phân quyền (authorization) trước khi xử lý logic
Tạo custom annotation
@RequireRole("ADMIN")
, rồi dùng AOP để chặn và kiểm tra quyền người dùng.
🔹 3. Validate hoặc xử lý exception toàn cục
🔸 Lợi ích khi dùng AOP:
Giúp code sạch, tách biệt rõ business logic và kỹ thuật.
Dễ maintain, dễ mở rộng.
Làm sao xử lý exception trong Spring MVC ?
Dạ, em xin trình bày ngắn gọn, đúng trọng tâm phỏng vấn:
✅ Cách xử lý Exception trong Spring MVC
Spring cung cấp nhiều cách để handle exception một cách tập trung, rõ ràng:
🔹 1. Dùng @ControllerAdvice
+ @ExceptionHandler
(Khuyến khích)
@ControllerAdvice
+ @ExceptionHandler
(Khuyến khích)Tạo 1 class riêng để xử lý toàn bộ exception cho ứng dụng.
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGeneric(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Lỗi hệ thống");
}
}
🔹 2. Xử lý tại từng controller (ít dùng)
@GetMapping("/user/{id}")
public ResponseEntity<?> getUser(@PathVariable Long id) {
try {
return ResponseEntity.ok(userService.findById(id));
} catch (ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
}
🔹 3. Custom ErrorController
(trường hợp nâng cao)
ErrorController
(trường hợp nâng cao)Dùng khi muốn override toàn bộ xử lý lỗi mặc định của Spring Boot.
✅ Tóm lại:
Em ưu tiên dùng
@ControllerAdvice
để tách riêng logic xử lý lỗi, giúp mã sạch, dễ maintain và nhất quán.
Khi một request đi vào hệ thống Spring Boot, nó sẽ đi qua những bước nào ?
Dạ, đây là câu em rất hay gặp khi phỏng vấn Spring Boot, nên em xin trình bày theo flow rõ ràng, ngắn gọn:
✅ Flow xử lý một HTTP Request trong hệ thống Spring Boot
🧭 1. Client gửi request → đi vào Servlet Container (Tomcat, Jetty...)
🧭 2. Servlet Container gọi DispatcherServlet
(trung tâm điều phối)
DispatcherServlet
(trung tâm điều phối)Là bean do Spring Boot tự cấu hình, đứng giữa controller và client.
🧭 3. DispatcherServlet xử lý lần lượt qua các bước sau:
1️⃣
HandlerMapping
Tìm ra method tương ứng với URL (vd: /api/users
)
2️⃣
HandlerAdapter
Chuẩn hóa handler (Controller method) để có thể gọi được
3️⃣
Interceptor (nếu có)
Thực hiện các logic như logging, auth check trước khi controller chạy
4️⃣
Controller method
Xử lý chính → gọi Service, Repository…
5️⃣
@ResponseBody / ViewResolver
Trả JSON hoặc render HTML (tùy theo kiểu controller)
6️⃣
ExceptionResolver
Nếu có lỗi, Spring gọi xử lý tại @ControllerAdvice
🧭 4. Response trả về client
📌 Tóm tắt ngắn:
Request → DispatcherServlet → HandlerMapping → Controller → Service → Response → Client
Em có thể giải thích ngắn gọn sự khác nhau giữa Spring và Spring Boot không ?
Dạ, em xin trình bày ngắn gọn, đúng tinh thần phỏng vấn:
✅ Spring vs Spring Boot – Sự khác nhau chính
Tiêu chí
Spring Framework
Spring Boot
Cấu hình
Phải cấu hình thủ công (XML, Java Config)
Auto Configuration – cấu hình sẵn
Web Server
Không tích hợp sẵn
Tích hợp sẵn (Tomcat, Jetty…) – chỉ cần chạy là chạy
Phụ thuộc (Dependencies)
Tự khai báo và quản lý
Dùng Starter – đơn giản, gọn gàng
Mục tiêu chính
Nền tảng phát triển ứng dụng Java EE
Giúp phát triển microservices nhanh hơn
File cấu hình
Không bắt buộc application.properties
Dùng application.properties
hoặc application.yml
🔍 Tóm gọn:
Spring Boot = Spring + Auto Configuration + Embedded Server + Opinionated Defaults ➡️ Giúp phát triển ứng dụng nhanh, ít cấu hình, dễ triển khai.
Spring Boot kết nối với DB khi nào ? Quá trình đó diễn ra như thế nào ?
Dạ, em xin trình bày theo hướng phỏng vấn – ngắn gọn, kỹ thuật rõ ràng:
✅ Spring Boot kết nối với Database khi nào?
Spring Boot kết nối với database trong quá trình khởi động ứng dụng, cụ thể là khi ApplicationContext được khởi tạo và Bean liên quan đến DataSource được cấu hình.
🔁 Quy trình kết nối DB trong Spring Boot
1️⃣ Đọc cấu hình từ application.properties
hoặc application.yml
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=1234
2️⃣ Tự động cấu hình (AutoConfiguration
)
Spring Boot dùng
DataSourceAutoConfiguration
để tạoDataSource
bean.Dựa vào dependency (VD: HikariCP, H2, MySQL driver…), Spring chọn
DataSource
phù hợp.
3️⃣ Tạo các Bean:
DataSource
EntityManagerFactory
(nếu dùng JPA)TransactionManager
4️⃣ Kết nối được thiết lập khi các bean trên được khởi tạo
Nếu dùng JPA, Spring sẽ kiểm tra schema, mapping entity, thực hiện
ddl-auto
, v.v.
🧪 Khi nào xảy ra lỗi DB?
Nếu thông tin kết nối sai, driver thiếu, DB không khởi động, lỗi xảy ra ngay khi ứng dụng khởi động, trước khi controller nào chạy.
📌 Ghi nhớ:
Spring Boot tự động kết nối DB trong giai đoạn Bean Initialization, thông qua auto-configuration dựa trên properties đã khai báo.
Spring Security dùng cách nào để chặn user truy cập tài nguyên không hợp lệ ?
Dạ, em xin trình bày ngắn gọn, rõ ràng theo kiểu đi phỏng vấn:
✅ Spring Security chặn user truy cập tài nguyên không hợp lệ bằng cách nào?
🔒 1. Filter Chain – lớp đầu tiên kiểm soát request
Spring Security tạo một chuỗi filter (Security Filter Chain) xử lý mọi request trước khi đến controller.
Quan trọng nhất là
UsernamePasswordAuthenticationFilter
vàAuthorizationFilter
.
🔐 2. Authentication (Xác thực)
Kiểm tra xem user đã đăng nhập chưa.
Nếu chưa → Spring Security trả về 401 Unauthorized.
🔐 3. Authorization (Phân quyền)
Kiểm tra xem user có đủ quyền truy cập tài nguyên hay không (dựa vào role, authority).
Ví dụ:
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> getAdminData() { ... }
Nếu không có quyền → Spring trả về 403 Forbidden.
🧠 Cách cấu hình phân quyền phổ biến:
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
🎯 Tóm lại:
Spring Security dùng Filter + Authentication + Authorization để ngăn user trái phép truy cập tài nguyên, và phản hồi lại với 401 hoặc 403 tùy trường hợp.
Bean lifecycle trong Spring diễn ra như thế nào ?
Dạ, em xin trình bày rõ ràng – đúng chất phỏng vấn kỹ thuật:
✅ Bean Lifecycle trong Spring diễn ra như thế nào?
Spring quản lý vòng đời của bean theo các bước sau:
🔁 1. Instantiation – Khởi tạo đối tượng
Spring tạo instance của bean thông qua constructor hoặc reflection.
🔁 2. Populate Properties – Gán giá trị cho các thuộc tính
Gán các dependency vào bean thông qua setter, constructor hoặc field injection.
🔁 3. Set Bean Name, Bean Factory (tùy chọn)
Nếu bean implement:
BeanNameAware
→ Spring gọisetBeanName(...)
BeanFactoryAware
→ Spring gọisetBeanFactory(...)
🔁 4. Pre-Initialization (Before Init)
Gọi các bean
BeanPostProcessor
(postProcessBeforeInitialization
)
🔁 5. Initialize Bean
Nếu bean có:
@PostConstruct
→ gọi method đóHoặc implement
InitializingBean
→ gọiafterPropertiesSet()
Hoặc khai báo
init-method
trong XML
🔁 6. Post-Initialization
Gọi tiếp
postProcessAfterInitialization
trongBeanPostProcessor
🔁 7. Ready to use – Bean sẵn sàng hoạt động
🔁 8. Destroy – Khi context shutdown
Nếu bean:
Có
@PreDestroy
→ được gọiHoặc implement
DisposableBean
→ gọidestroy()
Hoặc có
destroy-method
trong cấu hình XML
📝 Tóm tắt bằng sơ đồ đơn giản:
create -> inject -> aware -> pre-init -> init -> post-init -> use -> destroy
@Transactional hoạt động thế nào ? Rollback khi nào ?
Dạ, em xin trình bày ngắn gọn – đúng tinh thần phỏng vấn thực chiến:
✅ @Transactional
hoạt động như thế nào?
@Transactional
hoạt động như thế nào?Khi một method được đánh dấu bằng
@Transactional
, Spring sẽ:Tạo proxy (AOP) cho class đó.
Bắt đầu transaction trước khi method thực thi.
Commit hoặc rollback sau khi method kết thúc.
➡️ Tất cả quá trình này được quản lý bởi Transaction Manager (ví dụ: JpaTransactionManager
nếu dùng JPA).
🔄 Quy trình:
Bắt đầu transaction trước khi method chạy
Nếu method chạy thành công →
commit
Nếu method ném ra exception →
rollback
theo quy tắc bên dưới
❗ Khi nào rollback
?
rollback
?RuntimeException
✅ Có rollback
Bao gồm NullPointerException
, IllegalArgumentException
...
CheckedException
❌ Không rollback
VD: IOException
, SQLException
→ phải chỉ rõ bằng rollbackFor
➡️ Nếu muốn rollback checked exception:
@Transactional(rollbackFor = IOException.class)
public void updateFile() throws IOException {
// ...
}
📌 Ví dụ thực tế trong dự án:
@Transactional
public void registerUser(User user) {
userRepository.save(user); // step 1
sendWelcomeEmail(user); // step 2 (nếu lỗi ở đây, step 1 rollback)
}
✅ Tổng kết:
@Transactional
giúp đảm bảo toàn vẹn dữ liệu (ACID).Rollback xảy ra khi:
Có
RuntimeException
Hoặc
CheckedException
được cấu hình thêm
Cấu hình application.properties khác gì với application.yml ?
Dạ, em xin trả lời ngắn gọn – rõ ràng như khi đi phỏng vấn thực chiến:
✅ Khác nhau giữa application.properties
và application.yml
:
application.properties
và application.yml
:Tiêu chí
application.properties
application.yml
(YAML)
Cấu trúc
Dạng key-value phẳng
Cấu trúc phân cấp, rõ ràng hơn
Đọc dễ
Đơn giản, quen thuộc
Dễ đọc với cấu hình lồng nhau
Hỗ trợ cấu trúc phức tạp
Khó biểu diễn danh sách, nested config
Biểu diễn list, object rất tốt
Cú pháp lỗi dễ phát hiện
Dễ debug hơn
Nhạy cảm với thụt dòng (indentation)
💡 Kết luận:
Nếu config đơn giản →
properties
tiện hơn.Nếu config phức tạp, nhiều cấp → nên dùng
YAML
để dễ đọc, dễ bảo trì hơn.
Trong thực tế, em thường dùng application.yml
vì nó trực quan hơn khi quản lý nhiều cấu hình.
Khi nào cần dùng @Component ?
Dạ, em xin trả lời ngắn gọn – rõ ràng theo phong cách phỏng vấn:
✅ Khi nào cần dùng @Component
trong Spring?
@Component
trong Spring?@Component
được dùng khi mình muốn đánh dấu một class là một Spring Bean để Spring quản lý vòng đời và dependency injection của nó.
📌 Dùng @Component
khi:
@Component
khi:Class không thuộc các vai trò đặc biệt như Controller, Service, Repository
Ví dụ: các helper, util, mapper, validator, task runner…
@Component public class EmailValidator { public boolean isValid(String email) { return email.contains("@"); } }
Muốn để Spring tự động phát hiện (Component Scan)
Khi ứng dụng chạy, Spring sẽ scan các class có
@Component
và tạo bean.
Cần inject vào nơi khác
VD:
@Autowired EmailValidator
ở service/controller.
💡 Ghi nhớ:
Nếu class có vai trò rõ ràng hơn → dùng annotation chuyên biệt hơn:
@Service
,@Repository
,@Controller
→ đều là dạng mở rộng của@Component
.
Kết luận:
Dùng
@Component
khi muốn Spring quản lý 1 class không thuộc 3 tầng chính (Controller, Service, Repository), nhưng vẫn cần tạo bean để inject hoặc cấu hình.
Làm sao xử lí lỗi toàn cục trong Spring Boot ?
Dạ, em xin trình bày ngắn gọn và đúng trọng tâm phỏng vấn:
✅ Cách xử lý lỗi toàn cục trong Spring Boot
Spring Boot hỗ trợ Global Exception Handling thông qua:
🔧 1. Dùng @ControllerAdvice
+ @ExceptionHandler
@ControllerAdvice
+ @ExceptionHandler
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse("Not Found", ex.getMessage()));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleGeneric(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse("Server Error", ex.getMessage()));
}
}
✅ Ưu điểm:
Tách riêng logic xử lý lỗi.
Áp dụng toàn bộ ứng dụng (ControllerAdvice áp dụng cho tất cả controller).
⚙️ 2. Tuỳ chỉnh ErrorController
(nâng cao)
ErrorController
(nâng cao)Khi muốn can thiệp sâu hơn hoặc customize response cho 404
, 500
,...
📌 Thực tế em thường dùng @ControllerAdvice
để:
@ControllerAdvice
để:Trả response JSON chuẩn cho FE.
Log lỗi.
Phân biệt lỗi domain/business và lỗi hệ thống.
Spring Boot auto-configuration hoạt động như thế nào ?
Dạ, em xin trình bày ngắn gọn, mạch lạc đúng tinh thần phỏng vấn Java Backend:
✅ Spring Boot Auto-Configuration hoạt động như thế nào?
Auto-configuration là cơ chế giúp Spring Boot tự động cấu hình các bean dựa trên:
Các dependency có trong classpath
Các cấu hình trong
application.properties
/application.yml
Và một số điều kiện cụ thể khác
⚙️ Cơ chế hoạt động chi tiết:
Annotation
@SpringBootApplication
Nó bao gồm
@EnableAutoConfiguration
, kích hoạt auto-config.
Spring Boot scan file
spring.factories
File này nằm trong:
META-INF/spring.factories
Liệt kê danh sách các class cấu hình sẵn (được đánh dấu
@Configuration
)Ví dụ:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Điều kiện cấu hình (
@ConditionalOnXxx
)Mỗi auto-configuration class chỉ được kích hoạt nếu thỏa mãn điều kiện.
Ví dụ:
@ConditionalOnClass(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.url") public class DataSourceAutoConfiguration { // cấu hình datasource nếu có JDBC và cấu hình URL }
📌 Ví dụ thực tế:
Khi ta thêm
spring-boot-starter-data-jpa
, Spring Boot sẽ:Phát hiện JPA trong classpath
Tự cấu hình
EntityManagerFactory
,TransactionManager
,DataSource
v.v.
✅ Tóm lại:
Auto-configuration là một cơ chế "hợp lý theo mặc định" (convention over configuration) giúp giảm bớt cấu hình thủ công – chỉ cần khai báo dependency, Spring Boot sẽ lo phần còn lại.
Cách bạn validate dữ liệu đầu vào trong Controller ?
Dạ, em xin trình bày ngắn gọn như khi đi phỏng vấn thực tế:
✅ Cách em validate dữ liệu đầu vào trong Controller (Spring Boot):
Em thường dùng Bean Validation (JSR 380) với các annotation như @NotNull
, @Size
, @Email
, v.v… kết hợp với @Valid
trong controller.
📌 1. Sử dụng annotation trong DTO:
public class UserRequest {
@NotBlank
private String username;
@Email
@NotBlank
private String email;
@Min(18)
private int age;
// getters/setters
}
📌 2. Dùng @Valid
hoặc @Validated
trong controller:
@Valid
hoặc @Validated
trong controller:@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public ResponseEntity<?> createUser(@RequestBody @Valid UserRequest request) {
// nếu dữ liệu hợp lệ → xử lý
return ResponseEntity.ok("User created");
}
}
📌 3. Xử lý lỗi validate (toàn cục):
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationError(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(err -> {
errors.put(err.getField(), err.getDefaultMessage());
});
return ResponseEntity.badRequest().body(errors);
}
}
✅ Tóm lại:
Dùng
@Valid
để kích hoạt validationĐặt constraint ngay trong DTO
Dùng
@ControllerAdvice
để xử lý lỗi gọn gàng, tái sử dụng
Cách quản lý cấu hình đa môi trường (dev, staging, prod) ?
Dạ, câu này rất hay và thực tế trong dự án. Em xin trình bày gọn gàng – đúng tinh thần phỏng vấn Senior Java Developer:
✅ Cách quản lý cấu hình đa môi trường trong Spring Boot
Spring Boot hỗ trợ cấu hình đa môi trường rất linh hoạt qua profile.
🛠️ 1. Sử dụng profile-specific config files
Tạo các file riêng biệt:
application-dev.yml
application-staging.yml
application-prod.yml
Ví dụ:
# application-dev.yml
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/devdb
🧠 2. Kích hoạt profile thông qua:
a. application.yml (default)
spring:
profiles:
active: dev
b. Command line (thường dùng trong CI/CD)
java -jar app.jar --spring.profiles.active=prod
c. Biến môi trường (khi deploy)
SPRING_PROFILES_ACTIVE=staging
🧪 3. Em sử dụng để:
Tách biệt cấu hình DB, logging, API key giữa môi trường dev, test, prod
Tránh hardcode cấu hình nhạy cảm
CI/CD triển khai từng môi trường bằng đúng cấu hình tương ứng
✅ Kết luận:
Em dùng Spring Profile để tách biệt cấu hình, tránh lỗi cấu hình giữa các môi trường, và dễ dàng quản lý khi deploy thực tế.
Last updated