Անոտացված @Controller
և @ControllerAdvice
ունեցող կլասերը կարող են ունենալ մեթոդներ, որոնք նշված են @ExceptionHandler
-ով՝ բացառությունները կարգավորելու համար, ինչպես ցույց է տրված հետևյալ օրինակով:
@Controller
public class SimpleController {
// ...
@ExceptionHandler
public ResponseEntity<String> handle(IOException ex) {
// ...
}
}
@Controller
class SimpleController {
// ...
@ExceptionHandler
fun handle(ex: IOException): ResponseEntity<String> {
// ...
}
}
Բացառությունը կարող է համընկնել բարձր մակարդակի տարածված բացառության հետ (օրինակ, ուղղակիորեն գեներացված IOException
) կամ կարող է լինել ներսում որպես պատճառ բացառության-փաթեթի մեջ (օրինակ, IOException
, որը փաթեթված է IllegalStateException
ներսում): Սկսած 5.3-ից, դա կարող է համընկնել ցանկացած մակարդակի պատճառների վրա, մինչդեռ նախկինում միայն անմիջական պատճառը էր հաշվի առնվում:
Համընկնող բացառությունների տեսակների համար ցանկալի է հայտարարել նպատակային բացառությունը որպես մեթոդի արգումենտ, ինչպես ցույց է տրված նախորդ օրինակում: Մի քանի բացառությունների համընկնելու դեպքում, սովորաբար գերադասելի է է արմատային բացառության համընկնումը, քան պատճառի բացառության համընկնումը: Հատկապես, ExceptionDepthComparator
-ը օգտագործվում է բացառությունները տեսակավորելու նրանց խորությամբ գեներացված բացառության տիպից:
Բացի այդ, անոտացիայի հայտարարումը կարող է սահմանափակել բացառությունների տեսակներ, որոնք պետք է համընկնեն, ինչպես ցույց է տրված հետևյալ օրինակում:
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(IOException ex) {
// ...
}
@ExceptionHandler(FileSystemException::class, RemoteException::class)
fun handle(ex: IOException): ResponseEntity<String> {
// ...
}
Կարող եք նույնիսկ օգտագործել հատուկ բացառությունների տեսակների ցանկ շատ ընդհանուր արգումենտային ստորագրությամբ, ինչպես ցույց է տրված հետևյալ օրինակում:
@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(Exception ex) {
// ...
}
@ExceptionHandler(FileSystemException::class, RemoteException::class)
fun handle(ex: Exception): ResponseEntity<String> {
// ...
}
Արմատային և պատճառի բացառությունների համընկնումների միջև տարբերությունը կարող է զարմացնել:
IOException
-ի օրինակում, որը ցույց է տրված վերևում, մեթոդը ընդհանուր առմամբ կանչվում է FileSystemException
կամ RemoteException
փաստացի օրինակի օգտագործմամբ որպես արգումենտ, քանի որ երկուսն էլ ընդլայնվում են IOException
-ից: Սակայն, եթե ցանկացած նման համընկնող բացառություն տարածվում է փաթեթող բացառության ներսում, որը ինքն իրեն պահում է որպես IOException
, ապա փոխանցվող բացառության օրինակը հենց այդ փաթեթող բացառությունն է:
handle(Exception)
տարբերակում աշխատանքի տրամաբանությունը նույնիսկ ավելի պարզ է: Կանչվում է փաթեթող բացառությամբ փաթեթավորման սցենարում, իսկ փաստացի համընկնող բացառությունը կարող է գտնվել ex.getCause()
-ի օգնությամբ այս դեպքում: Փոխանցված բացառությունը հանդիսանում է FileSystemException
կամ RemoteException
փաստացի օրինակը միայն այն դեպքում, եթե դրանք գեներացվում են որպես բարձր մակարդակի բացառություններ:
Հաճախ առաջարկվում է որքան հնարավոր է կոնկրետ լինել արգումենտների ստորագրությունում՝ նվազեցնելու համար արմատային և պատճառի բացառությունների տեսակների միջև անհամապատասխանության հավանականությունը: Հաշվի առեք մի քանի համընկնումներով մեթոդը բաժանելու առանձին մեթոդներին, որոնք անոտացված են @ExceptionHandler
և որոնցից յուրաքանչյուրն ունի մեկ բացառության հատուկ տեսակ՝ իր ստորագրությամբ:
Մի քանի @ControllerAdvice
անոտացիաների կոնֆիգուրացիայում մենք խորհուրդ ենք տալիս հայտարարել հիմնական արմատային բացառությունների քարտեզները @ControllerAdvice
անոտացիայով համապատասխան առաջնահերթության կարգով: Թեպետ արմատային բացառությունների համընկնումը գերադասելի է, քան պատճառի բացառության համընկնումը, որոշումը տեղի է ունենում տվյալ կոնտրոլերի կամ @ControllerAdvice
-ով անոտացված դասի մեթոդների շրջանում: Սա նշանակում է, որ պատճառի համընկնումը @ControllerAdvice
-ով բարձր առաջնահերթությամբ նախընտրելի է ցանկացած համընկնումից (օրինակ, արմատային) @ControllerAdvice
-ով ավելի ցածր առաջնահերթությամբ:
Վերջապես, @ExceptionHandler
անոտացված մեթոդի իրականացումը կարող է հրաժարվել զբաղվել տվյալ բացառության օրինակով՝ կրկին գեներացնելով այն սկզբնական ձևով: Սա օգտակար է այն դեպքերում, երբ ձեզ հետաքրքրում են բացառապես արմատային մակարդակի կամ որոշակի կոնտեքստում համընկնումների, որոնք չեն կարող որոշվել ստատիկորեն, համընկնումները: Կրկնակի գեներացված բացառությունը տարածվում է մնացած լուծման շղթայի ընթացքում, կարծես թե առաջինը չէր համընկնում @ExceptionHandler
-ով նշված մեթոդի հետ:
Spring MVC-ում @ExceptionHandler
անոտացիայով մեթոդների աջակցությունը կառուցված է DispatcherServlet
մակարդակում, HandlerExceptionResolver մեխանիզմի վրա:
Մեթոդի արգումենտներ
@ExceptionHandler
անոտացված մեթոդները աջակցում են հետևյալ արգումենտներին:
Մեթոդի արգումենտներ | Նկարագրություն |
---|---|
Բացառության տեսակ |
Վերահասցադրում է գեներացված բացառությանը: |
|
Տրամադրում է մուտք դեպի այն կոնտրոլերի մեթոդը, որը գեներացրել է բացառությունը: |
|
Տիպիզացված մուտք դեպի հարցման պարամետրերը և հարցման և սեսիայի ատրիբուտները՝ առանց օգտվելու անմիջականորեն Servlet API-ից: |
|
Ընտրեք հարցման կամ պատասխանի որևէ կոնկրետ տեսակ (օրինակ, |
|
Ապահովում է սեսիայի առկայությունը: Հետևաբար, այդպիսի արգումենտը երբեք չի կարող լինել |
|
Ընթացիկ վավերացված օգտատերը՝ հնարավոր է, |
|
Հարցման HTTP մեթոդը: |
|
Հարցման ընթացիկ տեղայնությունները՝ որոշված ամենա կոնկրետ մատչելի |
|
Ժամային գոտին, կապված ընթացիկ հարցման հետ, որոշված |
|
Ապահովում է մուտք դեպի բուն պատասխանի մարմինը, ինչպես նախատեսված է Servlet API-ի միջոցով: |
|
Ապահովում է մուտք դեպի մոդելի՝ սխալի պատասխանը մատչելի դարձնելու համար: Միշտ դատարկ է: |
|
Նշեք այն ատրիբbutները, որոնք օգտագործվում են վերահղման դեպքում՝ (որոնք ավելացվում են հարցման տողում) և flash ատրիբուտները ժամանակավոր պահպանման համար մինչև վերահղման հարցման ստացավը: |
|
Նպատակ ունի ապահովել մուտք դեպի սեսիայի ցանկացած ատրիբուտ, ի տարբերություն մոդելի ատրիբուտների, որոնք պահվում են սեսիայով ՝ հասկանալի դարձնելու համար |
|
Նպատակ ունի ապահովել մուտք դեպի հարցման ատրիբուտները: |
Վերադարձվող արժեքներ
@ExceptionHandler
անոտացիայով մեթոդները աջակցում են հետևյալ վերադարձվող արժեքներին:
Return value | Նկարագրություն |
---|---|
|
Վերադարձվող արժեվորումը փոխակերպվում է |
|
Վերադարձվող արժեվորմա նշում է, որ ամբողջ պատասխանը (ներառյալ HTTP վերնագրերը և մարմինը) փոխակերպվում է |
|
Դիտման անունը, որը պետք է ճանաչվի |
|
|
|
Ատրիբուտներ, որը պետք է ավելացնենք անուղղակի մոդելին՝ դիտման անունով, անուղղակի որոշված |
|
Ատրիբուտը, որը ավելացված է մոդելում՝ դիտման անունով, անուղղակի սահմանված Խնդրում ենք նկատի ունենալ, որ |
|
Օգտագործված է տեսքի և մոդելի ատրիբուտներին և, անհրաժեշտության դեպքում, պատասխանի կարգավիճակին: |
|
Համարվում է, որ Եթե վերը նշվածներից մեկը ճիշտ չէ, ապա |
Ցանկացած այլ վերադարձվող արժեք |
Եթե վերադարձվող արժեքը չի համապատասխանեցվում վերոնշյալներից ոչ մեկին և պարզ տիպ չէ (ինչպես ցույց է տրված BeanUtils#isSimpleProperty), ապա դա կանխադրված է որպես մոդելի ատրիբուտ, որը պետք է ավելացնենք մոդելին: Եթե դա պարզ տիպ է, ապա այն մնում է չվճռված: |
Բացառությունների կառավարումն REST API-ի ներսում
REST ծառայությունների ընդհանուր պահանջն է սխալի տեղեկատվությունը ներառել պատասխանի մարմնում: Spring Framework-ը ինքնաբերաբար դա չի կատարում, քանի որ սխալի տեղեկատվութան ներկայացումը պատասխանի մարմնում կախված է կոնկրետ հավելվածից: Սակայն, @RestController
անոտացիայով մեթոդները կարող են օգտվել @ExceptionHandler
-ով նշված մեթոդների՝ վերադարձվող արժեքով ResponseEntity
կարգավիճակի և պատասխանի մարմնի կարգավորման համար: Այդպիսի մեթոդները նաև կարող են հայտարարել @ControllerAdvice
-ով անոտացված դասերում, որպեսզի դրանք կիրառվեն գլոբալ:
Հավելվածներ, որոնք իրականացնում են գլոբալ բացառությունների կառավարում՝ սխալի մանրամասն նկարագրությամբ պատասխանի մարմնում, պետք է հաշվի առնել ResponseEntityExceptionHandler
ընդլայնման հնարավորությունը, որը ապահովում է բացառությունների կարգավորում Spring MVC-ում և տրամադրում է միջակներ՝ պատասխանի մարմինը կարգավորելու համար: Այս նպատակի համար ստեղծեք ResponseEntityExceptionHandler
իջած դաս, այն.annotate @ControllerAdvice
ընտանիքին, վերախմբագրեք անհրաժեշտ մեթոդները և հայտարարեք այն որպես Spring bean:
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