1. Giới Thiệu Về Spring Framework và Spring Boot
Spring Framework là một framework Java cung cấp hỗ trợ hạ tầng cho việc xây dựng các ứng dụng cấp doanh nghiệp. Tính năng nổi bật nhất của nó là Inversion of Control (IoC): thay vì bạn tự tạo và kết nối các đối tượng (new SomeClass()), Spring tạo và quản lý các đối tượng (beans) cho bạn, tiêm chúng vào nơi cần thiết.
Spring Boot là một công cụ được xây dựng trên Spring Framework giúp phát triển nhanh hơn bằng cách:
- Tự động cấu hình mà không cần file XML.
- Cung cấp các "starter" dependencies (chỉ cần thêm một dòng vào
pom.xmlthay vì 10 dòng). - Nhúng Tomcat/Jetty để bạn có thể chạy ứng dụng chỉ với lệnh
java -jar.
Nếu không có Spring Boot, bạn sẽ phải cấu hình thủ công các kết nối cơ sở dữ liệu, servlet containers và beans. Với Spring Boot, hầu hết mọi thứ đều tự động.
2. Spring Core
- IoC Container: Là một hộp tạo ra và quản lý các đối tượng (beans) của bạn.
- ApplicationContext: Là container chính của Spring, tải các định nghĩa bean và kết nối các dependency.
- Bean Lifecycle: Cách mà các bean được tạo ra, khởi tạo và hủy bỏ.
Ví dụ:
java
@Configuration
public class AppConfig {
@Bean
public MessageService messageService() {
return new MessageService();
}
}
public class MessageService {
public String getMessage() {
return "Xin chào, Spring!";
}
}
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
MessageService service = context.getBean(MessageService.class);
System.out.println(service.getMessage());
}
}
Giải thích:
@Configurationthông báo cho Spring rằng lớp này định nghĩa các bean.@Beanđăng ký một bean (MessageService) bên trong container.ApplicationContexttải các bean và quản lý chúng.- Thay vì sử dụng
new MessageService(), chúng ta yêu cầu Spring cung cấp nó (getBean).
Các Phạm Vi Bean:
- singleton (mặc định) → một instance cho toàn bộ ứng dụng.
- prototype → một instance mới mỗi khi bạn yêu cầu.
- request → một cho mỗi HTTP request (chỉ dành cho ứng dụng web).
- session → một cho mỗi phiên làm việc của người dùng.
3. Interceptors & Filters
- Filters (cấp Servlet): Làm việc trước khi một request đến được Spring. Tốt cho việc ghi log, xác thực, v.v.
- Interceptors (cấp Spring MVC): Làm việc trước/sau khi gọi controller. Tốt cho các mối quan tâm chéo như đo thời gian thực thi.
Ví dụ: Filter
java
@Component
public class LoggingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
System.out.println("Request received at: " + new Date());
chain.doFilter(req, res);
}
}
Giải thích: Mỗi request đi qua filter này. Nó ghi lại thời gian, sau đó tiếp tục (chain.doFilter).
Ví dụ: Interceptor
java
@Component
public class RequestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
System.out.println("Trước Controller: " + req.getRequestURI());
return true; // tiếp tục request
}
}
Giải thích: Trước khi Spring MVC gọi phương thức controller của bạn, interceptor này sẽ chạy. Bạn có thể dừng request bằng cách trả về false.
4. Tệp Cấu Hình Properties / YAML
Spring Boot sử dụng application.properties hoặc application.yml cho cấu hình.
Ví dụ: application.properties
properties
server.port=8081
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
Giải thích:
server.port=8081→ chạy ứng dụng của bạn trên cổng 8081.spring.datasource.url=...→ cấu hình kết nối cơ sở dữ liệu.
Spring Boot sẽ tự động đọc điều này — không cần phân tích thủ công.
5. Dependencies
Ví dụ pom.xml:
xml
<dependencies>
<!-- Web Starter (REST APIs, Tomcat embedded) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JPA + H2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
Giải thích:
spring-boot-starter-webcung cấp cho bạn Spring MVC + Tomcat.spring-boot-starter-data-jpacung cấp cho bạn Hibernate + JPA.h2cung cấp cho bạn một cơ sở dữ liệu trong bộ nhớ (rất tốt cho việc kiểm thử).spring-boot-starter-securitythêm xác thực & phân quyền.
6. Cấu Hình Cơ Sở Dữ Liệu H2
Ví dụ: application.properties
properties
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
Giải thích:
spring.h2.console.enabled=truecho phép bạn mở một trình duyệt DB trên web.- Truy cập
http://localhost:8080/h2-consoleđể xem cơ sở dữ liệu trong bộ nhớ của bạn.
7. Xây Dựng Todo REST API
Entity
java
@Entity
public class Todo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private boolean completed;
}
Giải thích:
@Entityánh xạ lớp này tới một bảng DB.@Idđánh dấu khóa chính.@GeneratedValuecho phép DB tự động tạo ID.
Repository
java
public interface TodoRepository extends JpaRepository<Todo, Long> { }
Giải thích:
JpaRepositoryđã cung cấp các phương thức nhưsave(),findAll(),deleteById().- Không cần viết SQL thủ công.
Controller
java
@RestController
@RequestMapping("/api/todos")
public class TodoController {
@Autowired
private TodoRepository repo;
@GetMapping
public List<Todo> getAll() {
return repo.findAll();
}
@PostMapping
public Todo create(@RequestBody Todo todo) {
return repo.save(todo);
}
@PutMapping("/{id}")
public Todo update(@PathVariable Long id, @RequestBody Todo todo) {
todo.setId(id);
return repo.save(todo);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
repo.deleteById(id);
}
}
Giải thích:
@RestController→ lớp trả về JSON.@RequestMapping("/api/todos")→ tất cả các endpoint bắt đầu bằng/api/todos.@GetMapping→ trả về tất cả todos.@PostMapping→ tạo một todo (dữ liệu đến từ body của request).@PutMapping→ cập nhật một todo.@DeleteMapping→ xóa một todo theo ID.
8. Bảo Mật Cơ Bản
Ví dụ: Cấu Hình Bảo Mật
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/**").authenticated()
.anyRequest().permitAll()
)
.httpBasic();
return http.build();
}
@Bean
public UserDetailsService users() {
UserDetails user = User.builder()
.username("admin")
.password("{noop}password") // {noop} = plain text
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
Giải thích:
csrf().disable()vô hiệu hóa bảo vệ CSRF (đơn giản hóa API)..httpBasic()cho phép xác thực HTTP Basic → trình duyệt sẽ yêu cầu tên người dùng/mật khẩu.InMemoryUserDetailsManagerđịnh nghĩa một người dùng thử nghiệm (admin/password).- Bây giờ,
GET /api/todosyêu cầu xác thực.