- Sản phẩm & Dịch vụSản phẩm & Dịch vụ
- Giải phápGiải pháp
- Bảng giáBảng giá
- Công tyCông ty
- Tài liệuTài liệu
vi
vi
Chuyên mục với các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.
Technical Writer
I have over 5 years of experience writing technical documentation for tech products, making them accessible and user-friendly. My focus is always on providing clear and precise information. @#@ Tôi đã có hơn 5 năm kinh nghiệm viết tài liệu kỹ thuật cho các sản phẩm công nghệ, giúp người dùng dễ dàng tiếp cận và sử dụng. Tôi luôn tập trung vào việc cung cấp thông tin chính xác và dễ hiểu.
Thảo luận (0)
Đăng nhập để thảo luận

Bạn đang chuẩn bị cho một buổi phỏng vấn về Spring Framework? Đừng lo lắng, với vai trò là một developer dày dặn kinh nghiệm đã từng chinh chiến rất nhiều dự án, tôi có thể giúp bạn vượt qua buổi phỏng vấn với những câu hỏi “hóc búa” nhất. Bài viết này sẽ gợi ý câu trả lời cho những câu hỏi phỏng vấn phổ biến về Spring và giải thích chi tiết các khái niệm quan trọng.
Mẹo nhỏ: Core Java là nền tảng của mọi framework dựa trên Java, vì vậy nếu bạn đang chuẩn bị cho các cuộc phỏng vấn thì hãy đọc thêm về ”Câu hỏi phỏng vấn Java”.
Để giúp bạn chuẩn bị tốt nhất cho buổi phỏng vấn Spring, tôi đã tập hợp gần 50 câu hỏi thường gặp, kèm theo lời giải đáp chi tiết. Bộ câu hỏi này hoàn toàn sát với Spring 5, bao gồm cả những công nghệ mới như Spring WebFlux cho lập trình phản ứng (reactive programming).
Spring là một trong những framework Java EE được sử dụng rộng rãi nhất. Các khái niệm cốt lõi của Spring framework là “Dependency Injection” và “Aspect-Oriented Programming”.
Ngoài việc được biết đến trong các ứng dụng Java thông thường, Spring Framework còn giúp xây dựng mối liên kết lỏng lẻo giữa các thành phần nhờ cơ chế Dependency Injection. Hơn nữa, Spring còn hỗ trợ Lập trình hướng khía cạnh (AOP), cho phép chúng ta dễ dàng thực hiện các tác vụ chung như ghi log hay xác thực người dùng.
Tôi thích Spring bởi framework này mang đến vô số tính năng và module khác nhau, đáp ứng đa dạng các nhu cầu như Spring MVC hay Spring JDBC. Hơn nữa, là một dự án mã nguồn mở, Spring có nguồn tài liệu trực tuyến dồi dào và một cộng đồng lớn mạnh luôn sẵn lòng hỗ trợ, giúp việc học và làm việc với Spring trở nên dễ dàng và thú vị.
Spring Framework được xây dựng dựa trên hai khái niệm thiết kế – Dependency Injection và Aspect-Oriented Programming.
Một số tính năng của Spring Framework bao gồm:
Một số lợi ích của việc sử dụng Spring Framework là:

Spring 5 là một cuộc đại tu lớn từ Spring 4. Một số tính năng quan trọng là:
Bạn có thể xem qua các tính năng của Spring 5 để có cái nhìn tổng quan hơn.
Spring WebFlux là mô-đun mới được giới thiệu trong Spring 5. Spring WebFlux là bước đầu tiên hướng tới mô hình lập trình phản ứng (reactive programming) trong spring framework.
Spring WebFlux là giải pháp thay thế cho mô-đun Spring MVC. Nó được sử dụng để tạo ra một ứng dụng hoàn toàn không đồng bộ và không chặn (non-blocking), được xây dựng trên mô hình thực thi vòng lặp sự kiện (event-loop).
Mẫu thiết kế Dependency Injection cho phép chúng ta loại bỏ các dependency được hard-code và làm cho ứng dụng trở nên ít liên kết hơn, dễ mở rộng và bảo trì hơn. Chúng ta có thể triển khai mẫu dependency injection để di chuyển độ phân giải dependency từ thời gian biên dịch sang thời gian chạy.
Một số lợi ích của việc sử dụng Dependency Injection là: tách biệt các mối quan tâm (Separation of Concerns), giảm thiểu mã lặp (Boilerplate Code reduction), cấu hình linh hoạt cho các thành phần (Configurable components), và dễ dàng kiểm thử đơn vị (easy unit testing).
Chúng ta có thể dùng Google Guice để tự động chèn phụ thuộc (Dependency Injection). Tuy nhiên, trong đa số trường hợp, nhu cầu của chúng ta vượt xa việc chỉ chèn dependency đơn thuần, và đó là lý do Spring trở thành lựa chọn phù hợp hơn.

