JavaRush /Java Blog /Random-TL /Exception Handling sa Spring Boot Controllers

Exception Handling sa Spring Boot Controllers

Nai-publish sa grupo
NILALAMAN NG ARTIKULO CYCLE Kumusta muli! Oras na para alisin ang alikabok sa iyong keyboard. Gumawa ng spring-boot project. Mula sa maven dependencies kailangan namin:
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <java.version>1.8</java.version>
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.0.RELEASE</version>
    <relativePath/><!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
Bago magbasa nang higit pa, lumikha ng istraktura ng proyekto: Exception Handling sa Spring Boot Controllers - 1 BusinessException at CustomException:
public class BusinessException extends Exception{
    public BusinessException(String message) {
        super(message);
    }
}

public class CustomException extends Exception{
    public CustomException(String message) {
        super(message);
    }
}
at ang klase ng Tugon
public class Response {

    private String message;

    public Response() {
    }

    public Response(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
At ngayon, gagawa ako ng isang trick sa aking mga tainga at ibibigay ang sahig kay Alexey Kutepov, sa kanyang artikulong Exception Handling sa Spring Controllers, sasabihin niya sa amin kung paano punan ang mga file na ito ng tamang nilalaman. Magbasa nang dahan-dahan, maingat na kopyahin ang lahat ng mga halimbawa sa iyong proyekto, tumakbo at subukan sa Postman. Kung sa artikulo ni Alexey ang sumusunod na linya ay nagtaas ng mga tanong para sa iyo: produces = APPLICATION_JSON_VALUE , pagkatapos ay malaman na ito ay walang kinalaman sa exception handling, sinasabi nito na bilang default ang lahat ng mga pamamaraan ng controller na ito ay magbabalik ng JSON. Kung kinakailangan, sa isang partikular na paraan, ang halagang ito ay maaaring i-override sa isa pang MediaType. Kung nabasa mo na ito, magpatuloy. Tinatalakay ng artikulo sa itaas ang iba't ibang opsyon para sa mga humahawak. Ang pinaka-kakayahang umangkop sa kanila: @ControllerAdvice - pinapayagan ka nitong baguhin ang parehong code at ang katawan ng karaniwang tugon kung sakaling magkaroon ng error. Bilang karagdagan, pinapayagan ka nitong pangasiwaan ang maraming mga pagbubukod nang sabay-sabay sa isang paraan. Ngunit hindi lang iyon, kung magbabasa ka pa, makakakuha ka ng pinahusay na @ControllerAdvice na ganap na walang bayad. Gumawa tayo ng ilang gawaing paghahanda: Gusto kong ipakita ng tugon ang parehong custom at karaniwang mga mensahe ng error. Para magawa ito, gumawa tayo ng pagbabago sa klase ng Response : magdagdag ng isa pang field
private String debugMessage;
Gumawa tayo ng karagdagang constructor:
public Response(String message, String debugMessage) {
    this.message = message;
    this.debugMessage = debugMessage;
}
at huwag kalimutang gumawa ng Getter at Setter para sa bagong field. Ngayon sa punto. Sumulat tayo ng isa pang controller:
@RestController
public class Example7Controller {
    @GetMapping(value = "/testExtendsControllerAdvice")
    public ResponseEntity<?> testExtendsControllerAdvice(@RequestBody Response response) {
        return  ResponseEntity.ok(response);
    }
}
Subukan natin sa postman: Ipadala ang JSON sa http://localhost:8080/testExtendsControllerAdvice
{
    "message": "message"
}
Bilang tugon makakatanggap kami ng status na 200 at isang katawan
{
    "message": "message",
    "debugMessage": null
}
Ngayon, maliwanag na hindi tamang JSON ang ipapadala namin
{
    11"message": "message"
}
Bilang tugon, makakatanggap kami ng status na 400 (kung nakalimutan mo ang ibig sabihin nito, hanapin ito sa Internet) at isang walang laman na katawan ng pagtugon. Syempre walang natutuwa dito, ipaglaban natin. Dati, nilikha namin ang @ControllerAdvice mula sa simula, ngunit sa Spring Boot mayroong isang template - ResponseEntityExceptionHandler . Nakahawak na ito ng maraming exception, halimbawa: NoHandlerFoundException , HttpMessageNotReadableException , MethodArgumentNotValidException at iba pa. Ang klase na ito ay humahawak ng mga error. Mayroon itong isang grupo ng mga pamamaraan, ang mga pangalan ay batay sa prinsipyo ng handle + exception name. Kung gusto naming hawakan ang ilang pangunahing pagbubukod, pagkatapos ay magmana kami mula sa klase na ito at i-override ang gustong paraan . I-finalize natin ang default na advisory class
@ControllerAdvice
public class DefaultAdvice extends ResponseEntityExceptionHandler {//унаследовались от обработчика-заготовки

    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Response> handleException(BusinessException e) {
        Response response = new Response(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.OK);
    }
//Небольшое отступление: В обработчике выше, обратите внимание на HttpStatus.OK,
//он может быть и HttpStatus.BAD_REQUEST or другим, тут ограничений нет,
//попробуйте поменять статусы и потестить этот обработчик


    @Override//переопределor метод родительского класса
    protected ResponseEntity<Object> handleHttpMessageNotReadable
            (HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        Response response = new Response("Не правильный JSON",ex.getMessage());
        return new ResponseEntity<>(response, status);
    }
}
Tulad ng napansin mo, ang handler na responsable para sa HttpMessageNotReadableException ay na-override . Ang pagbubukod na ito ay nangyayari kapag ang katawan ng kahilingan na dumarating sa paraan ng controller ay hindi nababasa - halimbawa, maling JSON. Ang paraan ng handleHttpMessageNotReadable () ay responsable para sa pagbubukod na ito . Muli tayong humiling gamit ang maling JSON: sa http://localhost:8080/testExtendsControllerAdvice
{
    11"message": "message"
}
Nakatanggap kami ng tugon na may code 400 (Bad Request) at ang katawan:
{
    "message": "Не правильный JSON",
    "debugMessage": "JSON parse error: Unexpected character ('1' (code 49)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('1' (code 49)): was expecting double-quote to start field name\n at [Source: (PushbackInputStream); line: 2, column: 6]"
}
Ngayon ang tugon ay naglalaman hindi lamang ng tamang code, kundi pati na rin ng katawan na may mga mensaheng nagbibigay-kaalaman. Tingnan natin kung paano ito gumagana sa tamang Kahilingan ng JSON:
{
    "message": "message"
}
Natanggap namin ang sagot:
{
    "message": "message",
    "debugMessage": null
}
Sa totoo lang, hindi ko gusto na ang tugon ay naglalaman ng isang field na may halagang null , mabilis naming ayusin iyon ngayon. Pumunta sa klase ng Response at maglagay ng anotasyon sa kinakailangang field
@JsonInclude(JsonInclude.Include.NON_NULL)
private String debugMessage;
I-restart namin ang proyekto, gawin muli ang nakaraang kahilingan, at sa tugon ay nakukuha namin ang:
{
    "message": "message"
}
Salamat sa @JsonInclude(JsonInclude.Include.NON_NULL) annotation , isasama lang ang field na ito sa tugon kung tutukuyin namin ito. Ang @JsonInclude ay kasama sa library ng anotasyon ng Jackson , lubhang kapaki-pakinabang na malaman kung ano ang magagawa nito. Narito ang dalawang artikulong mapagpipilian: Mga anotasyon ng Jackson. Isinalin ng may-akda, ngunit hindi nakumpleto ang pagsasalin ; Mahusay ang ginagawa ng Google Translit. Pagpapatunay Kinakailangang dagdagan ang paksang ito ng isang konsepto tulad ng pagpapatunay. Sa madaling salita, ito ay isang tseke na ang bagay ay ang bagay na inaasahan natin. Halimbawa: kung sa application na "Direktoryo ng Telepono" kailangan nating suriin ang pagkakaroon ng mga numero ng telepono sa database, pagkatapos bago pumunta sa database, lohikal na suriin kung ang gumagamit ay nagpasok ng mga titik sa halip na mga numero. Tatlong artikulo sa pagpapatunay, sa pagtaas ng pagiging kumplikado: Pagpapatunay ng beans sa Spring Pag-set up ng pagpapatunay ng DTO sa Spring Framework Pagpapatunay ng data sa Spring Boot Tapos na tayo sa teorya para sa ngayon. Para sa pagsasanay, iminumungkahi ko ang sumusunod na gawain: Kailangan mong ipatupad ang application ng NightclubBouncer. Mga Kinakailangan: 1) Dapat tanggapin ng application ang JSON bilang input at sumulat sa database. Halimbawa ng JSON:
{
    "name": "Katy Perry"
    “status”:super star”
}
At ang katawan ng tugon ay dapat maglaman ng sumusunod na inskripsiyon: Maligayang pagdating + pangalan ! 2) Dapat ipatupad ng application ang mga sumusunod na pamamaraan: - Paglabas ng record sa pamamagitan ng id mula sa database patungo sa kliyente (Postman). - pagtanggal ng record ayon sa field: name . 3) Ang pagmamapa mula sa dto layer hanggang sa entity at pabalik ay dapat ipatupad . 4) Ang application ay dapat maghagis ng KickInTheAssException error (kailangan mo itong i-develop mismo) kung ang status field sa papasok na JSON ay hindi katumbas ng: super star 5) Ang KickInTheAssException error ay dapat pangasiwaan ng ControllerAdvice , at ang response body ay dapat maglaman ng mensahe: “Huwag mo na akong makitang muli dito! Ang status ng tugon ay dapat na 400. 6) Standard error EntityNotFoundException , na nangyayari, halimbawa, kung si Katy Perry lang ang dumating sa club at nag-save sa database na may id = 1 , at tinawag mo ang "display record by id" na paraan at gusto upang ipakita ang record na may id = 2 , na wala sa database. Ang error na ito ay dapat pangasiwaan ng isang overridden na paraan ng ResponseEntityExceptionHandler class , kung alin ang nasa iyo upang malaman ang iyong sarili. Ang tugon ay dapat na may naaangkop na katayuan. 7) Gawin ang pagpapatunay: isang simpleng opsyon - ang mga field ng JSON ay hindi dapat null, o mas mahirap, ang field na "pangalan" ay dapat na binubuo ng dalawang salita ng alpabetong Latin at pareho silang dapat magsimula sa malaking titik. Ang mga di-wastong halaga ay dapat magtapon ng isang pagbubukod, hawakan ito sa anumang paraan, i-print ang naaangkop na code ng error at mensahe ng error: Walang pagpapatunay. At ipatupad ang lahat ng ito nang hindi gumagamit ng Lombok library, huwag isama ito bilang isang dependency ng proyekto 😅
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION