Learn to create Spring WebMVC controllers with @Controller
annotation and map HTTP requests with annotations like @RequestMapping
, @GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
and @PatchMapping
.
1. Request Mapping Annotations
Before Spring 4.3, Spring had only @RequestMapping
annotation for mapping all the incoming HTTP request URLs to the corresponding controller methods.
For example, in the given below code, we are using the @RequestMapping
annotation to map 3 different HTTP requests to their respective controller methods. Notice that we have specified the HTTP request type (GET, POST etc.) as the annotation attribute method
.
@RequestMapping(value = "/users", method = RequestMethod.GET)
public Users getUsers() {
}
@RequestMapping(value = "/users", method = RequestMethod.POST)
public User createUser(User user) {
}
@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public User getUser(@PathVariable("id") String id) {
}
Spring 4.3 introduced five new and more specific annotations for each HTTP request type.
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
Using these new annotations, we can rewrite the @RequestMapping
example as given below. If you see carefully, we do not have the method
attribute anymore in the new annotations.
@GetMapping(value = "/users")
public Users getUsers() {
}
@PostMapping(value = "/users")
public User createUser(User user) {
}
@GetMapping(value = "/users/{id}")
public User getUser(@PathVariable("id") String id) {
}
2. Spring @GetMapping Example
- The @GetMapping annotation is a specialized version of
@RequestMapping
annotation that acts as a shortcut for@RequestMapping(method = RequestMethod.GET)
. - The
@GetMapping
annotated methods in the @Controller annotated classes handle the HTTPGET
requests matched with given URI expression.
Let us understand with example how to write controller methods mapped with @GetMapping annotations.
@RestController
public class UserController {
@Autowired
UserService userService;
@GetMapping("users")
public ResponseEntity<List<User>> getAll() {
return new ResponseEntity<>(userService.getAll(), HttpStatus.OK);
}
@GetMapping("users/{id}")
public ResponseEntity<User> getById(@PathVariable long id) {
Optional<User> user = userService.getById(id);
if (user.isPresent()) {
return new ResponseEntity<>(user.get(), HttpStatus.OK);
} else {
throw new RecordNotFoundException();
}
}
}
3. Spring @PostMapping Example
- The @PostMapping is specialized version of
@RequestMapping
annotation that acts as a shortcut for@RequestMapping(method = RequestMethod.POST)
. - The
@PostMapping
annotated methods in the @Controller annotated classes handle the HTTPPOST
requests matched with given URI expression.
Let us understand with example how to write controller methods mapped with @PostMapping annotations.
@PostMapping(path = "users",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> create(@RequestBody User newUser) {
User user = userService.save(newUser);
if (user == null) {
throw new ServerException();
} else {
return new ResponseEntity<>(user, HttpStatus.CREATED);
}
}
4. Shared Class Level Attributes
All the above-discussed request mapping annotations such as @RequestMapping, @GetMapping, @PostMapping etc., inherit the annotation attributes values from the @RequestMapping annotation applied at the @Controller class.
The method-level annotations may override the default values by providing their own set of values.
For example, in HomeController.java, @RequestMapping annotation at line no. 4 provides the default values of produces
attribute. It means that all the request handler methods in this controller class will, by default, will return the JSON response.
But addMember_V2()
method at line no. 12, overrides the produces
attribute and it will return the XML response to the clients.
Note that addMember_V1()
method will produce the content in default media type i.e. application/json
.
package com.howtodoinjava.web;
@Controller
@RequestMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE)
public class HomeController
{
@PostMapping(path = "/members")
public void addMember_V1(@RequestBody Member member) {
//code
}
@PostMapping(path = "/members", produces = MediaType.APPLICATION_XML_VALUE)
public void addMember_V2(@RequestBody Member member) {
//code
}
}
5. Difference between @PostMapping and @RequestMapping
- As noted above @PostMapping annotation is one specialized version of
@RequestMapping
annotation which handles only the HTTP POST requests.
The difference in one line
@PostMapping = @RequestMapping(method = { RequestMethod.POST })
- Let’s see the difference between PostMapping and @RequestMapping annotations with a very simple example. Both versions in the given example will work exactly the same. They just have a slightly different syntax.
@RequestMapping(value = "/employees", method = RequestMethod.POST) //1
@PostMapping("/employees") //2
- @PostMapping acts as a shortcut for @RequestMapping(method = RequestMethod.POST). We can see the sourcecode of the
@PostMapping
annotation which internally uses the@RequestMapping
annotation.
@Target({ java.lang.annotation.ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = { RequestMethod.POST })
public @interface PostMapping
{
//code
}
6. Summary
Spring MVC has made writing request handler controller classes and methods very easy. Just add a few annotations like @GetMapping and @PostMapping and put the class where component scanning can find them and configure them in the web application context.
It is also very easy to create attributes at the class level so that all handler methods inherit them by default, and can override them when needed.
Same way, you can use other request mapping annotations e.g. @PutMapping
, @DeleteMapping
and @PatchMapping
.
Happy Learning !!
I’m using @PostMapping like this:
@PostMapping(value = “/echo”)
public String postEcho(@RequestBody String entity) {
//TODO: process POST request
return entity;
}
and use a form to post data like this:
but it respond me Only one connection receive subscriber allowed.
why it run like this?
Please elaborate? – “but it respond me Only one connection receive subscriber allowed.”