JavaRush /Блоги Java /Random-TG /Истифодаи JNDI дар Java
Анзор Кармов
Сатҳи
Санкт-Петербург

Истифодаи JNDI дар Java

Дар гурӯҳ нашр шудааст
Салом! Имрӯз мо шуморо бо JNDI шинос хоҳем кард. Биёед бифаҳмем, ки он чӣ гуна аст, чаро он лозим аст, он чӣ гуна кор мекунад, мо бо он чӣ гуна кор карда метавонем. Ва он гоҳ мо санҷиши воҳиди Spring Boot менависем, ки дар дохor он мо бо ҳамин JNDI бозӣ мекунем. Истифодаи JNDI дар Java - 1

Муқаддима. Хидматҳои номгузорӣ ва директория

Пеш аз ворид шудан ба JNDI, биёед бифаҳмем, ки хидматҳои номгузорӣ ва директория чист. Намунаи равшантарини чунин хидмат системаи файлӣ дар ҳама гуна компютер, ноутбук ё смартфон мебошад. Системаи файлӣ файлҳоро (ба таври аҷиб) идора мекунад. Файлҳо дар чунин системаҳо дар сохтори дарахт гурӯҳбандӣ карда мешаванд. Ҳар як файл номи пурраи беназир дорад, масалан: C:\windows\notepad.exe. Лутфан таваҷҷӯҳ намоед: номи пурраи файл ин роҳ аз ягон нуқтаи реша (диски C) ба худи файл (notepad.exe) мебошад. Гиреҳҳои мобайнӣ дар чунин занҷир директорияҳо (директорияи windows) мебошанд. Файлҳои дохor директорияҳо атрибутҳо доранд. Масалан, «Пинҳон», «Танҳо барои хондан» ва ғайра. Тавсифи муфассали чунин як чизи оддӣ ба монанди системаи файлӣ барои беҳтар фаҳмидани таърифи номгузорӣ ва хидматҳои директория кӯмак мекунад. Ҳамин тавр, хидмати ном ва директория системаест, ки харитасозии номҳои зиёдеро ба an objectҳои зиёде идора мекунад. Дар системаи файлии мо, мо бо номҳои файле, ки an objectҳоро пинҳон мекунанд, яъне худи файлҳо дар форматҳои гуногун ҳамкорӣ мекунем. Дар хидмати номгузорӣ ва директория an objectҳои номбаршуда ба сохтори дарахт ташкил карда мешаванд. Ва an objectҳои директория атрибутҳо доранд. Намунаи дигари хидмати ном ва директория DNS (Системаи номи доменӣ) мебошад. Ин система харитасозии байни номҳои домейнҳои барои инсон хондашаванда (масалан, https://javarush.com/) ва суроғаҳои IP-и бо мошин хондашаванда (масалан, 18.196.51.113) идора мекунад. Ба ғайр аз DNS ва системаҳои файлӣ, бисёр хидматҳои дигар мавҷуданд, ба монанди:

JNDI

JNDI ё Java номгузорӣ ва интерфейси директория, API-и Java барои дастрасӣ ба хидматҳои номгузорӣ ва директория мебошад. JNDI як API аст, ки механизми ягонаи барномаи Java-ро барои ҳамкорӣ бо хидматҳои гуногуни номгузорӣ ва директория таъмин мекунад. Дар доираи он, ҳамгироӣ байни JNDI ва ҳама гуна хидмати додашуда бо истифода аз интерфейси провайдери хидматрасон (SPI) анҷом дода мешавад. SPI имкон медиҳад, ки хидматҳои гуногуни номгузорӣ ва директория шаффоф пайваст шаванд ва ба барномаи Java имкон медиҳад, ки API-и JNDI-ро барои дастрасӣ ба хидматҳои пайваст истифода барад. Дар расми зер меъмории JNDI тасвир шудааст: Истифодаи JNDI дар Java - 2

Манбаъ: Oracle Java дарсӣ

JNDI. Маънои калимаҳои оддӣ

Саволи асосӣ ин аст: барои чӣ ба мо JNDI лозим аст? JNDI лозим аст, то мо метавонем an objectи Java-ро аз баъзе "Бақайдгирии" an objectҳо аз codeи Java бо номи an objectи ба ин an object пайвастшуда ба даст орем. Биёед изҳороти болоро ба тезисҳо тақсим кунем, то фаровонии калимаҳои такрорӣ моро ба иштибоҳ наандозанд:
  1. Дар ниҳоят, мо бояд an objectи Java-ро гирем.
  2. Мо ин an objectро аз ягон реестр мегирем.
  3. Дар ин феҳрист як қатор an objectҳо мавҷуданд.
  4. Ҳар як an object дар ин реестр номи беназир дорад.
  5. Барои гирифтани an object аз реестр, мо бояд дар дархости худ ном гузорем. Гуё гуянд: «Он чиро, ки бо фалон ном доред, ба ман дех».
  6. Мо метавонем на танҳо an objectҳоро бо номи онҳо аз реестр хонем, балки инчунин an objectҳоро дар ин реестр бо номҳои муайян нигоҳ дорем (чизе онҳо ба он ҷо мерасанд).
Ҳамин тавр, мо як намуди феҳрист, ё нигаҳдории an object ё JNDI Tree дорем. Минбаъд, бо истифода аз як мисол, биёед кӯшиш кунем, ки маънои JNDI-ро фаҳмем. Бояд қайд кард, ки JNDI аксар вақт дар рушди Enterprise истифода мешавад. Ва чунин барномаҳо дар дохor баъзе serverҳои барнома кор мекунанд. Ин server метавонад ягон serverи барномаҳои Java EE ё контейнери сервлет ба монанди Tomcat ё ягон контейнери дигар бошад. Худи реестри an object, яъне дарахти JNDI одатан дар дохor ин serverи барнома ҷойгир аст. Охирин на ҳамеша зарур аст (шумо метавонед чунин дарахтро дар маҳал дошта бошед), аммо он маъмултарин аст. Дарахти JNDI метавонад аз ҷониби шахси махсус (администратори система ё мутахассиси DevOps) идора карда шавад, ки an objectҳоро бо номҳои худ "дар реестр захира мекунад". Вақте ки замимаи мо ва дарахти JNDI дар дохor як контейнер ҷойгиранд, мо метавонем ба осонӣ ба ҳама гуна an objectи Java, ки дар чунин реестр нигоҳ дошта мешавад, дастрасӣ пайдо кунем. Ғайр аз он, феҳрист ва замимаи мо метавонанд дар контейнерҳои гуногун ва ҳатто дар мошинҳои гуногуни физикӣ ҷойгир шаванд. JNDI ҳатто он вақт ба шумо имкон медиҳад, ки ба an objectҳои Java фосилаи дур дастрас шавед. Ҳолати маъмулӣ. Администратори serverи Java EE an objectеро дар реестр ҷойгир мекунад, ки маълумоти заруриро барои пайвастшавӣ ба пойгоҳи додаҳо нигоҳ медорад. Мувофиқи он, барои кор бо базаи маълумот, мо танҳо an objectи лозимиро аз дарахти JNDI дархост мекунем ва бо он кор мекунем. Ин хеле қулай аст. Бароҳатӣ инчунин дар он аст, ки дар рушди корхона муҳитҳои гуногун мавҷуданд. Серверҳои истеҳсолӣ мавҷуданд ва serverҳои санҷишӣ мавҷуданд (ва аксар вақт зиёда аз 1 serverи санҷишӣ мавҷуданд). Сипас, бо ҷойгир кардани an object барои пайвастшавӣ ба пойгоҳи додаҳо дар ҳар як server дар дохor JNDI ва истифодаи ин an object дар дохor замимаи мо, мо набояд ҳангоми ҷойгиркунии замимаи мо аз як server (озмоиш, баровардан) ба serverи дигар чизеро тағир диҳем. Дар ҳама ҷо ба пойгоҳи додаҳо дастрасӣ пайдо мешавад. Мисол, албатта, то андозае содда карда шудааст, аммо ман умедворам, ки он ба шумо дар фаҳмидани он ки чаро JNDI лозим аст, кӯмак мекунад. Минбаъд, мо бо баъзе унсурҳои ҳамла бо JNDI дар Java бештар шинос мешавем.

API JNDI

JNDI дар доираи платформаи Java SE таъмин карда шудааст. Барои истифодаи JNDI, шумо бояд синфҳои JNDI, инчунин як ё якчанд провайдерҳои хидматрасониро барои дастрасӣ ба хидматҳои номгузорӣ ва феҳрист ворид кунед. JDK провайдерҳои хидматрасониро барои хидматҳои зерин дар бар мегирад:
  • Протоколи дастрасӣ ба феҳристи сабук (LDAP);
  • Архитектураи брокери дархости умумӣ (CORBA);
  • Хидмати номгузории Common Object Services (COS);
  • Феҳристи Java Remote Method Invocation (RMI);
  • Хидмати номи домейн (DNS).
Рамзи API JNDI ба якчанд бастаҳо тақсим мешавад:
  • javax.nameming;
  • javax.naming.directory;
  • javax.naming.ldap;
  • javax.naming.event;
  • javax.naming.spi.
Мо муаррифии худро ба JNDI бо ду интерфейс оғоз мекунем - Ном ва Контекст, ки дорои функсияҳои асосии JNDI

Номи интерфейс

Интерфейси Ном ба шумо имкон медиҳад, ки номҳои ҷузъҳо ва инчунин синтаксиси номгузории JNDI-ро идора кунед. Дар JNDI, ҳама амалҳои ном ва директория нисбат ба контекст иҷро карда мешаванд. Решаҳои мутлақ вуҷуд надоранд. Аз ин рӯ, JNDI InitialContext-ро муайян мекунад, ки нуқтаи ибтидоиро барои номгузорӣ ва амалиёти директория таъмин мекунад. Пас аз дастрасӣ ба контексти ибтидоӣ, онро барои ҷустуҷӯи an objectҳо ва контекстҳои дигар истифода бурдан мумкин аст.
Name objectName = new CompositeName("java:comp/env/jdbc");
Дар codeи дар боло овардашуда мо номеро муайян кардем, ки дар зери он ягон an object ҷойгир аст (он шояд ҷойгир нашуда бошад, аммо мо ба он умед мебандем). Ҳадафи ниҳоии мо дарёфт кардани истинод ба ин an object ва истифодаи он дар барномаи мо мебошад. Ҳамин тавр, ном аз якчанд қисмҳо (ё аломатҳо) иборат аст, ки бо аломати слэш ҷудо карда шудаанд. Чунин нишонаҳо контекст номида мешаванд. Аввалин контекст танҳо контекст, ҳама баъдӣ зерконтекст (минбаъд зерконтекст номида мешавад). Контекстҳоро фаҳмидан осонтар аст, агар шумо онҳоро ба директорияҳо ё директорияҳо ё ҷузвдонҳои муқаррарӣ монанд кунед. Контексти решавӣ папкаи реша аст. Зерпапка аст. Мо метавонем ҳамаи ҷузъҳои (контекст ва зерконтекстҳо) номи додашударо тавассути иҷро кардани codeи зерин бубинем:
Enumeration<String> elements = objectName.getAll();
while(elements.hasMoreElements()) {
  System.out.println(elements.nextElement());
}
Натиҷа чунин хоҳад буд:

java:comp
env
jdbc
Натиҷа нишон медиҳад, ки нишонаҳо дар ном аз ҳамдигар бо хати слэш ҷудо шудаанд (аммо, мо инро зикр кардем). Ҳар як аломати ном индекси худро дорад. Индексизатсияи токен аз 0 оғоз мешавад. Контексти решавӣ индекси сифр дорад, контексти оянда индекси 1, оянда 2 ва ғайра дорад. Мо метавонем номи зерконтекстро аз рӯи индексаш гирем:
System.out.println(objectName.get(1)); // -> env
Мо инчунин метавонем аломатҳои иловагӣ илова кунем (дар охир ё дар макони мушаххаси индекс):
objectName.add("sub-context"); // Добавит sub-context в конец
objectName.add(0, "context"); // Добавит context в налачо
Рӯйхати пурраи усулҳоро дар ҳуҷҷатҳои расмӣ пайдо кардан мумкин аст .

Контексти интерфейс

Ин интерфейс маҷмӯи константаҳоро барои оғоз кардани контекст, инчунин маҷмӯи усулҳои эҷод ва нест кардани контекстҳо, пайваст кардани an objectҳо ба ном ва ҷустуҷӯ ва ҷустуҷӯи an objectҳоро дар бар мегирад. Биёед баъзе амалҳоеро, ки бо истифода аз ин интерфейс иҷро мешаванд, дида бароем. Амалҳои маъмултарин ҷустуҷӯи an object бо ном аст. Ин бо истифода аз усулҳои зерин анҷом дода мешавад:
  • Object lookup(String name)
  • Object lookup(Name name)
Пайваст кардани an object ба ном бо истифода аз усулҳо анҷом дода мешавад bind:
  • void bind(Name name, Object obj)
  • void bind(String name, Object obj)
Ҳарду усул номи номро ба an object Object мепайвандад unbind.
  • void unbind(Name name)
  • void unbind(String name)
Рӯйхати пурраи усулҳо дар вебсайти расмии ҳуҷҷатгузорӣ дастрас аст .

Context Initial

InitialContextсинфест, ки унсури решаи дарахти JNDI-ро ифода мекунад ва Context. Шумо бояд an objectҳоро аз рӯи ном дар дохor дарахти JNDI нисбат ба гиреҳи муайян ҷустуҷӯ кунед. Гиреҳи решаи дарахт метавонад ҳамчун гиреҳ хизмат кунад InitialContext. Ҳолати маъмулии истифодаи JNDI ин аст:
  • Гирифтан InitialContext.
  • InitialContextБарои гирифтани ном аз дарахти JNDI an objectҳоро истифода баред .
Якчанд роҳҳо барои ба даст овардани он вуҷуд доранд InitialContext. Ҳамааш аз муҳити ҷойгиршавии барномаи Java вобаста аст. Масалан, агар барномаи Java ва дарахти JNDI дар дохor як serverи барнома кор кунанд, InitialContextгирифтани он хеле осон аст:
InitialContext context = new InitialContext();
Агар ин тавр набошад, гирифтани контекст каме мушкилтар мешавад. Баъзан зарур аст, ки рӯйхати хосиятҳои муҳити зистро барои оғоз кардани контекст интиқол диҳед:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.fscontext.RefFSContextFactory");

Context ctx = new InitialContext(env);
Мисоли дар боло овардашуда яке аз роҳҳои имконпазири оғоз кардани контекстро нишон медиҳад ва ягон бори дигари семантикиро намебарад. Ба таври муфассал ба code ворид шудан лозим нест.

Намунаи истифодаи JNDI дар дохor санҷиши воҳиди SpringBoot

Дар боло, мо гуфтем, ки барои ҳамкории JNDI бо хидмати номгузорӣ ва директория, бояд SPI (Интерфейси хидматрасонӣ) дошта бошад, ки бо ёрии он ҳамгироӣ байни Java ва хидмати номгузорӣ анҷом дода мешавад. JDK-и стандартӣ бо якчанд SPI-ҳои гуногун меояд (мо онҳоро дар боло номбар кардем), ки ҳар яки онҳо барои мақсадҳои намоишӣ таваҷҷӯҳи кам доранд. Баланд бардоштани барномаи JNDI ва Java дар дохor контейнер то ҳадде ҷолиб аст. Аммо, муаллифи ин мақола як танбал аст, аз ин рӯ барои нишон додани он, ки JNDI чӣ гуна кор мекунад, ӯ роҳи муқовимати камтаринро интихоб кард: JNDI-ро дар дохor санҷиши воҳиди замимаи SpringBoot иҷро кунед ва ба контексти JNDI бо истифода аз як хаки хурди Spring Framework дастрасӣ пайдо кунед. Пас, нақшаи мо:
  • Биёед як лоиҳаи холии Spring Boot нависем.
  • Биёед дар дохor ин лоиҳа санҷиши воҳид эҷод кунем.
  • Дар дохor санҷиш мо кор бо JNDI-ро нишон медиҳем:
    • дастрасӣ ба контекст;
    • дар JNDI ягон an objectро бо ягон ном пайванд кардан (пайванд кардан);
    • an objectро бо номи он гирифтан (ҷустуҷӯ кардан);
    • Биёед санҷем, ки an object нул нест.
Биёед бо тартиб оғоз кунем. File->New->Project... Истифодаи JNDI дар Java - 3 Баъдан, ҷузъи Spring Initializr -ро интихоб кунед : Истифодаи JNDI дар Java - 4Метамаълумотро дар бораи лоиҳа пур кунед: Истифодаи JNDI дар Java - 5Сипас ҷузъҳои лозимии Spring Framework -ро интихоб кунед. Мо баъзе an objectҳои DataSource-ро мепайвандем, аз ин рӯ ба мо ҷузъҳо лозиманд, ки бо пойгоҳи додаҳо кор кунем:
  • API JDBC;
  • Махзани маълумоти H2 D.
Истифодаи JNDI дар Java - 6Биёед ҷойгиршавии системаи файлиро муайян кунем: Истифодаи JNDI дар Java - 7Ва лоиҳа сохта мешавад. Дар асл, як санҷиши воҳид барои мо ба таври худкор тавлид карда шуд, ки мо онро барои мақсадҳои намоишӣ истифода хоҳем кард. Дар зер сохтори лоиҳа ва санҷише, ки ба мо лозим аст: Истифодаи JNDI дар Java - 8Биёед ба навиштани code дар дохor санҷиши contextLoads шурӯъ кунем. Як хаки хурд аз Баҳор, ки дар боло муҳокима карда шуд, синфи SimpleNamingContextBuilder. Ин синф барои ба осонӣ баланд бардоштани JNDI дар дохor санҷишҳои воҳид ё барномаҳои мустақил тарҳрезӣ шудааст. Биёед codeро нависед, то контекстро ба даст орем:
final SimpleNamingContextBuilder simpleNamingContextBuilder
       = new SimpleNamingContextBuilder();
simpleNamingContextBuilder.activate();

final InitialContext context = new InitialContext();
Ду сатри аввали code ба мо имкон медиҳад, ки баъдтар контексти JNDI-ро ба осонӣ оғоз кунем. Бе онҳо, InitialContextҳангоми сохтани мисол истисно партофта мешавад: javax.naming.NoInitialContextException. Радди масъулият. Синф синфи SimpleNamingContextBuilderбекоршуда аст. Ва ин мисол барои нишон додани он аст, ки чӣ тавр шумо метавонед бо JNDI кор кунед. Инҳо таҷрибаҳои беҳтарин барои истифодаи JNDI дар дохor санҷишҳои воҳид нестанд. Гуфтан мумкин аст, ки ин асобаро барои сохтани контекст ва нишон додани ҳатмӣ ва дарёфти an objectҳо аз JNDI аст. Пас аз гирифтани контекст, мо метавонем аз он an objectҳоро ҷудо кунем ё an objectҳоро дар контекст ҷустуҷӯ кунем. Дар JNDI ҳоло ягон an object вуҷуд надорад, аз ин рӯ ба он ҷо гузоштани чизе мантиқӣ мебуд. Барои намуна, DriverManagerDataSource:
context.bind("java:comp/env/jdbc/datasource", new DriverManagerDataSource("jdbc:h2:mem:mydb"));
Дар ин сатр мо an objectи синфро DriverManagerDataSourceбо номи java:comp/env/jdbc/datasource. Минбаъд, мо метавонем an objectро аз контекст бо ном гирем. Мо дигар илоҷ надорем, ки an objectеро, ки нав гузоштаем, ба даст орем, зеро дар контекст ягон an objectи дигар вуҷуд надорад =(
final DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");
Акнун биёед тафтиш кунем, ки DataSource мо пайваст дорад (пайвастшавӣ, пайвастшавӣ ё пайвастшавӣ синфи Java аст, ки барои кор бо пойгоҳи додаҳо тарҳрезӣ шудааст):
assert ds.getConnection() != null;
System.out.println(ds.getConnection());
Агар мо ҳама чизро дуруст иҷро кунем, натиҷа чунин хоҳад буд:

conn1: url=jdbc:h2:mem:mydb user=
Бояд гуфт, ки баъзе сатрҳои code метавонанд истисноҳоро ба вуҷуд оранд. Сатрҳои зерин партофта мешаванд javax.naming.NamingException:
  • simpleNamingContextBuilder.activate()
  • new InitialContext()
  • context.bind(...)
  • context.lookup(...)
Ва ҳангоми кор бо синф DataSourceон метавонад партофта шавад java.sql.SQLException. Дар робита ба ин, зарур аст, ки codeро дар дохor блок иҷро кунед try-catchё дар имзои воҳиди санҷишӣ нишон диҳед, ки он метавонад истисноҳоро партояд. Ин аст рамзи пурраи синфи санҷиш:
@SpringBootTest
class JndiExampleApplicationTests {

    @Test
    void contextLoads() {
        try {
            final SimpleNamingContextBuilder simpleNamingContextBuilder
                    = new SimpleNamingContextBuilder();
            simpleNamingContextBuilder.activate();

            final InitialContext context = new InitialContext();

            context.bind("java:comp/env/jdbc/datasource", new DriverManagerDataSource("jdbc:h2:mem:mydb"));

            final DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");

            assert ds.getConnection() != null;
            System.out.println(ds.getConnection());

        } catch (SQLException | NamingException e) {
            e.printStackTrace();
        }
    }
}
Пас аз анҷом додани санҷиш, шумо метавонед гузоришҳои зеринро бинед:

o.s.m.jndi.SimpleNamingContextBuilder    : Activating simple JNDI environment
o.s.mock.jndi.SimpleNamingContext        : Static JNDI binding: [java:comp/env/jdbc/datasource] = [org.springframework.jdbc.datasource.DriverManagerDataSource@4925f4f5]
conn1: url=jdbc:h2:mem:mydb user=

Хулоса

Имрӯз мо ба JNDI назар кардем. Мо фаҳмидем, ки хидматҳои номгузорӣ ва директория чист ва JNDI API-и Java мебошад, ки ба шумо имкон медиҳад, ки бо хидматҳои гуногун аз барномаи Java яксон муомила кунед. Махз, бо ёрии JNDI, мо метавонем an objectҳоро дар дарахти JNDI бо номи муайян сабт кунем ва ҳамон an objectҳоро бо ном қабул кунем. Ҳамчун вазифаи бонус, шумо метавонед як мисолеро, ки чӣ тавр JNDI кор мекунад, иҷро кунед. Як чизи дигарро ба контекст пайваст кунед ва он гоҳ ин an objectро бо ном хонед.
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION