Spring Boot is great for developing web applications. You can create a standalone HTTP server using built-in Tomcat,
Jetty, Undertow or Netty. Most web applications use the spring-boot-starter-web
module for fast
execution. You can also compile reactive web applications using the spring-boot-starter-webflux
module.
If you want to build servlet-based web applications, you can take advantage of Spring's autoconfiguration capabilities Boot for Spring MVC or Jersey.
Spring Web MVC Framework
Spring Web MVC (often referred
to as "Spring MVC") is a full-fledged web framework based on the model -view-controller". Spring MVC allows you to
create custom beans with @Controller
or @RestController
annotations to handle incoming
HTTP requests. Methods in the controller are mapped to the HTTP protocol using @RequestMapping
annotations.
The following code shows a typical @RestController
annotation that works with JSON
data :
import java.util.List;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/users")
public class MyRestController {
private final UserRepository userRepository;
private final CustomerRepository customerRepository;
public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {
this.userRepository = userRepository;
this.customerRepository = customerRepository;
}
@GetMapping("/{userId}")
public User getUser(@PathVariable Long userId) {
return this.userRepository.findById(userId).get();
}
@GetMapping("/{userId}/customers")
public List<Customer> getUserCustomers(@PathVariable Long userId) {
return this.userRepository.findById(userId).map(this.customerRepository::findByUser).get();
}
@DeleteMapping("/{userId}")
public void deleteUser(@PathVariable Long userId) {
this.userRepository.deleteById(userId);
}
}
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/users")
class MyRestController(private val userRepository: UserRepository, private val customerRepository: CustomerRepository) {
@GetMapping("/{userId}")
fun getUser(@PathVariable userId: Long): User {
return userRepository.findById(userId).get()
}
@GetMapping("/{userId}/customers")
fun getUserCustomers(@PathVariable userId: Long): ListCustomer> {
return userRepository.findById(userId).map(customerRepository::findByUser).get()
}
@DeleteMapping("/{userId}")
fun deleteUser(@PathVariable userId: Long) {
userRepository.deleteById(userId)
}
}
The "WebMvc.fn", a functional option, separates the routing configuration from the actual processing of requests, as shown in the following example:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.function.RequestPredicate;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;
import static org.springframework.web.servlet.function.RequestPredicates.accept;
import static org.springframework.web.servlet.function.RouterFunctions.route;
@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {
private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);
@Bean
public RouterFunction<ServerResponse> routerFunction(MyUserHandler userHandler) {
return route()
.GET("/{user}", ACCEPT_JSON, userHandler::getUser)
.GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers)
.DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser)
.build();
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.web.servlet.function.RequestPredicates.accept
import org.springframework.web.servlet.function.RouterFunction
import org.springframework.web.servlet.function.RouterFunctions
import org.springframework.web.servlet.function.ServerResponse
@Configuration(proxyBeanMethods = false)
class MyRoutingConfiguration {
@Bean
fun routerFunction(userHandler: MyUserHandler): RouterFunction<ServerResponse> {
return RouterFunctions.route()
.GET("/{user}", ACCEPT_JSON, userHandler::getUser)
.GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers)
.DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser)
.build()
}
companion object {
private val ACCEPT_JSON = accept(MediaType.APPLICATION_JSON)
}
}
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
@Component
public class MyUserHandler {
public ServerResponse getUser(ServerRequest request) {
...
return ServerResponse.ok().build();
}
public ServerResponse getUserCustomers(ServerRequest request) {
...
return ServerResponse.ok().build();
}
public ServerResponse deleteUser(ServerRequest request) {
...
return ServerResponse.ok().build();
}
}
import org.springframework.stereotype.Component
import org.springframework.web.servlet.function.ServerRequest
import org.springframework.web.servlet.function.ServerResponse
@Component
class MyUserHandler {
fun getUser(request: ServerRequest?): ServerResponse {
return ServerResponse.ok().build()
}
fun getUserCustomers(request: ServerRequest?): ServerResponse {
return ServerResponse.ok().build()
}
fun deleteUser(request: ServerRequest?): ServerResponse {
return ServerResponse.ok().build()
}
}
RouterFunction
beans as you wish. The beans can be ordered if you want to apply execution order.
Spring MVC Auto-Configuration
Spring Boot provides auto-configuration for Spring MVC, which works fine with most applications.
Auto-configuration adds the following functionality in addition to the default Spring settings:
Adding
ContentNegotiatingViewResolver
andBeanNameViewResolver
beans.Support for processing static resources, including support for WebJars.
Automatic registration of
Converter
,GenericConverter
beans andFormatter
.Support for
HttpMessageConverters
.Automatic registration
MessageCodesResolver
.Support for static
index.html
.Automatic use of the
ConfigurableWebBindingInitializer
bean.
If you need to save these Spring Boot MVC settings and add additional MVC settings (interceptors, formatters,
view controllers and other functions ), then you can add your own class marked with the @Configuration
annotation, like WebMvcConfigurer
, but without the @EnableWebMvc
annotation .
If you need to pass custom instances of RequestMappingHandlerMapping
, RequestMappingHandlerAdapter
or ExceptionHandlerExceptionResolver
and at the same time preserve the Spring Boot MVC settings, then
you can declare a bean of type WebMvcRegistrations
and use it to pass custom instances of these
components.
If you need to fully control the operation of Spring MVC, you can add your own @Configuration
, marked with the @EnableWebMvc
annotation, or you can add your own
DelegatingWebMvcConfiguration
class, marked with the @Configuration
annotation, as
described in the Javadoc for the @EnableWebMvc
annotation.
Spring MVC uses a different ConversionService
than the one
used for value conversion from your application.properties
or application.yaml
file. This
means that the Period
, Duration
and DataSize
converters will not be available
and that the @DurationUnit
and @ annotations DataSizeUnit
will be ignored.
If you need to personalize the settings of the ConversionService
service used by Spring MVC, you can
provide a WebMvcConfigurer
bean with a method addFormatters
. From this method you can
register any preferred converter or delegate authority to the static methods available to ApplicationConversionService
.
HttpMessageConverters
Spring MVC uses the HttpMessageConverter
interface for
converting HTTP requests and responses. Adequate default settings are provided out of the box. For example, objects
can be automatically converted to JSON (using the Jackson library) or to XML (using the Jackson XML extension if
available, or using JAXB if the Jackson XML extension is not available). By default, strings are encoded in UTF-8
.
If you need to add or customize converters, you can use the HttpMessageConverters
class for Spring
Boot, as shown in the following listing:
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();
HttpMessageConverter<?> another = new AnotherHttpMessageConverter();
return new HttpMessageConverters(additional, another);
}
}
import org.springframework.boot.autoconfigure.http.HttpMessageConverters
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.HttpMessageConverter
@Configuration(proxyBeanMethods = false)
class MyHttpMessageConvertersConfiguration {
@Bean
fun customConverters(): HttpMessageConverters {
val additional: HttpMessageConverter<*> = AdditionalHttpMessageConverter()
val another: HttpMessageConverter<*> = AnotherHttpMessageConverter()
return HttpMessageConverters(additional, another)
}
}
Any HttpMessageConverter
bean present in the context , is added to the list of converters. You
can override the default resolvers in the same way.
MessageCodesResolver
Spring MVC contains an
error code generation strategy for printing binding error messages: MessageCodesResolver
. If the
property is set spring.mvc.message-codes-resolver-format
PREFIX_ERROR_CODE
or POSTFIX_ERROR_CODE
,
Spring Boot will create it for you.