Spring MVC Annotations with Examples


In this tutorial, we’ll explore Spring Web annotations from the org.springframework.web.bind.annotation package.

This article is part of a series:

Before you get started, check out Spring Data JPA Tutorial and Spring MVC Tutorial

 Spring MVC Tutorials and Articles :

@RequestBody Annotation

@RequestBody annotation indicating a method parameter should be bound to the body of the web request. The body of the request is passed through an HttpMessageConverter to resolve the method argument depending on the content type of the request. Optionally, automatic validation can be applied by annotating the argument with @Valid.
For example, the employee JSON object is converted into Java employee object using @RequestBody annotation.
@RestController
@RequestMapping("/api/v1")
public class EmployeeController {
    @Autowired
    private EmployeeRepository employeeRepository;
    
    @PostMapping("/employees")
    public Employee createEmployee(@Valid @RequestBody Employee employee) {
        return employeeRepository.save(employee);
    }
Read more at Spring @RequestBody and @ResponseBody Annotations

@RequestMapping

@RequestMapping annotation for mapping web requests onto methods in request-handling classes with flexible method signatures.
Both Spring MVC and Spring WebFlux support this annotation through a RequestMappingHandlerMapping and RequestMappingHandlerAdapter in their respective modules and package structure.
@RequestMapping marks request handler methods inside @Controller classes; it can be configured using:
  • path, or its aliases, name, and value: which URL the method is mapped to
  • method: compatible HTTP methods
  • params: filters requests based on the presence, absence, or value of HTTP parameters
  • headers: filters requests based on the presence, absence, or value of HTTP headers
  • consumes: which media types the method can consume in the HTTP request body
  • produces: which media types the method can produce in the HTTP response body Here’s a quick example of what that looks like:
@Controller
class EmployeeController {
 
    @RequestMapping(value = "/employees/home", method = RequestMethod.GET)
    String home() {
        return "home";
    }
}
We can provide default settings for all handler methods in a @Controller class if we apply this annotation to the class level. The only exception is the URL which Spring won’t override with method level settings but appends the two path parts.
For example, the following configuration has the same effect as the one above:
@Controller
@RequestMapping(value = "/employees", method = RequestMethod.GET)
class EmployeeController {
 
    @RequestMapping("/home")
    String home() {
        return "home";
    }
}

@GetMapping

@GetMapping annotation for mapping HTTP GET requests onto specific handler methods.
Specifically, @GetMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.GET).
Example:
@GetMapping("/employees")
public List<Employee> getAllEmployees() {
 return employeeRepository.findAll();
}

@GetMapping("/employees/{id}")
public ResponseEntity<Employee> getEmployeeById(@PathVariable(value = "id") Long employeeId)
 throws ResourceNotFoundException {
 Employee employee = employeeRepository.findById(employeeId)
   .orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));
 return ResponseEntity.ok().body(employee);
}

@PostMapping

@PostMapping annotation for mapping HTTP POST requests onto specific handler methods.
Specifically, @PostMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.POST).
Example:
@PostMapping("/employees")
public Employee createEmployee(@Valid @RequestBody Employee employee) {
 return employeeRepository.save(employee);
}

@PutMapping

@PutMapping annotation for mapping HTTP PUT requests onto specific handler methods.
Specifically, @PutMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.PUT).
Example:
@PutMapping("/employees/{id}")
public ResponseEntity<Employee> updateEmployee(@PathVariable(value = "id") Long employeeId,
  @Valid @RequestBody Employee employeeDetails) throws ResourceNotFoundException {
 Employee employee = employeeRepository.findById(employeeId)
 .orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));

 employee.setEmailId(employeeDetails.getEmailId());
 employee.setLastName(employeeDetails.getLastName());
 employee.setFirstName(employeeDetails.getFirstName());
 final Employee updatedEmployee = employeeRepository.save(employee);
 return ResponseEntity.ok(updatedEmployee);
}

@DeleteMapping