Chúng ta có thể sử dụng cấu hình dựa trên Spring XML cũng như dựa trên Annotation để triển khai DI trong các ứng dụng spring. Để hiểu rõ hơn, vui lòng đọc ví dụ về Spring Dependency Injection.
Chúng ta có thể cài đặt các plugin vào Eclipse để sở hữu tất cả các tính năng của Spring Tool Suite (STS). Tuy nhiên, STS đi kèm với Eclipse với một số loại thành phần quan trọng khác như hỗ trợ Maven, Template để tạo các loại dự án Spring khác nhau và máy chủ tc server giúp tối ưu hiệu năng cho các ứng dụng Spring..
Tôi đặc biệt thích sử dụng STS vì nó có khả năng làm nổi bật các thành phần của Spring. Nếu bạn làm việc với AOP, STS còn trực quan hóa các advice sẽ được áp dụng tại pointcut nào. Nhờ vậy, thay vì phải tự cấu hình mọi thứ, tôi luôn ưu tiên STS khi phát triển các ứng dụng Spring.
Một số mô-đun Spring Framework quan trọng là:
Trong các ứng dụng doanh nghiệp thường xuất hiện những nhu cầu chung, có thể áp dụng cho nhiều đối tượng và module khác nhau, ví dụ như ghi log, quản lý giao dịch, kiểm tra dữ liệu, xác thực người dùng,… Nếu như lập trình hướng đối tượng (OOP) đạt được tính mô-đun thông qua các lớp, thì AOP lại tiếp cận bằng cách sử dụng các aspect. Các aspect này được cấu hình để tác động lên nhiều phương thức khác nhau trong ứng dụng.
AOP loại bỏ sự phụ thuộc trực tiếp của các tác vụ cắt ngang từ các lớp không thể thực hiện được trong lập trình hướng đối tượng thông thường. Ví dụ, chúng ta có thể có một lớp riêng để ghi nhật ký nhưng các lớp khác sẽ phải gọi các phương thức này. Tuy nhiên, trong AOP, tôi cấu hình các khía cạnh và việc thực thi phương thức diễn ra tự động.
Aspect: Aspect là một lớp đảm nhiệm việc hiện thực hóa các mối quan tâm cắt ngang (cross-cutting concerns), ví dụ điển hình là quản lý giao dịch (transaction management). Các Aspect có thể được định nghĩa như một lớp Java thông thường và sau đó cấu hình trong tệp cấu hình Spring Bean, hoặc chúng ta có thể tận dụng khả năng tích hợp AspectJ của Spring để khai báo một lớp là Aspect thông qua annotation @Aspect.
args() trong pointcut. Khi sử dụng cách này, tên tham số trong phương thức Advice phải trùng khớp với tên tham số mà từ đó kiểu đối số được xác định.Ban đầu, các khái niệm này có vẻ phức tạp, nhưng việc nghiên cứu kỹ lưỡng các ví dụ về Spring Aspect và Advice sẽ giúp bạn dễ dàng nắm bắt và liên hệ chúng với nhau.
AspectJ là sự triển khai tiêu chuẩn cho lập trình hướng khía cạnh trong khi Spring triển khai AOP cho một số trường hợp. Sự khác biệt chính giữa Spring AOP và AspectJ là:
Inversion of Control (IoC) là cơ chế giúp đạt được sự liên kết lỏng lẻo giữa các Object phụ thuộc. Để đạt được điều này và liên kết động của các đối tượng trong thời gian chạy, các đối tượng xác định các dependency của chúng đang được chèn bởi các đối tượng assembler khác. Spring IoC container là chương trình đưa các dependency vào một đối tượng và làm cho nó sẵn sàng để chúng ta sử dụng.
Các lớp chứa IoC của Spring Framework là một phần của các gói org.springframework.beans và org.springframework.context và cung cấp cho chúng ta những cách khác nhau để tách các Object phụ thuộc.
Một số triển khai ApplicationContext hữu ích mà chúng ta sử dụng là;

