April 18, 2023
@RestController combines @Controller and @ResponseBody. It is used to return object data in JSON format and is commonly used when developing REST APIs. It wraps objects in ResponseEntity for return. Equivalent implementation with @Controller + @ResponseBody:
@Controller
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/user/{userId}")
public @ResponseBody String getUser(@PathVariable final Long userId) {
System.out.println("Requested user ID: " + userId);
return "User retrieval successful";
}
}
access
attribute: Specifies the access modifier.Before @AllArgsConstructor:
@Getter
public class EditRequestDto {
private String title;
private String content;
public EditRequestDto(String title, String content) {
this.title = title;
this.content = content;
}
}
After @AllArgsConstructor:
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class EditRequestDto {
private String title;
private String content;
}
Example using @RequiredArgsConstructor instead of constructor injection:
Before @RequiredArgsConstructor:
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
}
After @RequiredArgsConstructor:
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
}
These annotations map requests to handlers.
These annotations can all be replaced by @RequestMapping
. For example, @GetMapping("/post/search")
is equivalent to @RequestMapping(value = "/post/search", method = RequestMethod.GET)
.
However, @GetMapping
, @PostMapping
, etc., are more intuitive and make it easier to understand which method handles which request.
@RequestMapping
can be used at both class and method levels, whereas @GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
, @PatchMapping
are used only at the method level.
PUT and PATCH methods both update resources, but:
PUT updates the entire resource. For example, if you want to update only the title
of a post resource while keeping content
and date
unchanged, PUT would require you to send all fields (title
, content
, date
). If any field is empty, it will be set to null.
RequestBody:
{
"title": "Post 1",
"content": "Some content",
"date": "2023-04-18"
}
PATCH updates part of the resource. If you send only the title
field in the RequestBody, PATCH will update only the title
field while leaving content
and date
unchanged.
RequestBody:
{
"title": "Post 2"
}
@PathVariable
extracts variables from the request URI.
@GetMapping("/post/{postId}")
public String getPost(@PathVariable final Long postId) {
System.out.println("Requested post ID: " + postId);
return postService.getDetail(postId);
}
In this example, postId
from the path /post/{postId}
is mapped to Long postId
.
@RequestParam
retrieves parameters from the request URI in query params format.
@GetMapping("/post/search")
public List<Post> search(@RequestParam final String title) {
System.out.println("Search parameter: " + title);
return postService.search(title);
}
For example, if there is a GET API like this /post/search
, requests can be made like /post/search?title=Post1
. Multiple parameters can be received as /post/search?title=Post1&content=SomeContent
.
public List<Post> search(@RequestParam(required = true, defaultValue = "") final String title) {
System.out.println("Search parameter: " + title);
return postService.search(title);
}
You can set required
and defaultValue
. required=true
is the default, so if title
is missing in the request, it will result in a 400 Bad Request error.
@RequestBody
retrieves data sent in the HTTP request body.
@RequestBody
converts JSON (application/json) content from the HTTP body sent by the client into a Java Object.
The key feature is conversion rather than binding, so variables do not need setter functions to be stored correctly.
@PostMapping("/post")
public String register(@RequestBody final RegisterRequestDto request) {
Long postId = postService.register(request);
System.out.println(request.getId() + request.getContent() + request.getTitle());
}
In this code, data received via @RequestBody
is converted into a Java Object (RegisterRequestDto
) so that methods like getTitle()
, getContent()
can be used.
@Getter
generates getters using get[FieldName]()
. Although not used in the example, @Setter
generates setters using set[FieldName]()
.
@PutMapping("/post/{postId}")
public String editPost(@PathVariable final Long postId, @RequestBody final EditRequestDto request) {
System.out.println(request.getTitle() + request.getContent());
return postService.edit(postId, request);
}
In this example, because @Getter
is used in EditRequestDto
, methods like getTitle()
, getContent()
are automatically generated without explicitly defining them.