@Controller,@RestController
Spring MVC
provides an annotation-based programming model where @Controller
and @RestController
components use annotations to express request mappings
, request input
, exception handling
, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces. The following example shows a controller defined by annotations:
@Controller
public class HelloController {
@GetMapping("/hello")
public String handle(Model model) {
model.addAttribute("message", "Hello World!");
return "index";
}
}
In the preceding example, the method accepts a Model
and returns a view name as a String
, but many other options exist.
You can define controller beans by using a standard Spring bean definition in the Servlet’s WebApplicationContext
. The @Controller
stereotype allows for auto-detection
, aligned with Spring general support for detecting @Component
classes in the classpath
and auto-registering bean definitions for them. It also acts as a stereotype for the annotated class, indicating its role as a web component.
To enable auto-detection
of such @Controller
beans, you can add component scanning to your Java configuration, as the following example shows:
@Configuration
@ComponentScan("org.example.web")
public class WebConfig {
// ...
}
The following example shows the XML
configuration equivalent of the preceding example:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.example.web"/>
<!-- ... -->
</beans>
@RestController
is a composed annotation
that is itself meta-annotated with @Controller
and @ResponseBody
to indicate a controller whose every method inherits the type-level @ResponseBody
annotation and, therefore, writes directly to the response body versus view resolution and rendering with an HTML
template.
@Request Mapping
You can use the @RequestMapping
annotation to map requests to controllers methods. It has various attributes to match by URL
, HTTP method
, request parameters
, headers
, and media types
. You can use it at the class level to express shared mappings or at the method level to narrow down to a specific endpoint mapping.
There are also HTTP method specific shortcut variants of @RequestMapping
:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
The shortcuts are Custom Annotations
that are provided because, arguably, most controller methods should be mapped to a specific HTTP
method versus using @RequestMapping
, which, by default, matches to all HTTP
methods. At the same, a @RequestMapping
is still needed at the class level to express shared mappings.
The following example has type and method level mappings:
@RestController
@RequestMapping("/persons")
class PersonController {
@GetMapping("/{id}")
public Person getPerson(@PathVariable Long id) {
// ...
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void add(@RequestBody Person person) {
// ...
}
}
@PathVariable
For access to URI
template variables.
You can map requests by using the following glob patterns and wildcards:
?
matches one character*
matches zero or more characters within a path segment**
match zero or more path segments
You can also declare URI
variables and access their values with @PathVariable
, as the following example shows:
@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
You can declare URI
variables at the class and method levels, as the following example shows:
@Controller
@RequestMapping("/owners/{ownerId}")
public class OwnerController {
@GetMapping("/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
}
URI
variables are automatically converted to the appropriate type, or TypeMismatchException
is raised. Simple types (int
, long
, Date
, and so on) are supported by default and you can register support for any other data type.
You can explicitly name URI
variables (for example, @PathVariable("customId")
), but you can leave that detail out if the names are the same and your code is compiled with debugging
information or with the -parameters
compiler flag on Java 8
.
The syntax {varName:regex}
declares a URI
variable with a regular expression that has syntax of {varName:regex}
. For example, given URL “/spring-web-3.0.5 .jar
”, the following method extracts the name
, version
, and file extension
:
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String ext) {
// ...
}
URI
path patterns can also have embedded ${…}
placeholders that are resolved on startup by using PropertyPlaceHolderConfigurer
against local
, system
, environment
, and other property sources
. You can use this, for example, to parameterize a base URL
based on some external configuration.
@ResponseBody
The return value is converted through HttpMessageConverter
implementations and written to the response.
You can use the @ResponseBody
annotation on a method to have the return serialized to the response body through an HttpMessageConverter
. The following listing shows an example:
@GetMapping("/accounts/{id}")
@ResponseBody
public Account handle() {
// ...
}
@ResponseBody
is also supported at the class level, in which case it is inherited by all controller methods. This is the effect of @RestController
, which is nothing more than a meta-annotation marked with @Controller
and @ResponseBody
.
You can use @ResponseBody
with reactive types.
You can use the Message Converters
option of the MVC Config
to configure or customize message conversion.
You can combine @ResponseBody
methods with JSON
serialization views.
@RequestBody
For access to the HTTP
request body. Body content is converted to the declared method argument type by using HttpMessageConverter
implementations.
You can use the @RequestBody
annotation to have the request body read and deserialized into an Object through an HttpMessageConverter
. The following example uses a @RequestBody
argument:
@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
// ...
}
You can use the Message Converters
option of the MVC Config
to configure or customize message conversion.
You can use @RequestBody
in combination with javax.validation.Valid
or Spring’s @Validated
annotation, both of which cause Standard Bean Validation
to be applied. By default, validation errors cause a MethodArgumentNotValidException
, which is turned into a 400
(BAD_REQUEST
) response. Alternatively, you can handle validation errors locally within the controller through an Errors
or BindingResult
argument, as the following example shows:
@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, BindingResult result) {
// ...
}
@RequestParam
For access to the Servlet
request parameters. Parameter values are converted to the declared method argument type.
You can use the @RequestParam
annotation to bind Servlet request parameters
(that is, query parameters or form data) to a method argument in a controller.
The following example shows how to do so:
@Controller
@RequestMapping("/pets")
public class EditPetForm {
// ...
@GetMapping
public String setupForm(@RequestParam("petId") int petId, Model model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
return "petForm";
}
// ...
}
Using @RequestParam
to bind petId
.
By default, method parameters that use this annotation are required, but you can specify that a method parameter is optional by setting the @RequestParam
annotation’s required flag to false or by declaring the argument with an java.util.Optional
wrapper.
Type conversion is automatically applied if the target method parameter type is not String
.
When an @RequestParam
annotation is declared as a Map<String, String>
or MultiValueMap<String, String>
argument, the map is populated with all request parameters.
RedirectAttributes
Specify attributes to use in case of a redirect
(that is, to be appended to the query string) and flash attributes to be stored temporarily until the request after redirect.
By default, all model attributes are considered to be exposed as URI
template variables in the redirect URL
. Of the remaining attributes, those that are primitive types
or collections
or arrays of primitive types
are automatically appended as query parameters.
Appending primitive type attributes
as query parameters can be the desired result if a model instance was prepared specifically for the redirect. However, in annotated controllers
, the model can contain additional attributes added for rendering purposes (for example, drop-down field values). To avoid the possibility of having such attributes appear in the URL
, a @RequestMapping
method can declare an argument of type RedirectAttributes
and use it to specify the exact attributes to make available to RedirectView
. If the method does redirect, the content of RedirectAttributes
is used. Otherwise, the content of the model is used.
The RequestMappingHandlerAdapter
provides a flag called ignoreDefaultModelOnRedirect
, which you can use to indicate that the content of the default Model should never be used if a controller method redirects. Instead, the controller
method should declare an attribute of type RedirectAttributes
or, if it does not do so, no attributes should be passed on to RedirectView
. Both the MVC namespace
and the MVC Java configuration
keep this flag set to false
, to maintain backwards compatibility. However, for new applications, we recommend setting it to true
.
@PostMapping("/files/{path}")
public String upload(...) {
// ...
return "redirect:files/{path}";
}