Bất kỳ lớp java bình thường nào được khởi tạo bởi container Spring IoC được gọi là Spring Bean. Chúng ta sử dụng Spring ApplicationContext để lấy thực thể Spring Bean.
Spring IoC container quản lý vòng đời của Spring Bean, phạm vi bean và chèn bất kỳ dependency cần thiết nào vào bean.
Chúng ta sử dụng tệp cấu hình Spring Bean để xác định tất cả các bean sẽ được khởi tạo bởi Spring Context. Khi chúng ta tạo thực thể của Spring ApplicationContext, nó sẽ đọc tệp XML spring bean và khởi tạo tất cả. Khi context được khởi tạo, chúng ta có thể sử dụng nó để lấy các instance của bean khác nhau.
Ngoài cấu hình Spring Bean, tệp này còn chứa các bộ chặn Spring MVC, trình phân giải chế độ xem và các phần tử khác để hỗ trợ cấu hình dựa trên annotation.
Có ba cách khác nhau để cấu hình Spring Bean.
Cấu hình XML: Đây là cấu hình phổ biến nhất và chúng ta có thể sử dụng phần tử bean trong tệp context để cấu hình Spring Bean. Chẳng hạn:
<bean name="myBean" class="com.journaldev.spring.beans.MyBean"></bean>
Cấu hình dựa trên Java: Nếu bạn chỉ sử dụng annotation, bạn có thể định cấu hình Spring bean bằng cách sử dụng annotation @Bean . Annotation này được sử dụng với các lớp @Configuration để định cấu hình một spring bean. Cấu hình mẫu là:
@Configuration@ComponentScan(value="com.journaldev.spring.main")public class MyConfiguration {@Beanpublic MyService getService(){return new MyService();}}Để lấy bean này từ context spring, chúng ta phải sử dụng đoạn code sau:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
MyConfiguration.class);
MyService service = ctx.getBean(MyService.class);
Cấu hình dựa trên annotation: Chúng ta cũng có thể sử dụng các annotation như:@Component, @Service, @Repository và @Controller với các lớp để định cấu hình chúng thành spring bean. Đối với những lớp này, chúng ta cần cung cấp vị trí gói gốc (base package) để quét các lớp. Chẳng hạn:
<context:component-scan base-package="com.journaldev.spring" />
Có năm phạm vi được xác định cho Spring Bean.
Spring Framework có thể mở rộng và chúng ta cũng có thể tạo phạm vi (scope) của riêng mình. Nhưng hầu hết các trường hợp thì các phạm vi được cung cấp bởi framework đã đủ dùng. Để thiết lập phạm vi Spring bean, chúng ta có thể sử dụng thuộc tính “scope” trong phần tử bean hoặc annotation @Scope cho các cấu hình dựa trên annotation.

