Салом! Имрӯз мо шуморо бо JNDI шинос хоҳем кард. Биёед бифаҳмем, ки он чӣ гуна аст, чаро он лозим аст, он чӣ гуна кор мекунад, мо бо он чӣ гуна кор карда метавонем. Ва он гоҳ мо санҷиши воҳиди Spring Boot менависем, ки дар дохor он мо бо ҳамин JNDI бозӣ мекунем.
Муқаддима. Хидматҳои номгузорӣ ва директория
Пеш аз ворид шудан ба 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 ва системаҳои файлӣ, бисёр хидматҳои дигар мавҷуданд, ба монанди:- Протоколи дастрасӣ ба феҳристи сабук (LDAP) ;
- Хадамоти номгузории CORBA ;
- Хадамоти иттилоотии шабакавӣ (NIS) ;
- Ва дигарон.
JNDI
JNDI ё Java номгузорӣ ва интерфейси директория, API-и Java барои дастрасӣ ба хидматҳои номгузорӣ ва директория мебошад. JNDI як API аст, ки механизми ягонаи барномаи Java-ро барои ҳамкорӣ бо хидматҳои гуногуни номгузорӣ ва директория таъмин мекунад. Дар доираи он, ҳамгироӣ байни JNDI ва ҳама гуна хидмати додашуда бо истифода аз интерфейси провайдери хидматрасон (SPI) анҷом дода мешавад. SPI имкон медиҳад, ки хидматҳои гуногуни номгузорӣ ва директория шаффоф пайваст шаванд ва ба барномаи Java имкон медиҳад, ки API-и JNDI-ро барои дастрасӣ ба хидматҳои пайваст истифода барад. Дар расми зер меъмории JNDI тасвир шудааст:Манбаъ: Oracle Java дарсӣ
JNDI. Маънои калимаҳои оддӣ
Саволи асосӣ ин аст: барои чӣ ба мо JNDI лозим аст? JNDI лозим аст, то мо метавонем an objectи Java-ро аз баъзе "Бақайдгирии" an objectҳо аз codeи Java бо номи an objectи ба ин an object пайвастшуда ба даст орем. Биёед изҳороти болоро ба тезисҳо тақсим кунем, то фаровонии калимаҳои такрорӣ моро ба иштибоҳ наандозанд:- Дар ниҳоят, мо бояд an objectи Java-ро гирем.
- Мо ин an objectро аз ягон реестр мегирем.
- Дар ин феҳрист як қатор an objectҳо мавҷуданд.
- Ҳар як an object дар ин реестр номи беназир дорад.
- Барои гирифтани an object аз реестр, мо бояд дар дархости худ ном гузорем. Гуё гуянд: «Он чиро, ки бо фалон ном доред, ба ман дех».
- Мо метавонем на танҳо an objectҳоро бо номи онҳо аз реестр хонем, балки инчунин an objectҳоро дар ин реестр бо номҳои муайян нигоҳ дорем (чизе онҳо ба он ҷо мерасанд).
API JNDI
JNDI дар доираи платформаи Java SE таъмин карда шудааст. Барои истифодаи JNDI, шумо бояд синфҳои JNDI, инчунин як ё якчанд провайдерҳои хидматрасониро барои дастрасӣ ба хидматҳои номгузорӣ ва феҳрист ворид кунед. JDK провайдерҳои хидматрасониро барои хидматҳои зерин дар бар мегирад:- Протоколи дастрасӣ ба феҳристи сабук (LDAP);
- Архитектураи брокери дархости умумӣ (CORBA);
- Хидмати номгузории Common Object Services (COS);
- Феҳристи Java Remote Method Invocation (RMI);
- Хидмати номи домейн (DNS).
- javax.nameming;
- javax.naming.directory;
- javax.naming.ldap;
- javax.naming.event;
- javax.naming.spi.
Номи интерфейс
Интерфейси Ном ба шумо имкон медиҳад, ки номҳои ҷузъҳо ва инчунин синтаксиси номгузории 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)
bind
:
void bind(Name name, Object obj)
void bind(String name, Object obj)
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 нул нест.
- API JDBC;
- Махзани маълумоти H2 D.
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=
GO TO FULL VERSION