Използване на Spring ResponseEntity за манипулиране на HTTP отговора

1. Въведение

Използвайки Spring, обикновено имаме много начини да постигнем една и съща цел, включително фина настройка на HTTP отговорите.

В този кратък урок ще видим как да зададем тялото, състоянието и заглавията на HTTP отговор с помощта на ResponseEntity .

2. ResponseEntity

ResponseEntity представлява целия HTTP отговор: код на състоянието, заглавки и тяло . В резултат на това можем да го използваме, за да конфигурираме напълно HTTP отговора.

Ако искаме да го използваме, трябва да го върнем от крайната точка; За останалото се грижи пролетта.

ResponseEntity е родов тип. Следователно можем да използваме всякакъв тип като тяло на отговора:

@GetMapping("/hello") ResponseEntity hello() { return new ResponseEntity("Hello World!", HttpStatus.OK); }

Тъй като програмно задаваме състоянието на отговора, можем да се върнем с различни кодове на състоянието за различни сценарии:

@GetMapping("/age") ResponseEntity age( @RequestParam("yearOfBirth") int yearOfBirth) { if (isInFuture(yearOfBirth)) { return new ResponseEntity( "Year of birth cannot be in the future", HttpStatus.BAD_REQUEST); } return new ResponseEntity( "Your age is " + calculateAge(yearOfBirth), HttpStatus.OK); }

Освен това можем да зададем HTTP заглавки:

@GetMapping("/customHeader") ResponseEntity customHeader() { HttpHeaders headers = new HttpHeaders(); headers.add("Custom-Header", "foo"); return new ResponseEntity( "Custom header set", headers, HttpStatus.OK); }

Освен това ResponseEntity предоставя два вложени интерфейса на конструктора : HeadersBuilder и неговия подинтерфейс BodyBuilder . Следователно можем да получим достъп до техните възможности чрез статичните методи на ResponseEntity .

Най-простият случай е отговор с тяло и HTTP 200 код за отговор:

@GetMapping("/hello") ResponseEntity hello() { return ResponseEntity.ok("Hello World!"); }

За най-популярните HTTP кодове на състоянието получаваме статични методи:

BodyBuilder accepted(); BodyBuilder badRequest(); BodyBuilder created(java.net.URI location); HeadersBuilder noContent(); HeadersBuilder notFound(); BodyBuilder ok();

Освен това можем да използваме методите BodyBuilder status (HttpStatus status) и BodyBuilder status (int status) , за да зададем всяко HTTP състояние.

И накрая, с ResponseEntity BodyBuilder.body (T тяло) можем да зададем HTTP тялото на отговора:

@GetMapping("/age") ResponseEntity age(@RequestParam("yearOfBirth") int yearOfBirth) { if (isInFuture(yearOfBirth)) { return ResponseEntity.badRequest() .body("Year of birth cannot be in the future"); } return ResponseEntity.status(HttpStatus.OK) .body("Your age is " + calculateAge(yearOfBirth)); }

Също така можем да зададем персонализирани заглавки:

@GetMapping("/customHeader") ResponseEntity customHeader() { return ResponseEntity.ok() .header("Custom-Header", "foo") .body("Custom header set"); }

Тъй като BodyBuilder.body () връща ResponseEntity вместо BodyBuilder, това трябва да е последното повикване.

Имайте предвид, че с HeaderBuilder не можем да зададем никакви свойства на тялото на отговора.

При връщането ResponseEntity обект от контролера, може да получите изключение или грешка при обработката на молбата и би искал да се върне информация за грешка, свързана с потребителя представени като някакъв друг вид, нека да кажат E .

Пролет 3.2 носи поддръжка за глобален @ExceptionHandler с новата анотация @ControllerAdvice , която обработва подобни сценарии. За подробни подробности вижте нашата съществуваща статия тук.

Въпреки че ResponseEntity е много мощен, не бива да го прекаляваме. В прости случаи има и други опции, които задоволяват нашите нужди и водят до много по-изчистен код.

3. Алтернативи

3.1. @ResponseBody

В класическите Spring MVC приложения крайните точки обикновено връщат изобразени HTML страници. Понякога трябва да върнем само действителните данни; например, когато използваме крайната точка с AJAX.

В такива случаи можем да маркираме метода на манипулатора на заявки с @ResponseBody , а Spring обработва стойността на резултата на метода като самото тяло на HTTP отговора .

За повече информация тази статия е добро място за начало.

3.2. @ResponseStatus

Когато една крайна точка се върне успешно, Spring предоставя HTTP 200 (OK) отговор. Ако крайната точка изхвърли изключение, Spring търси манипулатор на изключения, който казва кой HTTP статус да се използва.

Можем да маркираме тези методи с @ResponseStatus и следователно Spring се връща с персонализиран HTTP статус .

За повече примери, моля, посетете нашата статия за персонализирани кодове на състоянието.

3.3. Манипулирайте директно отговора

Spring също така ни позволява директен достъп до обекта javax.servlet.http.HttpServletResponse ; трябва само да го декларираме като аргумент на метод:

@GetMapping("/manual") void manual(HttpServletResponse response) throws IOException { response.setHeader("Custom-Header", "foo"); response.setStatus(200); response.getWriter().println("Hello World!"); }

Тъй като Spring осигурява абстракции и допълнителни възможности над основната реализация, не бива да манипулираме отговора по този начин .

4. Заключение

В тази статия обсъдихме множество начини за манипулиране на HTTP отговора през пролетта и разгледахме техните предимства и недостатъци.

Както обикновено, примерите са достъпни в GitHub.