Spring Bean được khởi tạo bởi Spring Container và tất cả các phụ thuộc cũng được tiêm vào. Khi context bị hủy, nó cũng hủy tất cả các bean đã khởi tạo. Nguyên tắc khởi tạo mặc định thường phù hợp, nhưng đôi khi chúng ta cần thực hiện các tác vụ chuẩn bị khác, chẳng hạn như khởi tạo tài nguyên bổ sung hoặc kiểm tra dữ liệu trước khi bean được đưa vào sử dụng. Spring Framework hỗ trợ các phương thức post-initialization (sau khởi tạo) và pre-destruction (trước khi hủy) để đáp ứng những nhu cầu này trong Spring bean.
Chúng ta có thể làm điều này theo hai cách – bằng cách triển khai các giao diện InitializingBean và DisposableBean hoặc sử dụng thuộc tính init-method và destroy-method trong cấu hình spring bean.
Có hai cách để lấy các đối tượng cụ thể của Container trong spring bean.
ServletContextAware và ServletConfigAware. Để xem ví dụ đầy đủ về các interface này, bạn có thể tham khảo bài viết Spring Aware Interfaces.@Autowired với biến bean có kiểu ServletContext hoặc ServletConfig. Tuy nhiên, cách này chỉ hoạt động trong các môi trường cụ thể sử dụng servlet container.@Autowired
ServletContext servletContext;
Quá trình tiêm các dependency vào Spring Bean trong lúc khởi tạo được gọi là Spring Bean Wiring. Mặc dù việc khai báo rõ ràng các dependency thường là lựa chọn tốt nhất, Spring vẫn hỗ trợ cơ chế autowire. Chúng ta có thể sử dụng annotation @Autowired trên các trường hoặc phương thức autowire theo kiểu dữ liệu. Để annotation này có hiệu lực, cần kích hoạt cấu hình dựa trên annotation trong file cấu hình Spring bằng phần tử <context:annotation-config>.
Spring Framework cung cấp bốn loại autowire:
@Autowired và @QualifierTrước Spring 3.1, còn có tùy chọn autowire tự động (autodetect), tương tự như byConstructor hoặc byType. Bạn có thể tìm hiểu thêm về các tùy chọn này trong tài liệu về Spring Bean Autowiring.
Vấn đề về tính an toàn luồng (thread safety) của Spring Bean là một khía cạnh quan trọng cần xem xét. Theo mặc định, phạm vi (scope) của Spring Bean là singleton, nghĩa là chỉ có duy nhất một instance được tạo ra trong mỗi Spring IoC container. Điều này đồng nghĩa với việc nếu một Bean singleton chứa các biến ở cấp độ lớp (class-level variables) mà nhiều luồng (threads) có thể đồng thời truy cập và sửa đổi, sẽ dẫn đến tình trạng dữ liệu không nhất quán. Do đó, trong cấu hình mặc định, các Spring Bean không đảm bảo tính an toàn luồng.
Tuy nhiên, Spring Framework cung cấp khả năng thay đổi phạm vi của Bean thành request, prototype, hoặc session. Việc điều chỉnh phạm vi này có thể đạt được tính an toàn luồng, nhưng cần lưu ý rằng điều này có thể đi kèm với sự suy giảm hiệu suất do việc tạo và quản lý nhiều instance hơn. Quyết định lựa chọn phạm vi Bean là một yếu tố thiết kế then chốt, phụ thuộc hoàn toàn vào các yêu cầu cụ thể của dự án.
Cũng giống như mẫu thiết kế MVC, Controller là lớp xử lý tất cả các yêu cầu của máy khách và gửi chúng đến các tài nguyên được định cấu hình để xử lý chúng. Trong Spring MVC, DispatcherServlet là lớp điều khiển phía trước khởi tạo context dựa trên cấu hình spring bean. Một Controller class đảm nhiệm việc xử lý các loại yêu cầu khác nhau từ client dựa trên các ánh xạ yêu cầu (request mappings). Chúng ta có thể tạo một lớp Controller bằng cách sử dụng annotation @Controller. Thông thường, annotation này được sử dụng kết hợp với annotation @RequestMapping để định nghĩa các phương thức xử lý (handler methods) cho các ánh xạ URI cụ thể.

