Ту метавонӣ аннотатсияи @RequestMapping
-ро истифода барӣ барои намоиши дархостҳо ба методҳои контроллер. Он як қатор атрибутҳо барои мувофиқати URL-ҳо, HTTP-методҳо, параметрҳои дархост, сарлавҳаҳо ва намудҳои маълумот дорад. Метавонӣ онро дар сатҳи синфҳо барои ифодаи намоишҳои умумӣ ё дар сатҳи методҳо барои маҳдуд кардан ба намоиши мушаххаси нуқтаи ниҳоӣ истифода барӣ.
Вариантҳои махсуси HTTP-методҳо барои кӯтоҳ кардани аннотатсияи @RequestMapping
вуҷуд доранд:
-
@GetMapping
-
@PostMapping
-
@PutMapping
-
@DeleteMapping
-
@PatchMapping
Кӯтоҳкунӣ аннотатсияҳои кастом мебошанд, ки барои ҳамин пешниҳод шудаанд, ки эҳтимолан аксари методҳои контроллер бояд ба HTTP-методи мушаххас мувофиқат карда шаванд, на истифодаи аннотатсияи @RequestMapping
, ки ба ҳама HTTP-методҳо мувофиқат мекунад. Барои ифодаи намоишҳои умумӣ дар сатҳи синф, ҳамоно @RequestMapping
зарур аст.
Намунаи зерин намоишҳоро дар сатҳи намудҳо ва методҳо дорад:
@RestController
@RequestMapping("/persons")
class PersonController {
@GetMapping("/{id}")
public Person getPerson(@PathVariable Long id) {
// ...
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public void add(@RequestBody Person person) {
// ...
}
}
@RestController
@RequestMapping("/persons")
class PersonController {
@GetMapping("/{id}")
fun getPerson(@PathVariable id: Long): Person {
// ...
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun add(@RequestBody person: Person) {
// ...
}
}
Шаблонҳои URI-идентификаторҳо
Методҳо, ки бо @RequestMapping
аннотатсия шудаанд, метавонанд бо истифода аз шаблонҳои URL-ҳо намоиш дода шаванд. Ду алтернатива мавҷуд аст:
-
PathPattern
- шаблони пешакӣ парсшуда, ки бо роҳи URL-ҳо мувофиқат карда, ҳамчунPathContainer
низ парс шудааст. Ин ҳалли таҳияшуда барои истифода дар муҳити интернетӣ бо параметрҳои кодгузорӣ ва роҳҳо самаранок кор мекунад, инчунин мувофиқати самаранокро таъмин мекунад. -
AntPathMatcher
- мувофиқат кардани шаблонҳои стринг бо роҳи стринг. Ин ҳалли аслист, ки инчунин дар конфигуратсияи Spring барои интихобҳои захираҳо дар classpath, дар системаи файлӣ ва ҷойҳои дигар истифода мешавад. Он камтар самаранок аст ва ворид кардани роҳи стрингу кор бо масоили кодгузорӣ ва дигар мушкилот бо адресҳои URL-ҳоро душвортар мекунад.
PathPattern
ҳалли тавсияшуда барои веб-барномаҳо аст ва ин ягона вариант ҳангоми кор дар Spring WebFlux аст. То версияи 5.3 AntPathMatcher
ягона вариант ҳангоми кор дар Spring MVC буд ва ҳамчун пешфарз боқӣ мемонад. Аммо PathPattern
дар конфигуратсияи MVC фаъол кардан мумкин аст.
PathPattern
ҳамон синтаксиси шаблонҳоро, ки AntPathMatcher
дастгирӣ мекунад, дастгирӣ менамояд. Илова бар ин, он инчунин шаблони захираро дастгирӣ менамояд, ба монанди {*spring}
, барои мувофиқат ба 0 ё зиёда сегментҳои роҳ дар охири роҳ. PathPattern
инчунин истифодаи аломати **
-ро барои мувофиқат кардан бо сегментҳои зиёди роҳ маҳдуд менамояд, чунон ки он танҳо дар охири шаблон иҷозат дода шудааст. Ин имкон медиҳад, ки ҳолатҳои ношиносӣ ҳангоми интихоби беҳтарин шаблони мувофиқат барои дархости додашуда пешгирӣ карда шаванд. Синтаксиси пурраи шаблонҳо дар қисмҳои бахшида ба PathPattern ва AntPathMatcher оварда шудааст.
Баъзе намунаҳои шаблонҳо:
-
"/resources/ima?e.png"
– мувофиқат кардан бо як аломат дар сегменти роҳ -
"/resources/*.png"
– мувофиқат кардан бо 0 ё зиёда аломатҳо дар сегменти роҳ -
"/resources/**"
– мувофиқат кардан бо сегментҳои зиёди роҳ -
"/projects/{project}/versions"
– мувофиқат кардан бо сегменти роҳ ва сабт кардани он ҳамчун тағйирёбанда -
"/projects/{project:[a-z]+}/versions"
– мувофиқат кардан ва захира кардани тағйирёбанда бо истифода аз эвф сафҳибеевар мадакоро баҳар морад.
Ба тағйирёбандаҳои захирашудаи URI-идентификаторҳо бо истифода аз аннотатсияи @PathVariable
дастрасӣ ёфтан мумкин аст. Масалан:
@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
@GetMapping("/owners/{ownerId}/pets/{petId}")
fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
// ...
}
Ту метавонӣ тағйирёбандаҳои URI-идентификаторро дар сатҳи синф ва методҳо эълон кунӣ, тавре ки дар намунаи зерин нишон дода шудааст:
@Controller
@RequestMapping("/owners/{ownerId}")
public class OwnerController {
@GetMapping("/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
}
@Controller
@RequestMapping("/owners/{ownerId}")
class OwnerController {
@GetMapping("/pets/{petId}")
fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
// ...
}
}
Тағйирёбандаҳои URI-идентификаторҳо ба таври автоматӣ ба навъи мувофиқ табдил дода мешаванд, ё ки TypeMismatchException
тавлид карда мешавад. Навъи оддӣ(int
, long
, Date
ва ғайра) ба таври пешфарз дастгирӣ шуда, вале метавонӣ барои ҳар навъи дигари маълумот вобастаҳои дастгирикунандаро сабти ном кунӣ. Бакта "DataBinder"
ва бахши "Преобразованияи Навъ"
Метавонӣ ба таври равшан номҳои тағйирёбандаҳои URI-идентификаторҳоро таъин кунӣ (масалан, @PathVariable("customId")
), лекин метавонед ин маълумотро нишон надед, агар номҳо яксон бошанд ва коди шумо бо истифода аз маълумоти debugging ё бо парчами компилятор -parameters
дар Java 8 компил карда мешавад.
Синтаксис {varName:regex}
тағйирёбандаи URI-идентификаторро бо истифода аз эвф масоили вадирлот дардает, ки синтаксис {varName:regex}
дорад. Масалан, агар URL-адрес "/spring-web-3.0.5.jar"
бошад, методи зерин ном, версия ва васеънамоии файлро мегирад:
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
// ...
}
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
fun handle(@PathVariable name: String, @PathVariable version: String, @PathVariable ext: String) {
// ...
}
Шаблонҳои роҳҳои URI-идентификаторҳо метавонанд инчунин ҷойгиркуниҳои дохилиии ${…}
-ро, ки бо PropertySourcesPlaceholderConfigurer
дар манбаъҳои маҳалли, системӣ, манбаъҳои хосияти муҳит ва ғайра шинохта мешаванд, дар вақти иҷро дар бар гиранд. Метавонии инро барои параметргузории URL асосӣ дар асоси як конфигуратсияи беруна истифода барӣ.
Муқоисаи Шаблонҳо
Агар URL-адрес ба якчанд шаблон мувофиқат кунад, илоҷанак бояд интихоби мувофиқтаринро кард. Ин кор бо яке аз усулҳои зерин вобаста ба он, ки PathPattern
-и синтаксисӣ парсшуда иҷозат шудааст ё не, анҷом дода мешавад:
Ҳар дуе ба ташкили шаблонҳо кӯмак мерасонад, ки бо конкретии бештар онҳо дар болои рӯйхат пайдо мешаванд. Шаблон камтар конкретӣ мебошад, агар дар он камтар тағйирёбандаҳои URI-идентификатор (баробар ба 1), подстановочные аломатҳои ягона (баробар ба 1) ва подстановочные аломатҳои дугона (баробар ба 2) вуҷуд дошта бошад. Агар нишондиҳандаҳо баробар бошанд, шаблони дарозтар интихоб мешавад. Агар нишондиҳандаҳо ва дарозӣ баробар бошад, шаблоне, ки бештар тағйирёбандаҳои URI-идентификатор дошта бошад, аз подстановочные аломатҳо интихоб мешавад.
Шаблони намоишии пешфарз (/**
) аз ҳисоб баромада аст ва дар рӯйхат ҳамеша охирин ҷойгир мешавад. Илова бар ин, шаблонҳое, ки префиксҳо доранд (мисли /public/**
), назар ба дигар шаблонҳое, ки подстановочные аломатҳои дугона надоранд, камтар конкретӣ ба ҳисоб мераванд.
Барои маълумотҳои пурра ба пайвандҳои таъминшудаи тавсифоти компараторҳои шаблонҳо муроҷиат намоед.
Мувофиқати Суффикс
Аз версияи 5.3, Spring MVC бо суффикси .*
ба таври пешфарз шаблонҳои мувофиқат намекунад. Агар контроллере, ки дар /person
мувофиқат карда шудааст, инчунин ба таври ғайримустақим бо /person.*
мувофиқат мекунад. Аз ин рӯ, васеъкунии роҳҳо дигар барои тафсири намуди мундариҷаи талабшуда барои посух истифода намешавад – масалан, /person.pdf
, /person.xml
ва ғайра.
Истифодаи васеъкуниҳои файл ба ин тарз зарур буд, вақте ки браузерҳо сарлавҳаҳои Accept
мефиристоданд, ки онҳоро пай дар пай тафсир кардан душвор буд. Ҳоло ба ин зарурат нест ва истифодаи сарлавҳаи Accept
бояд интихоби афзалиятнок бошад.
Бо гузашти вақт, истифодаи васеъкуниҳои номҳои файл ба як қатор сабабҳо мушкилот эҷод кард. Ин метавонад ҳангоми истифодаи тағйирёбандаҳои URI-идентификатор, параметрҳои роҳ ва кодгузории URI-идентификаторҳо боиси ношиносӣ гардад. Тафаккури дурустии авторизатсия ва амният дар асоси URL (бо тафсилот ба бахши зерин нигаред) низ мураккабтар шудааст.
Барои комилан хомӯш кардани истифодаи васеъкунии роҳ дар версияҳои пеш аз 5.3, корҳои зеринро гузоред:
-
useSuffixPatternMatching(false)
-
favorPathExtension(false)
Доштани роҳи талаб кардани намудҳои мундариҷа, ки аз сарлавҳаи "Accept"
фарқ мекунад, метавонад, масалан ҳангоми ворид кардани URL дар браузер, муфид бошад. Стратегияи параметрҳои дархост ҳамчун алтернативаи бехавфи васеъкунии роҳ истифода мешавад. Агар ба шумо дастрасӣ ба васеъкуниҳои файл лозим бошад, фикр кунед, ки онҳоро бо рӯйхати васеъкуниҳои аниқ сабти номшуда тавассути хосияти mediaTypes
барои ContentNegotiationConfigurer маҳдуд кунед.
Мувофиқати Суффикс ва RFD
Вектори ҳамлаи зеркашии файлҳои инъикосшуда (Reflected File Download/RFD) ба XSS шабеҳ аст, то ки он ба вуруди маълумоти дархост асос ёфтааст (масалан, параметри дархост ва тағйирёбандаи URI-идентификатор), ки дар ҷавоб инъикос ёфтааст. Аммо ба ҷои ворид кардани JavaScript дар HTML, вектори ҳамлаи RFD ба тағйири браузер ба иҷрои зеркашӣ ва коркарди ҷавоб ҳамчун скрипти иҷроишаванда пас аз зер кардани дубора асос ёфтааст.
Дар Spring MVC, методҳое, ки бо аннотатсияи @ResponseBody
нишондод шудаанд ва методҳои ResponseEntity
дар хатар қарор доранд, чунки онҳо метавонанд намудҳои мундариҷаи гуногунро, ки муштариён метавонанд тавассути васеъкунии роҳҳои URL талаб кунанд, визуализатсия кунанд. Хомӯш кардани мувофиқати суффикс ва истифодаи васеъкунии роҳҳо барои мувофиқати мундариҷа хатари онро коҳиш медиҳад, вале барои пешгирии ҳамлаҳои RFD кофӣ нест.
Барои пешгирӣ кардани ҳамлаҳои RFD, пеш аз визуализатсияи бадани ҷавоб Spring MVC сарлавҳаи Content-Disposition:inline;filename=f.txt
-ро илова мекунад, то ки фикси бехавфи файли зеркашии пешниҳодшуда пешниҳод шавад. Ин танҳо дар ҳолати ворид нашудани URL васеъкунии файл мешавад, ки ҳамчун бехавф иҷозат дода нашудааст ва барои мувофиқати мундариҷа аниқ сабти ном шуда наомадааст. Аммо ин метавонад таъсири тарафӣ дошта бошад, агар URL алоқаҳои мустақиман дар браузер ворид шаванд.
Бисёр васеъкуниҳои умумии роҳҳо аз пешфарз ҳамчун бехавф иҷозат дода шудаанд. Барномаҳо бо амалишавии кастомии HttpMessageConverter
метавонанд васеъкуниҳои файлро барои мувофиқати мундариҷа аниқ сабти ном кунанд, то аз иловаи сарлавҳаи Content-Disposition
барои ин васеъкуниҳо пешгирӣ кунанд.
Барои маслиҳатҳои иловагӣ вобаста ба RFD, ба "CVE-2015-5211" нигаред.
Намудҳои мундариҷаи қабулшаванда
Метавони дастаи муайяни дархостҳоро дар асоси Content-Type
хосият маҳдуд кардунам то ки онҳо ба Content-Type
дархост мувофиқат кунанд, тавре ки дар намунаи зерин нишон дода шудааст:
@PostMapping(path = "/pets", consumes = "application/json")
public void addPet(@RequestBody Pet pet) {
// ...
}
- Истифодаи атрибут
consumes
барои маҳдуд кардани диапазони намоиш бо намуди мундариҷа.
@PostMapping("/pets", consumes = ["application/json"])
fun addPet(@RequestBody pet: Pet) {
// ...
}
- Истифодаи атрибут
consumes
барои маҳдуд кардани диапазони намоиш бо намуди мундариҷа.
Атрибут consumes
инчунин изҳори манфиҳоро дастгирӣ мекунад – масалан, !text/plain
маънои ҳар як намуди мундариҷаи дигарро аз text/plain
дорад.
Метавони атрибут consumes
-ро дар сатҳи синф эълон кард. Аммо, дар муқоиса бо аксари дигар атрибутҳои намоиши дархост, ҳангоми истифода дар сатҳи синф, атрибут consumes
дар сатҳи метод бештар ивази эълони синф мешавад, на илова кардани он.
MediaType
константаҳо барои намудҳои маъмулан истифодашавандаи миёнаравии маълумотро таъмин мекунад, аз қабили
APPLICATION_JSON_VALUE
ва
APPLICATION_XML_VALUE
.
Намудҳои мундариҷае, ки тавлид мешаванд
Метавон дастаи муайяни дархостҳоро дар асоси сарлавҳаи дархости Accept
ва рӯйхати намудҳои мундариҷа, ки методи контроллер тавлид мекунад, маҳдуд кард, тавре ки дар намунаи зерин нишон дода шудааст:
@GetMapping(path = "/pets/{petId}", produces = "application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId) {
// ...
}
- Истифодаи атрибут
produces
барои маҳдуд кардани диапазони намоиш бо намуди мундариҷа.
@GetMapping("/pets/{petId}", produces = ["application/json"])
@ResponseBody
fun getPet(@PathVariable petId: String): Pet {
// ...
}
- Истифодаи атрибут
produces
барои маҳдуд кардани диапазони намоиш бо намуди мундариҷа.
Намуди миёнаравии маълумот метавонад маҷмӯи символҳоро муайян кунад. Изҳори манфиҳо дастгирӣ мешавад – масалан, !text/plain
маънои ҳар намуди мундариҷаро, ки аз "text/plain" фарқ мекунад, дорад.
Метавон атрибут produces
-ро дар сатҳи синф эълон кард. Аммо, дар муқоиса бо аксари дигар атрибутҳои намоиши дархост, ҳангоми истифода дар сатҳи синф атрибут produces
дар сатҳи метод бештар ивази эълони синф мешавад, на илова кардани он.
MediaType
константаҳо барои намудҳои маъмулан истифодашавандаи миёнаравии маълумотро таъмин мекунад, аз қабили
APPLICATION_JSON_VALUE
ва
APPLICATION_XML_VALUE
.
Параметрҳо, сарлавҳаҳо
Метавон дастаи муайяни дархостҳоро дар асоси шароити параметрҳои дархост маҳдуд кард. Ту метавонӣ мавҷудиятро санҷӣ, набудани параметри дархост(myParam
), ё муайян кадани арзиш(myParam=myValue
). Дар намунаи зерин нишон дода шудааст, ки чӣ тавр барои санҷиши мавҷудияти арзиши муайян:
@GetMapping(path = "/pets/{petId}", params = "myParam=myValue")
public void findPet(@PathVariable String petId) {
// ...
}
- Санҷиш, ки
myParam
ба арзишиmyValue
баробар аст.
@GetMapping("/pets/{petId}", params = ["myParam=myValue"])
fun findPet(@PathVariable petId: String) {
// ...
}
- Санҷиш, ки
myParam
ба арзишиmyValue
баробар аст.
Ҳамон тавр, шароити сарлавҳаи дархост низ метавонад истифода шавад, тавре ки дар намунаи зерин нишон дода шудааст:
@GetMapping(path = "/pets", headers = "myHeader=myValue")
public void findPet(@PathVariable String petId) {
// ...
}
- Санҷиш, ки
myHeader
ба арзишиmyValue
баробар аст.
@GetMapping("/pets", headers = ["myHeader=myValue"])
fun findPet(@PathVariable petId: String) {
// ...
}
Content-Type
ва
Accept
-ро бо шароити сарлавҳаҳо мувофиқат кунӣ, аммо беҳтар аст, ки ба ҷои ин consumes ва produces истифода шавад.
HTTP-методҳои HEAD, OPTIONS
@GetMapping
(ва @RequestMapping(method=HttpMethod.GET)
) HTTP-методи HEAD-ро барои мувофиқати дархостҳо шаффоф дастгирӣ мекунад. Ба методҳои контроллер ягон тағйирот ворид кардан лозим нест. Ҳамчунон, функсияи обёркунии ҷавоб, ки дар javax.servlet.http.HttpServlet
таҷриба шудааст, сарлавҳаи Content-Length
-ро ба миқдори байтҳои сабтшуда насб мекунад (бе амалан сабт кардан ба ҷавоб).
@GetMapping
(ва @RequestMapping(method=HttpMethod.GET)
) ба таври ғайримустақим ба HTTP-методи HEAD мувофиқат мекунад ва онро дастгирӣ мекунад. Дархости HTTP-методи HEAD ба тавре, ки HTTP-методи GET коркард мешавад, коркард карда мешавад, ба истиснои он ки ба ҷои сабт кардани бадан миқдори байтҳо ҳисоб шуда, сарлавҳаи Content-Length
насб карда мешавад.
Ба таври пешфарз HTTP-методи OPTIONS тавассути насб кардани сарлавҳаи ҷавоб Allow
ба рӯйхати HTTP-методҳое, ки дар ҳама методҳо бо аннотатсияи@RequestMapping
нишондодашуда, ки ба шаблонҳои URL мувофиқат мекунанд, коркард мешавад.
Дар ҳолати аннотатсияи @RequestMapping
бе эълони HTTP-методҳо, сарлавҳаи Allow
ба GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
насб карда мешавад. Методҳои контроллер ҳамеша бояд HTTP-методҳои дастгиришавандаро эълон кунанд (масалан, бо истифода аз вариантҳои махсуси HTTP-методҳо: @GetMapping
, @PostMapping
ва ғайра).
Ту метавонӣ методе, ки бо аннотатсияи @RequestMapping
нишондода шудааст, ба таври равшан ба HTTP-методи HEAD ва HTTP-методи OPTIONS мувофиқат кунад, аммо дар истилоҳоти умумӣ зарурати ба таври равшан барои ин вуҷуд надорад.
Кастомные аннотациях
Spring MVC истифодаи аннотацияҳои мураккабро барои намоиши дархостҳо дастгирӣ мекунад. Инҳо аннотацияхое мебошанд, ки худашон мета-аннотацияҳои @RequestMapping
мебошанд ва барои эълони дубораи подмножество ё атрибутҳои аннотацияшудаи @RequestMapping
бо мақсади бештар танг, бештар мушаххас тартиб дода шудаанд.
@GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
ва @PatchMapping
намунаҳои аннотацияхои мураккаб мебошанд. Онҳо бо мақсади пешниҳод шудаанд, ки эҳтимолан аксари методҳои контроллер бояд ба HTTP-методи мушаххас мувофиқат карда шаванд, на истифодаи аннотацияи @RequestMapping
, ки ба таври пешфарз бо ҳама HTTP-методҳо мувофиқат мекунад. Агар ба ту намунае барои аннотацияҳои мураккаб лозим бошад, бубин, ки онҳо чӣ тавр эълон шудаанд.
Spring MVC инчунин атрибутҳои намоиши дархости кастомро бо мантиқи намоиши кастом дастгирӣ мекунад. Ин варианте аст, ки ба эҷоди зерсинфи RequestMappingHandlerMapping
ва бознависии методи getCustomMethodCondition
талаб мекунад, ки дар он метавонӣ атрибути кастомро санҷӣ ва RequestCondition
худро баргардонӣ.
Явная регистрация
Ту метавонӣ методҳои обработчикро барномавӣ сабт кунӣ, ки онҳо барои сабти ном кардани динамикӣ ё ҳангоми ҳолатҳои мураккабтар, масалан, агар якчанд экземплери ҳамон обработчикро бо URL-ҳои гуногун дошта бошӣ, истифода шаванд. Дар намунаи зерин методи обработчик сабти ном шудааст:
@Configuration
public class MyConfig {
@Autowired
public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler)
throws NoSuchMethodException {
RequestMappingInfo info = RequestMappingInfo
.paths("/user/{id}").methods(RequestMethod.GET).build();
Method method = UserHandler.class.getMethod("getUser", Long.class);
mapping.registerMapping(info, handler, method);
}
}
- Шарҳ барои интегратсияи обработчик ва намоиши обработчик барои контроллерҳо.
- Тайёр кардани метамаълумоти намоиши дархост.
- Гирифтани методи обработчик.
- Илова кардани сабти ном.
@Configuration
class MyConfig {
@Autowired
fun setHandlerMapping(mapping: RequestMappingHandlerMapping, handler: UserHandler) {
val info = RequestMappingInfo.paths("/user/{id}").methods(RequestMethod.GET).build()
val method = UserHandler::class.java.getMethod("getUser", Long::class.java)
mapping.registerMapping(info, handler, method)
}
}
- Шарҳ барои интегратсияи обработчик ва намоиши обработчик барои контроллерҳо.
- Тайёр кардани метамаълумоти намоиши дархост.
- Гирифтани методи обработчик.
- Илова кардани сабти ном.
GO TO FULL VERSION