-
Spring ControllersJava/Spring 2022. 2. 11. 16:26
Spring의 Controller에 대해 정리하였습니다.
< Introduction >
The Spring framework is an incredible resource to help us quickly build RESTful applications. The core functionality of these applications lies in their ability to receive requests, route them accordingly, and provide a proper response.
- Annotations : recognized by their starting @ symbol, are built-in units of Spring code that make complex functionality readily available in Spring applications.
< Mapping Requests in Spring >
In order to provide a response to a request, the server maps the request to an endpoint.
In Spring, a class is marked as a controller and each of its methods is associated with an endpoint.This is facilitated by two important annotations:
- @RestController : declare a controller and bind the return value of a controller method to the HTTP response body.
- @RequestMapping : wire request types and endpoints to specific class methods.
< @RestController >
- The @RestController annotation should be added to each class that will handle responses to HTTP requests.
- The @RestController combines the functionality of two separate annotations :
@Controller and @ResponseBody
- @Controller is used to make a class identifiable to Spring as a component of the web application.
- @ResponseBody tells Spring to convert the return values of a controller’s methods to JSON and bind that JSON to the HTTP response body. Since almost every major programming language offers some type of JSON (JavaScript Object Notation) support, we can easily take an object created in Spring and translate it to JSON which can be easily parsed in the HTML and displayed on the page.
< @RequestMapping >
- The @RequestMapping annotation accepts several other arguments including path, method, params, and consumes.
- value(path): determine where requests are mapped.
- method: allows the developer to specify which HTTP method should be used when accessing the controller method. The most common are RequestMethod.GET, ...POST, ...PUT, and ...DELETE. Since this is an optional argument, if we do not specify an HTTP method it will be defaulted to GET.
- params: filters requests based on given parameters.
- consumes: used to specify which media type can be consumed; some common media types are "text/plain", "application/JSON", etc.
Example)
@RestController public class VirtualLibrary{ @RequestMapping("/books/all", RequestMethod.GET) // same as @RequestMapping(value = "/books/all", method = RequestMethod.GET) public Book getAllBooks() { return getBook(); } }
+. To use @RestController and @RequestMapping, import the annotations
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping;
< Defining Base Paths >
@RequestMapping can be used on classes as well as methods
- When the @RequestMapping data annotation is used at the class level, the specified path argument will become the base path.
Example)
@RestController @RequestMapping("/books") public class VirtualLibrary { @RequestMapping(value = "/thumbnails", method = RequestMethod.GET) public String[] getBookThumbnails() { //returns thumbnails for all available titles } }
: “/books” is the base path and the getBookThumbnails method is associated with the endpoint “/books/thumbnails”
< Using HTTP Method Annotations >
In addition to @RequestMapping annotation, Spring also offers several annotations which can be used to map to common request types. These annotations perform the same function as @RequestMapping
HTTP Method Annotation Usage @GetMapping Used to specify GET requests to retrieve resources @PostMapping Used to specify POST requests to retrieve resources @PutMapping Used to specify PUT requests to retrieve resources @DeleteMapping Used to specify DELETE requests to retrieve resources Example)
@RequestMapping("/about", method = RequestMethod.GET) // is equivalent to @GetMapping("/about")
< Using Query Parameters >
When users need to pass data to the server, the term we use to describe the process is called binding. The prime example of binding data from a user’s request to an endpoint occurs when a user needs to submit data.
@RequestParam is an annotation that allows us to parse query parameters and capture those parameters as method arguments.- @RequestParam is incredibly helpful because we can take values passed in from the HTTP request, parse them, and then bind the values to a controller method for further processing.
Example : user submits their request for a book with 2 authors and a publishing year of 1995.
libraryapp.com/book?author_count=2&published_year=1995
@GetMapping("/book") public Book isBookAvailable(@RequestParam int author_count, @RequestParam int published_year) { return books.find(author_count, published_year); }
: The author_count and published_year values would map to the method parameters
< Using Template Path Variables >
To maps template variables in the request URI directly to a method’s parameters using @PathVariable
=> To take a variable received from the request URI and pass it into a method as a parameter.Example)
localhost:4001/books/28937
@GetMapping("/books/{id}") public Book isBookAvailable(@PathVariable int id) { return book.findByID(id); }
+. @RequestParam vs @PathVariable : two ways to capture parameters from a request URI
- @RequestParam : captures the id included in the URI /books?id=28937
- @PathVariable : captures the id included in the URI /books/28937 as long as the path includes the {id} variable in books/{id}.
< Deserializing into Objects >
To receive data from request's body.
For example, instead of receiving the first name as a string parameter from an HTTP request, perhaps we may need to receive an entire form object.
Use the @RequestBody annotation on the parameters of a method, To automatically deserialize(parse) the HTTP request body into a Java object which can be bound to the method and further processed.Example)
curl -X POST --data '{\"authorCount\": \"2\", \"publishedYear\": \"1995\"}' "https://localhost:8080/.../book"
class Book { public int authorCount; public int publishedYear; } @GetMapping("/book") public Book isBookAvailable(@RequestBody Book book) { return book.find(book.authorCount, book.publishedYear); }
: the request would need to have authorCount and publishedYear in its body (rather than the previous URL query parameters ?author_count=2&published_year=1995)
< Fine Tuning Responses with @ResponseStatus >
To fine-tune the HTTP response to give the user more information about what occurred using @ResponseStatus annotation
- @ResponseStatus : can be applied to methods to help with fine-tuning HTTP responses. The annotation accepts parameters for the status code and reason.
1. code : Http's Status Code
2. reason : Reasons to an HTTP response Reason for HTTP result
Example : Clients enter all of the required information and click submit.
@PutMapping(path="/book") @ResponseStatus(code = HttpStatus.CREATED, reason = "Book was successfully added") public string addNewBook(@RequestParam string title) { }
< Exception Handling in Spring >
If an error is encountered, we can use ResponseStatusException to exert even more control over the exception handling process.
ResponseStatusException is a class.ResponseStatusException accepts up to 3 arguments:
- HttpStatus code
- String reason
- Throwable cause
Example : method is expecting a number, but if the client’s submission includes a character other than a number, an exception could be thrown.
@GetMapping("/{id}") public Book isBookAvailable(@PathVariable string id) { if (id.isNumeric()) { int id_int = Integer.parseInt(id) return book.findByID(id_int) } else { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "The ID contained a non-numerical value."); } }
: We are accepting the ID from the client as a string and parsing it into an integer. If the parse fails, a NumberFormatException will be thrown. This type of exception may not be so helpful if it is returned to the client. Therefore, we are catching this exception and throwing a new ResponseStatusException that will contain more detailed information.
+. ResponseStatusException class vs @ResponseStatus annotation :
ResponseStatusException is used to create specific responses dynamically, while a @ResponseStatus determines the status code for any response returned by the method.
'Java > Spring' 카테고리의 다른 글
Spring Container & Bean (3) 2024.12.12 Object-Oriented Design and Spring (46) 2024.11.19 Custom Queries with JPA (5) 2024.10.15 Add a Database with JPA (8) 2024.10.14 Hello Spring (2) 2022.02.10