server.xml 또는 context.xml에서 데이터베이스 연결 속성을 설정해야합니까?


79

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 콘솔을 통해 구성해야합니까?

감사!

답변:


27

저는 user1016403이 설명하는 접근법 1접근법 2 에서 가장 좋은 세 번째 접근법을 선호합니다 .

접근 3

  1. 데이터베이스 속성을 server.xml
  2. server.xml웹 애플리케이션에서 데이터베이스 속성 참조META-INF/context.xml

접근 방식 3 가지 이점

첫 번째 지점은 보안상의 이유로 유용하지만 두 번째 지점은 서버 속성 값이 변경 되더라도 웹 응용 프로그램에서 서버 속성 값을 참조하는 데 유용합니다.

또한 서버의 리소스 정의를 웹 응용 프로그램에서 사용하는 것과 분리하면 서로 다른 팀이 서로 다른 계층 / 계층에서 작업하는 다양한 복잡성으로 조직 전체에서 이러한 구성을 확장 할 수 있습니다. 관리자가 동일한 것을 공유하는 경우 서버 관리자 팀은 개발자 팀과 충돌하지 않고 작업 할 수 있습니다. 각 자원에 대한 개발자와 함께 JNDI 이름.

접근 방식 3 구현

JNDI 이름을 정의하십시오 jdbc/ApplicationContext_DatabaseName.

다음과 같은 것을 사용하여 jdbc/ApplicationContext_DatabaseNameTomcat에서의 다양한 속성과 값을 선언하십시오 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>

"동일한 서버의 많은 웹 응용 프로그램에서 사용하는 동일한 데이터베이스에 대한 많은 데이터 소스"시나리오에 관한 질문 ... <Resource name="jdbc/ApplicationContextX_DatabaseName" ... /> <Resource name="jdbc/ApplicationContextY_DatabaseName" ... /> 리소스가 연결 풀인 경우 웹 응용 프로그램 당 하나씩 두 개의 개별 풀이 제공됩니까? 반면에 두 웹앱에서 하나의 리소스로 연결하면 연결 풀이 하나만있을 것입니다. 맞습니까? 하나를 선호하는 이유가 있습니까? (웹 앱당 하나의 개별 DB 연결 풀과 모든 웹앱에서 공유하는 하나의 연결 풀)? 감사.
Rebeccah

1
@Rebeccah-Q1 : 리소스가 연결 풀인 경우 웹 앱당 하나씩 두 개의 개별 풀을 제공합니까? A1 : 그렇습니다.
taringamberini

1
@Rebeccah-Q2 : 두 웹앱에서 하나의 리소스로 연결하면 연결 풀이 하나만있을 것입니다. 맞습니까? A2 : 맞습니다.
taringamberini

2
@Rebeccah-Q3 : 하나를 다른 것보다 선호하는 이유는 무엇입니까? (웹 앱당 하나의 개별 DB 연결 풀과 모든 웹앱에서 공유하는 하나의 연결 풀)? A3 : webAppX를 집중적으로 사용하면 webAppX의 연결 풀이 고갈되어 webAppY 속도가 느려지지 않기 때문에 "웹 앱당 하나의 별도 DB 연결 풀"을 선호합니다. 또한 데이터베이스 모니터링 및 로깅 시스템은 webAppX와 webAppY 요청을 구분할 수 없으므로 문제를 이해하고 격리하는 것이 어렵거나 불가능합니다.
taringamberini

23

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 확장자를 뺀 이름)에서 파생됩니다.

•…


2
답변 주셔서 감사합니다. 애플리케이션 META-INF / context.xml에 모든 속성을 배치하면? 보관하기에 가장 좋은 장소입니까?
user1016403 2013

5
일부 속성 값을 내부 (예 : META-INF / context.xml의 경우)에 배치하는 것이 좋은 방법이라고 생각하지 않습니다. 속성이 변경되면 응용 프로그램을 다시 컴파일하고 배포해야하기 때문입니다. -따라서 이것은 속성을 전혀 사용하지 않고 값을 spring config.xml에 직접 배치하는 것과 거의 동일합니다.
Ralph

그렇다면 보관하는 데 권장되는 장소는 어디입니까?
user1016403 2013

2
context.xml.default를 사용하여 모든 앱에 대해 정의하는 대신 동일한 폴더에있는 yourapp.xml과 같은 애플리케이션 별 컨텍스트 구성 파일을 사용하여 동일한 전쟁의 두 배포를 가리킬 수 있습니다. 다른 데이터베이스.
usethe4ce 2010 년

1
유용한 답변이 아닙니다. 단지 선호 사항을 명시하고 정당성을 제공하지 않습니다.
DavidS

10

접근 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해당 디렉토리 에 로컬 을 배치합니다.

또한보십시오:


0

테스트, 통합 테스트, 프로덕션을위한 다양한 애플리케이션 구성에 대한 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 지원 을 확인하십시오 .


0

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();

모든 것이 설정되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.