@DeleteMapping annotation for mapping HTTP DELETE requests onto specific handler methods.
Specifically, @DeleteMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.DELETE).
Example:
@DeleteMapping("/employees/{id}")
public Map<String, Boolean> deleteEmployee(@PathVariable(value = "id") Long employeeId)
  throws ResourceNotFoundException {
 Employee employee = employeeRepository.findById(employeeId)
   .orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));

 employeeRepository.delete(employee);
 Map<String, Boolean> response = new HashMap<>();
 response.put("deleted", Boolean.TRUE);
 return response;
}

@PatchMapping

@PatchMapping annotation for mapping HTTP PATCH requests onto specific handler methods.
Specifically, @PatchMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.PATCH).
Example:
@PatchMapping("/patch")
public @ResponseBody ResponseEntity<String> patch() {
    return new ResponseEntity<String>("PATCH Response", HttpStatus.OK);
}

@ControllerAdvice

@ControllerAdvice annotation is a specialization of @Component. The classes annotated with @ControllerAdvice are auto-detected by classpath scanning.
The use of @ControllerAdvice is advising all or selected controllers for @ExceptionHandler, @InitBinder, and @ModelAttribute. What we have to do is create a class annotated with @ControllerAdvice and create a required method which will be annotated with @ExceptionHandler for global exception handling, @InitBinder for global init binding and @ModelAttribute for global model attributes addition. Whenever a request comes to a controller and its method with @RequestMapping and if there is no locally defined @ExceptionHandler, @InitBinder and @ModelAttribute, the globally defined class annotated with @ControllerAdvice is served.
Here’s a quick example of what that looks like:
@ControllerAdvice(basePackages = {"com.javaguides.springmvc.controller"} )
public class GlobalControllerAdvice {
 @InitBinder
 public void dataBinding(WebDataBinder binder) {
  SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
  dateFormat.setLenient(false);
  binder.registerCustomEditor(Date.class, "dob", new CustomDateEditor(dateFormat, true));
 }
 @ModelAttribute
        public void globalAttributes(Model model) {
  model.addAttribute("msg", "Welcome to My World!");
        }
 @ExceptionHandler(FileNotFoundException.class)
        public ModelAndView myError(Exception exception) {
     ModelAndView mav = new ModelAndView();
     mav.addObject("exception", exception);
     mav.setViewName("error");
     return mav;
 }
}
Read complete example at Spring MVC Exception Handling

@ResponseBody Annotation

When you use the @ResponseBody annotation on a method, Spring converts the return value and writes it to the HTTP response automatically. Each method in the Controller class must be annotated with @ResponseBody.
The @ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object.
For example,
@ResponseBody
@RequestMapping("/hello")
String hello() {
    return "Hello World!";
}
Spring 4.0 introduced @RestController, a specialized version of the controller which is a convenience annotation that does nothing more than adding the @Controller and @ResponseBody annotations.

@ExceptionHandler

@ExceptionHandler annotation for handling exceptions in specific handler classes and/or handler methods.
Handler methods which are annotated with this annotation are allowed to have very flexible signatures.
Spring calls this method when a request handler method throws any of the specified exceptions. The caught exception can be passed to the method as an argument:
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
  ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
  return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}

@ResponseStatus

We can specify the desired HTTP status of the response if we annotate a request handler method with this annotation. We can declare the status code with the code argument, or its alias, the value argument.
Also, we can provide a reason using the reason argument.
We also can use it along with @ExceptionHandler:
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
  ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
  return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}

@PathVariable

This annotation indicates that a method argument is bound to a URI template variable. We can specify the URI template with the @RequestMapping annotation and bind a method argument to one of the template parts with @PathVariable.
We can achieve this with the name or its alias, the value argument:
@RequestMapping("/{id}")
public User getUser(@PathVariable("id") long id) {
    // ...
}
If the name of the part in the template matches the name of the method argument, we don’t have to specify it in the annotation:
@RequestMapping("/{id}")
public User getUser(@PathVariable long id) {
    // ...
}
Moreover, we can mark a path variable optional by setting the argument required to false:
@RequestMapping("/{id}")
public User getUser(@PathVariable(required = false) long id) {
    // ...
}