@Component được sử dụng để đánh dấu một lớp là một component (thành phần). Các lớp này được sử dụng cho cơ chế tự động phát hiện (auto-detection) và được cấu hình như một bean khi sử dụng cấu hình dựa trên annotation.
@Controller là một loại component cụ thể, được sử dụng trong các ứng dụng MVC (Model-View-Controller) và thường được sử dụng cùng với annotation @RequestMapping.
Annotation @Repository được sử dụng để đánh dấu một component được sử dụng như một repository (kho lưu trữ) và là một cơ chế để lưu trữ/truy xuất/tìm kiếm dữ liệu. Chúng ta có thể áp dụng annotation này cho các lớp triển khai pattern DAO (Data Access Object).
@Service được sử dụng để đánh dấu một lớp là một Service (dịch vụ). Thông thường, các lớp facade nghiệp vụ (business facade classes) cung cấp một số dịch vụ sẽ được đánh dấu bằng annotation này.
Chúng ta có thể sử dụng bất kỳ annotation nào ở trên cho một lớp để tự động phát hiện, nhưng các loại khác nhau được cung cấp để bạn có thể dễ dàng phân biệt mục đích của các lớp đã được đánh dấu.
DispatcherServlet là bộ điều khiển phía trước trong ứng dụng Spring MVC và nó tải tệp cấu hình spring bean và khởi tạo tất cả các bean được định cấu hình. Nếu annotation được bật, nó cũng quét các gói và định cấu hình bất kỳ bean nào được chú thích bằng annotation @Component, @Controller, @Repository hoặc @Service.
ContextLoaderListener là một thành phần lắng nghe (listener) trong Spring, có nhiệm vụ khởi tạo và đóng WebApplicationContext gốc của ứng dụng web. Chức năng quan trọng của nó là gắn kết vòng đời của ApplicationContext với vòng đời của ServletContext và tự động tạo ra ApplicationContext. Nhờ đó, chúng ta có thể cấu hình các bean dùng chung thông qua listener này, cho phép nhiều thành phần Spring khác nhau trong ứng dụng cùng sử dụng.
Việc triển khai ViewResolver được sử dụng để phân giải các trang chế độ xem theo tên. Ta có thể định cấu hình nó trong tệp cấu hình spring bean. Chẳng hạn:
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
InternalResourceViewResolver là một trong những triển khai của giao diện ViewResolver và chúng ta đang cung cấp thư mục trang xem và vị trí hậu tố thông qua các thuộc tính bean. Vì vậy, nếu một phương thức xử lý bộ điều khiển trả về “home”, view resolver sẽ sử dụng view page nằm tại /WEB-INF/views/home.jsp.
Giao diện MultipartResolver được sử dụng để tải lên các tệp. CommonsMultipartResolver và StandardServletMultipartResolver là hai triển khai được cung cấp bởi spring framework để tải lên tệp. Theo mặc định, không có bộ phân giải multipart nào được định cấu hình nhưng để sử dụng chúng cho việc tải các tập tin, tất cả chúng ta cần xác định một bean có tên là “multipartResolver” với phân loại là MultipartResolver trong cấu hình spring bean.
Sau khi được cấu hình, bất kỳ yêu cầu nhiều phần nào sẽ được giải quyết bởi MultipartResolver được định cấu hình và chuyển một HttpServletRequest được bao bọc. Sau đó, nó được sử dụng trong lớp controller để lấy tệp và xử lý.
Spring MVC Framework cung cấp các cách sau để giúp chúng ta đạt được việc xử lý ngoại lệ một cách hiệu quả.
Controller-Based: Chúng ta có thể xác định các phương thức xử lý ngoại lệ trong các lớp controller. Tất cả những gì chúng ta cần là chú thích các phương pháp này bằng annotation @ExceptionHandler.
Global Exception Handler: Xử lý ngoại lệ là một mối quan tâm xuyên suốt và Spring cung cấp annotation @ControllerAdvice mà chúng ta có thể sử dụng với bất kỳ lớp nào để xác định trình xử lý ngoại lệ toàn cầu của chúng ta.
Triển khai HandlerExceptionResolver: Đối với các ngoại lệ chung, hầu hết thời gian chúng tôi phục vụ các trang tĩnh. Spring Framework cung cấp một giao diện HandlerExceptionResolver mà chúng ta có thể thực hiện để tạo ra một trình xử lý ngoại lệ toàn cục. Lý do Spring bổ sung thêm cách tiếp cận này là vì framework cũng cung cấp sẵn các lớp triển khai mặc định của HandlerExceptionResolver. Chúng ta có thể khai báo các lớp này trong file cấu hình Spring Bean để tận dụng các tính năng xử lý ngoại lệ mặc định mà Spring cung cấp.

