Spring 웹 애플리케이션에 JNDI를 사용하여 데이터베이스 연결 속성을 설정하려고합니다.
다음과 같은 두 가지 접근 방식을 고려하고 있습니다.
접근법 1 :
Spring 구성에는 다음과 같은 것이있을 수 있습니다.
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/facs"/>
그런 다음 webapp /META-INF/context.xml 파일에도 비슷한 내용이 있어야합니다.
<?xml version='1.0' encoding='utf-8'?>
<!-- antiResourceLocking="true" -->
<Context path="/podd-apn"
reloadable="true"
cachingAllowed="false"
antiResourceLocking="true"
>
<Resource name="jdbc/facs"
type="javax.sql.DataSource" username="${database.username}" password="${database.password}"
driverClassName="org.postgresql.Driver"
url="${database.url}"
maxActive="8" maxIdle="4"
global="jdbc/facs"
/>
</Context>
그리고 web.xml에서 다음과 같이해야합니다.
<!-- JNDI -->
<resource-ref>
<description>FACs Datasource</description>
<res-ref-name>jdbc/facs</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
접근법 2 :
다음과 같이 Spring 컨텍스트에서 설정하십시오.
<jee:jndi-lookup id="dbDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
다음과 같이 Tomcat의 server.xml에서 JNDI 리소스를 선언 할 수 있습니다.
<GlobalNamingResources>
<Resource name="jdbc/DatabaseName" auth="Container" type="javax.sql.DataSource"
username="dbUsername" password="dbPasswd"
url="jdbc:postgresql://localhost/dbname"
driverClassName="org.postgresql.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"/>
</GlobalNamingResources/>
다음과 같이 Tomcat의 웹 context.xml에서 JNDI 리소스를 참조하십시오.
<ResourceLink name="jdbc/DatabaseName"
global="jdbc/DatabaseName"
type="javax.sql.DataSource"/>
내 질문은 데이터베이스 속성을 유지하는 가장 좋은 장소는 어디입니까? server.xml 또는 context.xml 에 있어야합니까 ?
또한 2 개의 데이터베이스가있는 경우 2 개의 구성을 사용해야합니까?
또한 server.xml 또는 context.xml에 직접 배치하는 것이 가장 좋은 방법입니까? 아니면 Tomcat Manager GUI 콘솔을 통해 구성해야합니까?
감사!
답변
저는 user1016403이 설명하는 접근법 1 과 접근법 2 에서 가장 좋은 세 번째 접근법을 선호합니다
.
접근 3
- 데이터베이스 속성을
server.xml
server.xml
웹 애플리케이션에서 데이터베이스 속성 참조META-INF/context.xml
접근 방식 3 가지 이점
첫 번째 지점은 보안상의 이유로 유용하지만 두 번째 지점은 서버 속성 값이 변경 되더라도 웹 응용 프로그램에서 서버 속성 값을 참조하는 데 유용합니다.
또한 서버의 리소스 정의를 웹 응용 프로그램에서 사용하는 것과 분리하면 서로 다른 팀이 서로 다른 계층 / 계층에서 작업하는 다양한 복잡성으로 조직 전체에서 이러한 구성을 확장 할 수 있습니다. 관리자가 동일한 것을 공유하는 경우 서버 관리자 팀은 개발자 팀과 충돌하지 않고 작업 할 수 있습니다. 각 자원에 대한 개발자와 함께 JNDI 이름.
접근 방식 3 구현
JNDI 이름을 정의하십시오 jdbc/ApplicationContext_DatabaseName
.
다음과 같은 것을 사용하여 jdbc/ApplicationContext_DatabaseName
Tomcat에서의 다양한 속성과 값을 선언하십시오 server.xml
.
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName" auth="Container" type="javax.sql.DataSource"
username="dbUsername" password="dbPasswd"
url="jdbc:postgresql://localhost/dbname"
driverClassName="org.postgresql.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"/>
</GlobalNamingResources/>
링크 jdbc/ApplicationContext_DatabaseName
웹 응용 프로그램에서의 특성을 META-INF/context.xml
응용 프로그램 – 개인 JNDI 컨텍스트에 의해 java:comp/env/
에 지정된 name
속성 :
<Context path="/ApplicationContext" ... >
<!--
"global" attribute links to GlobalNamingResources in the ${catalina.base}/conf/server.xml (server administrator team)
"name" attribute is relative to the application-private JNDI context java:comp/env/ and is looked up from the java web application (application developer team)
-->
<ResourceLink global="jdbc/ApplicationContext_DatabaseName" name="jdbc/DatabaseName" type="javax.sql.DataSource"/>
</Context>
마지막으로 JNDI 리소스를 사용하려면 jdbc/DatabaseName
웹 애플리케이션의 배포 설명자에 JNDI 이름 을 지정합니다 .
<resource-ref>
<description>DatabaseName's Datasource</description>
<res-ref-name>jdbc/DatabaseName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
그리고 Spring 컨텍스트에서 :
<jee:jndi-lookup id="DatabaseNameDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
3 가지 단점 접근
JNDI 이름이 변경되면 server.xml
및 을 모두 META-INF/context.xml
편집해야하며 배포가 필요합니다. 그럼에도 불구하고이 시나리오는 드뭅니다.
3 가지 변형에 접근
하나의 웹 애플리케이션에서 사용하는 많은 데이터 소스
Tomcat에 구성을 추가하기 만하면됩니다 server.xml
.
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContext_DatabaseName2" ... />
...
</GlobalNamingResources/>
속성에 지정된 META-INF/context.xml
응용 프로그램 개인 JNDI 컨텍스트로 링크 웹 응용 프로그램 을 추가 합니다.java:comp/env/
name
<Context path="/ApplicationContext" ... >
<ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />
<ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />
...
</Context>
마지막으로 웹 애플리케이션의 배포 설명자에 JNDI 리소스 사용량을 추가합니다.
<resource-ref>
<description>DatabaseName1's Datasource</description>
<res-ref-name>jdbc/DatabaseName1</res-ref-name> ...
</resource-ref>
<resource-ref>
<description>DatabaseName2's Datasource</description>
<res-ref-name>jdbc/DatabaseName2</res-ref-name> ...
</resource-ref>
...
그리고 Spring 컨텍스트에서 :
<jee:jndi-lookup id="DatabaseName1DataSource"
jndi-name="jdbc/DatabaseName1" ... />
<jee:jndi-lookup id="DatabaseName2DataSource"
jndi-name="jdbc/DatabaseName2" ... />
...
동일한 서버의 많은 웹 응용 프로그램에서 사용하는 많은 데이터 소스
Tomcat에 구성을 추가하기 만하면됩니다 server.xml
.
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextX_DatabaseName2" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName2" ... />
...
</GlobalNamingResources/>
다른 구성은 이전 변형 사례에서 추론 할 수 있어야합니다.
동일한 서버의 많은 웹 애플리케이션에서 사용되는 동일한 데이터베이스에 대한 많은 데이터 소스
이 경우 Tomcat의 server.xml
구성은 다음과 같습니다.
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
다음 META-INF/context.xml
과 같은 두 가지 웹 응용 프로그램에서 끝납니다 .
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
그리고 좋아 :
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
누군가가 같은이 사실에 대해 걱정 될 수 있도록 name="jdbc/DatabaseName"
같은 서버에 배치 된 두 개의 서로 다른 응용 프로그램에서, 고개를 한 후 사용하십시오이 있기 때문에 문제가되지 않습니다 jdbc/DatabaseName
응용 프로그램 – 개인 JNDI 컨텍스트입니다 java:comp/env/
때문에, ApplicationContextX
사용java:comp/env/
할 수 없습니다 (설계 상)에 링크 된 리소스를 찾습니다 global="jdbc/ApplicationContextY_DatabaseName"
.
물론 이러한 걱정없이 더 편안하게 느껴진다면 다음과 같은 다른 이름 지정 전략을 사용할 수 있습니다.
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/applicationXprivateDatabaseName" ... />
</Context>
그리고 좋아 :
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/applicationYprivateDatabaseName" ... />
</Context>
답변
YOUR_APP.xml
파일
저는 접근 방식 2를 선호합니다 (구성의 일부 속성뿐만 아니라 모든 것을 넣습니다).하지만 전역 server.xml
또는 전역 에 배치하는 대신 Tomcat context.xml
의 응용 프로그램 별 파일에 배치해야합니다.context.xml.default
YOUR_APP.xml
YOUR_APP.xml
파일에 있습니다 $catalinaHome/conf/<engine>/<host>
(예를 들어 conf/Catalina/localhost/YOUR_APP.xml
).
특정 애플리케이션의 구성 YOUR_APP.xml
은 특정 애플리케이션에만 사용할 수 있습니다.
MuleSoft에서 발행 한 가이드를 참조하십시오 . 공식 문서 인 Tomcat Configuration Reference , The Context Container 페이지를 참조 하십시오.
해당 문서를 인용하려면 :
개별 컨텍스트 요소는 명시 적으로 정의 할 수 있습니다.
•…
•
$CATALINA_BASE/conf/[enginename]/[hostname]/
디렉토리의 개별 파일 (확장자 “.xml”) . 컨텍스트 경로와 버전은 파일의 기본 이름 (파일 이름에서 .xml 확장자를 뺀 이름)에서 파생됩니다.•…
답변
접근 4
JNDI를 사용하는 대신 구성 시간 대신 프로그램 초기화 중에.properties
파일로 작업하고 복잡한 객체를 빌드합니다 .
이미 Spring을 사용하고 있으며 다음과 같이 쉽게 구성 DataSource
할 수 있습니다.
<context:property-placeholder location="classpath:app.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@${db.host}:${db.port}:${db.user}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
</bean>
배포 설명자를 사용하는 것에 대해 Ralph에 완전히 동의 $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml
하지만 JNDI 대신 일반 키-값 파일을 좋아합니다!
Spring을 사용하면 위의 속성을 빈 필드에 쉽게 주입 할 수 있습니다.
@Value("${db.user}") String defaultSchema;
JNDI 대신 :
@Inject ApplicationContext context;
Enviroment env = context.getEnvironment();
String defaultSchema = env.getProperty("db.user");
EL은 이것을 허용합니다 (기본값 및 심층 재귀 대체) :
@Value('${db.user:testdb}') private String dbUserName;
<property name='username' value='${db.user.${env}}'/>
.properties
파일 을 외부화하려면 org.apache.catalina.loader.VirtualWebappLoader 가있는 최신 Tomcat 7을 사용합니다 .
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="/srv/web/app/"/>
따라서 devop virtualClasspath
은 애플리케이션별로 별도의 로컬 외부 전체 경로를 채우고 app.properties
해당 디렉토리 에 로컬 을 배치합니다.
또한보십시오:
답변
테스트, 통합 테스트, 프로덕션을위한 다양한 애플리케이션 구성에 대한 JNDI URL 지원을 사용할 수도 있습니다.
<Context>
...
<Resource auth="Container" factory="com.benasmussen.jndi.url.URLFactory"
name="url/MyUrl" type="java.net.URL" url="file:///your/path/to/file"/>
...
</Context>
<jee:jndi-lookup id="myUrl" jndi-name="java:comp/env/url/MyUrl" expected-type="java.net.URL" />
Tomcat 서버에 대한 JNDI URL 지원 을 사용 하려면 GitHub 프로젝트 Tomcat JNDI URL 지원 을 확인하십시오 .
답변
1 단계 : context.xml
<Context path="/projectname">
<Resource auth="Container"
driverClassName="com.mysql.jdbc.Driver"
logAbandoned="true"
maxActive="100" ``
maxIdle="30"
maxWait="10000"
name="refname"
removeAbandoned="true"
removeAbandonedTimeout="60"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:8080/dbname"
username="root"
password="root"/>
</Context>
2 단계 : web.xml
<resource-ref>
<description>DB Connection</description>
<res-ref-name>refname</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
3 단계 : 연결을위한 클래스 생성
Connection connection = null;
Context context = (Context) new InitialContext().lookup("java:comp/env");
DataSource ds = (DataSource) context.lookup("refname");
connection = ds.getConnection();
모든 것이 설정되었습니다.