@RequestParam

@RequestParam annotation which indicates that a method parameter should be bound to a web request parameter. We use @RequestParam for accessing HTTP request parameters:
@RequestMapping
Vehicle getVehicleByParam(@RequestParam("id") long id) {
    // ...
}
It has the same configuration options as the @PathVariable annotation.
In addition to those settings, with @RequestParam we can specify an injected value when Spring finds no or empty value in the request. To achieve this, we have to set the default value argument.
Providing a default value implicitly sets required to false:
@RequestMapping("/buy")
Car buyCar(@RequestParam(defaultValue = "5") int seatCount) {
    // ...
}

@Controller

This annotation is simply a specialization of the @Component class and allows implementation classes to be autodetected through the classpath scanning.
We can define a Spring MVC controller with @Controller. Read more at The Spring @Controller and @RestController Annotations with Examples
For example,
@Controller
@RequestMapping("/api/v1")
public class EmployeeController {
    @Autowired
    private EmployeeRepository employeeRepository;

    @GetMapping("/employees")
    public List<Employee> getAllEmployees() {
        return employeeRepository.findAll();
    }
}

@RestController

Spring 4.0 introduced @RestController, a specialized version of the controller which is a convenience annotation that does nothing more than adding the @Controller and @ResponseBody annotations. By annotating the controller class with @RestController annotation, you no longer need to add @ResponseBody to all the request mapping methods. The @ResponseBody annotation is active by default.
To use @RestController in our example, all we need to do is modify the @Controller to @RestController and remove the @ResponseBody from each method. The resultant class should look like the following:
@RestController
@RequestMapping("/api/v1")
public class EmployeeController {
    @Autowired
    private EmployeeRepository employeeRepository;

    @GetMapping("/employees")
    public List<Employee> getAllEmployees() {
        return employeeRepository.findAll();
    }
}
Read more at The Spring @Controller and @RestController Annotations with Examples

@ModelAttribute

With this annotation we can access elements that are already in the model of an MVC @Controller, by providing the model key:
@PostMapping("/users")
void saveUser(@ModelAttribute("user") User user) {
    // ...
}
Like with @PathVariable and @RequestParam, we don’t have to specify the model key if the argument has the same name:
@PostMapping("/users")
void saveUser(@ModelAttribute User user) {
    // ...
}
Besides, @ModelAttribute has another use: if we annotate a method with it, Spring will automatically add the method’s return value to the model:
@ModelAttribute("vehicle")
User getUser() {
    // ...
}
Like before, we don’t have to specify the model key, Spring uses the method’s name by default:
@ModelAttribute
User user() {
    // ...
}
Before Spring calls a request handler method, it invokes all @ModelAttribute annotated methods in the class.

@CrossOrigin

@CrossOrigin enables cross-domain communication for the annotated request handler methods:
@CrossOrigin
@RequestMapping("/hello")
String hello() {
    return "Hello World!";
}
If we mark a class with it, it applies to all request handler methods in it.
We can fine-tune CORS behavior with this annotation’s arguments.

@InitBinder

@InitBinder annotation that identifies methods which initialize the WebDataBinder which will be used for populating command and form object arguments of annotated handler methods.
Such init-binder methods support all arguments that RequestMapping supports, except for command/form objects and corresponding validation result objects. Init-binder methods must not have a return value; they are usually declared as void.
For example,
 // add an initbinder ... to convert trim input strings
    // remove leading and trailing whitespace
    // resolve issue for our validation

    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {

        StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);

        dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
    }

Related Annotations Posts

  1. Spring Boot Annotations
  2. 15 Spring Core Annotations
  3. Spring Scheduling Annotations
  4. The Spring @Controller and @RestController Annotations with Examples
  5. Spring @RequestBody and @ResponseBody Annotations
  6. Spring @GetMapping, @PostMapping, @PutMapping, @DeleteMapping and @PatchMapping

Comments