Có những cách sau đây để tạo sping context trong một chương trình java độc lập.
Đối với các ứng dụng Spring MVC, chúng ta có thể định nghĩa nhiều tệp cấu hình spring context thông qua contextConfigLocation. Chuỗi vị trí này có thể bao gồm nhiều vị trí được phân tách bằng bất kỳ số dấu phẩy và dấu cách nào. Ví dụ như:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml,/WEB-INF/spring/appServlet/servlet-jdbc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Chúng ta cũng có thể định nghĩa nhiều cấu hình Spring ở cấp độ gốc (root level) và tải chúng thông qua context-param. Ví dụ:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml /WEB-INF/spring/root-security.xml</param-value>
</context-param>
Một tùy chọn khác là sử dụng phần tử import trong tệp cấu hình để nhập thêm các cấu hình khác, ví dụ:
<beans:import resource="spring-jdbc.xml"/>
ContextLoaderListener là lớp listener được sử dụng để tải context gốc và xác định cấu hình spring bean sẽ hiển thị cho tất cả các context khác. Nó được định cấu hình trong tệp web.xml như sau:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Để tạo một ứng dụng Spring MVC đơn giản, chúng ta sẽ cần thực hiện các tác vụ sau.
Các bước trên là các bước cơ bản để tạo ra một ứng dụng Spring MVC Hello World đơn giản.
Cái tên MVC cũng cho chúng ta biết rằng Spring MVC được xây dựng trên kiến trúc Model-View-Controller. DispatcherServlet là Front Controller trong ứng dụng Spring MVC, xử lý tất cả các yêu cầu đến và ủy quyền chúng cho các phương thức xử lý bộ điều khiển khác nhau.
Mô hình có thể là bất kỳ Java Bean nào trong Spring Framework, giống như bất kỳ framework MVC khác Spring cung cấp liên kết tự động dữ liệu biểu mẫu với java bean. Chúng ta có thể đặt mô hình bean làm thuộc tính được sử dụng trong các trang xem.
View Pages có thể là JSP, HTML tĩnh, v.v. và view resolvers có chức năng tìm đúng view page. Khi trang xem được xác định, quyền kiểm soát được trao lại cho bộ điều khiển DispatcherServlet. DispatcherServlet chịu trách nhiệm hiển thị chế độ xem và trả về phản hồi cuối cùng cho máy khách.
Spring cung cấp hỗ trợ tuyệt vời cho localization hoặc i18n thông qua các gói tài nguyên. Các bước cơ bản cần thiết để triển khai localization cho ứng dụng bao gồm:
<beans:bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:messages" />
<beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>
<beans:bean id=”localeResolver”
class=”org.springframework.web.servlet.i18n.CookieLocaleResolver”>
<beans:property name=”defaultLocale” value=”en” />
<beans:property name=”cookieName” value=”myAppLocaleCookie”></beans:property>
<beans:property name=”cookieMaxAge” value=”3600″></beans:property>
</beans:bean>
<interceptors>
<beans:bean class=”org.springframework.web.servlet.i18n.LocaleChangeInterceptor”>
<beans:property name=”paramName” value=”locale” />
</beans:bean>
</interceptors>
Chúng ta có thể sử dụng Spring Framework để tạo các dịch vụ web Restful trả về dữ liệu JSON. Spring cung cấp tích hợp với Jackson JSON API. API này được sử dụng để gửi phản hồi JSON trong một dịch vụ web restful.
Chúng ta sẽ cần thực hiện các bước sau để định cấu hình ứng dụng Spring MVC để gửi phản hồi JSON.
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.databind-version}</version>
</dependency>
2. Định cấu hình RequestMappingHandlerAdapter bean trong tệp cấu hình spring bean và đặt thuộc tính message converters thành MappingJackson2HttpMessageConverter bean. Cấu hình mẫu sẽ là:
<!-- Configure to plugin JSON as request and response in method handler -->
<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter"/>
</beans:list>
</beans:property>
</beans:bean>
<!– Configure bean to convert JSON to POJO and vice versa –>
<beans:bean id=”jsonMessageConverter” class=”org.springframework.http.converter.json.MappingJackson2HttpMessageConverter”>
</beans:bean>
3. Trong các phương thức xử lý bộ điều khiển, trả về Object trong response bằng cách sử dụng annotation @ResponseBody. Đoạn code mẫu:
@RequestMapping(value = EmpRestURIConstants.GET_EMP, method = RequestMethod.GET)
public @ResponseBody Employee getEmployee(@PathVariable("id") int empId) {
logger.info("Start getEmployee. ID="+empId);
return empData.get(empId);
}
4. Bạn có thể gọi rest service thông qua bất kỳ API nào, nhưng nếu bạn muốn sử dụng Spring thì bạn có thể dễ dàng thực hiện nó bằng cách sử dụng lớp RestTemplate.
Một số annotation Spring mà tôi đã sử dụng trong dự án của mình là:
Được. chúng ta có thể sử dụng annotation @ResponseBody. Đây là cách tôi gửi phản hồi dựa trên JSON hoặc XML trong các dịch vụ web restful.
Spring cung cấp tính năng tải tệp tích hợp sẵn thông qua việc triển khai giao diện MultipartResolver. Nó cực kỳ dễ sử dụng, bạn chỉ cần thay đổi một chút trong cấu hình là có thể hoạt động được ngay. Sau đó, chúng ta sẽ viết phương thức trong controller để xử lý tệp đến và làm những gì cần thiết với nó.
Spring hỗ trợ xác thực dựa trên annotation JSR-303 cũng như cung cấp một giao diện Validator mà chúng ta có thể thực hiện để tạo ra trình xác thực tùy chỉnh của riêng mình. Để sử dụng xác thực dựa trên JSR-303, chúng ta cần annotation các biến bean với các xác thực cần thiết.
Spring MVC Interceptor hoạt động tương tự như Servlet Filter, cho phép chúng ta “chặn” và xử lý các yêu cầu từ máy khách. Chúng ta có thể can thiệp vào các yêu cầu này ở ba giai đoạn khác nhau: preHandle (trước khi xử lý), postHandle (sau khi xử lý nhưng trước khi render view), và afterCompletion (sau khi hoàn tất mọi thứ).
Để tạo một Interceptor trong Spring, bạn có thể triển khai giao diện HandlerInterceptor hoặc mở rộng lớp trừu tượng HandlerInterceptorAdapter. Sau đó, bạn cần cấu hình Interceptor này trong file Spring Bean của dự án. Bạn có toàn quyền quyết định: hoặc chặn tất cả các yêu cầu, hoặc chỉ áp dụng cho các URI cụ thể mà bạn muốn.
Spring Framework cung cấp sự tích hợp tuyệt vời với API JDBC và cung cấp lớp tiện ích JdbcTemplate mà chúng ta có thể sử dụng để tránh mã bolier-plate từ logic hoạt động cơ sở dữ liệu của chúng ta như Opening/Closing Connection, ResultSet, PreparedStatement, v.v.
Để sử dụng JNDI DataSource được cấu hình bởi servlet container, chúng ta cần cấu hình nó trong tệp cấu hình spring bean và sau đó đưa nó vào spring bean dưới dạng dependency. Nhờ vậy, ta có thể sử dụng nó với JdbcTemplate để thực hiện các thao tác cơ sở dữ liệu.
<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName" value="java:comp/env/jdbc/MyLocalDB"/>
</beans:bean>
Spring framework hỗ trợ quản lý giao dịch thông qua quản lý giao dịch khai báo cũng như quản lý giao dịch có lập trình. Quản lý giao dịch khai báo được sử dụng rộng rãi nhất vì nó dễ sử dụng và hoạt động trong hầu hết các trường hợp.
Chúng ta sử dụng annotation @Transactional để đánh dấu một phương thức cho việc quản lý giao dịch khai báo. Để làm được điều này, ta cần cấu hình transaction manager cho DataSource trong tệp cấu hình Spring bean.
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
Hỗ trợ Spring DAO được cung cấp để làm việc với các công nghệ truy cập dữ liệu như JDBC, Hibernate một cách nhất quán và dễ dàng. Ví dụ: chúng ta có JdbcDaoSupport, HibernateDaoSupport, JdoDaoSupport và JpaDaoSupport cho các công nghệ tương ứng.
Spring DAO cũng giúp chuẩn hóa hệ thống ngoại lệ (exception hierarchy) và chúng ta không cần phải xử lý riêng từng loại exception cụ thể.
Chúng ta có thể sử dụng mô-đun Spring ORM để tích hợp các framework Spring và Hibernate nếu bạn đang sử dụng Hibernate 3+ trong đó SessionFactory cung cấp phiên bản hiện tại, thì bạn nên tránh sử dụng các lớp HibernateTemplate hoặc HibernateDaoSupport và tốt hơn là sử dụng mẫu DAO với dependency injection cho tích hợp.
Spring ORM cung cấp hỗ trợ cho việc sử dụng quản lý giao dịch khai báo Spring, vì vậy bạn nên sử dụng điều đó thay vì sử dụng mã boiler-plate Hibernate để quản lý giao dịch.
Spring security framework tập trung vào việc cung cấp cả xác thực và ủy quyền trong các ứng dụng java. Nó cũng xử lý hầu hết các lỗ hổng bảo mật phổ biến như tấn công CSRF.
Nó đem lại nhiều lợi ích và dễ sử dụng bảo mật Spring trong các ứng dụng web, thông qua việc sử dụng các annotation như @EnableWebSecurity.
Chúng ta phải định nghĩa bean propertyConfigurer để tải các thuộc tính từ tệp thuộc tính đã cho. Sau đó, chúng ta có thể sử dụng hỗ trợ Spring EL để đưa các thuộc tính vào các phụ thuộc bean khác. Chẳng hạn:
<bean id="propertyConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" value="/WEB-INF/application.properties" />
</bean>
<bean class="com.journaldev.spring.EmployeeDaoImpl">
<property name="maxReadResults" value="${results.read.max}"/>
</bean>
Nếu bạn đang sử dụng annotation để cấu hình spring bean, thì bạn có thể chèn thuộc tính như bên dưới.
@Value("${maxReadResults}")
private int maxReadResults;
Spring Framework đang sử dụng rất nhiều mẫu thiết kế, một số mẫu phổ biến là:
Một số phương pháp triển khai Spring Framework hay bao gồm:
Spring Boot chính là điểm đặc biệt giúp Spring Framework nổi bật. Nó giúp chúng ta dễ dàng xây dựng nhiều loại ứng dụng Java khác nhau và đóng gói chúng thành một file JAR duy nhất. Nhờ đó, chúng ta có thể chạy ứng dụng ngay lập tức mà không cần phải triển khai lên một servlet container riêng biệt. Điều này giúp tiết kiệm đáng kể thời gian thiết lập dự án ban đầu, cho phép chúng ta nhanh chóng tập trung vào logic nghiệp vụ thay vì loay hoay với các bước cấu hình và triển khai thông thường. Vì đây là một chủ đề rất rộng, tôi khuyên bạn nên tìm hiểu thêm về các câu hỏi phỏng vấn liên quan đến Spring Boot để nắm vững kiến thức.
Trên đây là tất cả những tuyệt chiêu giúp bạn trả lời các câu hỏi phỏng vấn Spring Framework. Hy vọng chúng sẽ giúp bạn tự tin hơn trong cuộc phỏng vấn Java EE sắp tới. Danh sách này sẽ được cập nhật thường xuyên khi tôi tìm thấy những câu hỏi thú vị hơn. Nếu bạn có bất kỳ đề xuất nào, đừng ngần ngại để lại bình luận bên dưới nhé. Tôi luôn sẵn sàng lắng nghe và sẽ cân nhắc bổ sung vào danh sách.