Khi tạo mới một project Spring MVC sử dụng Spring Tool Suite 3 IDE, các bạn có thể thấy, chúng ta có một tập tin web.xml định nghĩa cấu hình cho DispatcherServlet, các tập tin root-context.xml và servlet-context.xml định nghĩa cấu hình các bean trong Spring container bao gồm ViewResolver, một Controller handle request từ người dùng và các tập tin .jsp để hiển thị thông tin cho người dùng. Nếu các bạn muốn làm tất cả những điều này hoàn toàn bằng code Java thì có thể sử dụng các interface WebApplicationInitializer và WebMvcConfigurer. Cụ thể như thế nào? Trong bài viết này, mình sẽ hướng dẫn các bạn cấu hình Spring MVC với WebApplicationInitializer và WebMvcConfigurer các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Maven project:
Các bạn có thể thấy project này đang bị lỗi ở tâp tin pom.xml.
Nguyên nhân là vì mình đang khai báo packaging trong tập tin này với giá trị “war” dành cho ứng dụng web:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<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> <groupId>com.huongdanjava</groupId> <artifactId>spring-mvc-webapplicationinitializer</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> </properties> </project> |
và IDE đang detect là không có tập tin web.xml:
Chúng ta sẽ không thêm tập tin web.xml để fix lỗi này. Các bạn có thể fix nó bằng cách sử dụng Maven plugin maven-war-plugin và cấu hình failOnMissingWebXml với giá trị false như sau:
1 2 3 4 5 6 7 8 |
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> |
Bây giờ chúng ta sẽ khai báo các dependencies cần thiết cho project Spring MVC của chúng ta các bạn nhé!
Các dependencies này như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.17</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> |
Để chạy ứng dụng web này, mình sẽ sử dụng plugin Maven Jetty Plugin như sau:
1 2 3 4 5 |
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.45.v20220203</version> </plugin> |
OK, bây giờ chúng ta sẽ đi vào phần chính của bài viết này các bạn nhé!
Nói nôm na thì interface WebApplicationInitializer dùng để định nghĩa cấu hình cho web application với khai báo cho DispatcherServlet và Spring container. Nó dùng để thay thế tập tin web.xml đó các bạn!
Còn interface WebMvcConfigurer thì dùng để khai báo các cấu hình liên quan đến Spring MVC như ViewResolver và các bean cần thiết để ứng dụng chạy được. Chúng ta cũng sẽ khai báo class này trong class implement interface WebApplicationInitializer nha các bạn!
Mình sẽ tạo mới một class SpringConfiguration implement interface WebMvcConfigurer để định nghĩa Spring container trước.
1 2 3 4 5 6 7 |
package com.huongdanjava.springmvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; public class SpringConfiguration implements WebMvcConfigurer { } |
Các bạn cần khai báo thêm một annotation của Spring là @EnableWebMvc để Spring import các configuration mặc định từ class WebMvcConfigurationSupport hỗ trợ cho Spring MVC. Nếu muốn override bất kỳ configuration mặc định nào thì các bạn có thể override chúng trong class SpringConfiguration này.
Ở đây, mình cần cấu hình ViewResolver nên mình sẽ sử dụng method addViewControllers() để làm điều này:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package com.huongdanjava.springmvc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @EnableWebMvc @Configuration public class SpringConfiguration implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); } @Bean public ViewResolver viewResolver() { InternalResourceViewResolver bean = new InternalResourceViewResolver(); bean.setViewClass(JstlView.class); bean.setPrefix("/WEB-INF/views/"); bean.setSuffix(".jsp"); return bean; } } |
Ở đây, mình đang khai báo một view name là “index” mapping với request “/”. Và như các bạn thấy, mình cũng khai báo thêm bean cho phần ViewResolver sử dụng InternalResourceViewResolver. Chúng ta sẽ có các tập tin .jsp trong thư mục /WEB-INF/views để xây dựng phần View trong mô hình MVC.
Nội dung của tập tin index.jsp của mình như sau:
1 |
<label>Welcome to Huong Dan Java</label> |
Vì chúng ta khai báo annotation @Bean trong class này nên các bạn cũng cần thêm annotation @Configuration để Spring tự scan và tạo bean trong Spring container của nó.
Với class WebApplicationInitializer thì các bạn có thể thêm mới một class implement nó với nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.huongdanjava.springmvc; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class AppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext sc) throws ServletException { AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); root.scan("com.huongdanjava.mvc"); sc.addListener(new ContextLoaderListener(root)); ServletRegistration.Dynamic appServlet = sc.addServlet("appServlet", new DispatcherServlet(new GenericWebApplicationContext())); appServlet.setLoadOnStartup(1); appServlet.addMapping("/"); } } |
Ở đây, chúng ta đang sử dụng class AnnotationConfigWebApplicationContext để cấu hình cách mà Spring sẽ làm để tự động tạo bean trong containter của nó sử dụng annotation. Spring sẽ tự scan package “com.huongdanjava.springmvc” để làm điều này.
Chúng ta cũng khởi tạo DispatcherServlet và thêm nó vào ServletContext. Các bạn có thể đọc thêm bài viết này để hiểu rõ về cách Spring sẽ làm việc với Java Servlet nhé!
OK, bây giờ các bạn có thể chạy ứng dụng web của chúng ta lên và đi đến địa chỉ http://localhost:8080 để kiểm tra kết quả:
Của mình như sau: