`

打造易于部署的WEB应用项目

 
阅读更多
概述
很多WEB应用的配置文件位于项目的类路径下(如WEB-INF\classes\conf\conf.properties),数据源也直接采用DBCP,C3P0等数据源,在Spring配置文件中定义。这种项目结构的部署性存在很大问题,其一,部署人员需要到WAR包中去更改配置信息,其二,新版本的WAR包不能直接覆盖生产环境下的WAR包,否则原有配置文件会被覆盖。也即这个WAR包是有状态的,它既包含了程序代码还包含了生产环境的配置信息,因此配置性,便携性将大大弱化。本文将给出一种优化的项目结构,解决项目部署性问题。

"传统的"WEB项目属性文件

以下是一个传统的WEB项目,在其Spring配置文件中通过<context:property-placeholder/>引用一个基于类路径的属性文件,如下所示:
<context:property-placeholder location="classpath:conf/conf.properties"/>
<rop:annotation-driven
            core-pool-size="${rop.corePoolSize}"
            max-pool-size="${rop.maxPoolSize}"
            queue-capacity="${rop.queueCapacity}"
            keep-alive-seconds="${rop.keepAliveSeconds}"
            thread-ferry-class="${rop.threadFerryClass}"
            sign-enable="${rop.signEnable}"
            ext-error-base-names="${rop.customErrorBasenames}"
            service-timeout-seconds="${rop.serviceTimeoutSeconds}"
            session-manager="sessionManager"
            app-secret-manager="appSecretManager"
            formatting-conversion-service="conversionService"/>


这个WEB项目打成WAR包后,在生产环境下如果要更改conf.properties配置文件中的参数,必须在WAR包中更改,虽然大部分WEB应用都会解开WAR到一个文件目录。即使如此,对于开发人员及实施人员都是头疼的。

对于开发人员来说,每次打WAR包时需要使用生产环境的conf.properties替换开发环境的conf.properties,而往往开发人员并不清楚生产环境的具体情况,此时,开发人员只能请求实施人员不要用这个WAR包直接覆盖生产环境下的WAR包。

对于实施人员来说,他得战战兢兢地升级WAR包,先将生产环境下WAR包的conf.properties拷贝出来,覆盖升级版的WAR包中的conf.properties,以免生产环境的conf.properties被覆盖了。当然,平常要更改配置参数也很麻烦,需要到每个WAR包中去更改。

便于部署的WEB项目如何规划属性文件
为了方便WEB项目的部署,必须将属性文件和WAR包解耦,即WAR包中不包含配置文件。但这样问题又来了,难不成开发环境下,需要将配置文件放到一个项目之外的目录下,那项目的团队开发岂不是又很麻烦,需要每个成员都手工拷贝项目的配置文件,而无法使用SVN同步即可。

为了使项目既具有开发便携性(SVN一同步,mvn jetty:run即可启动项目),又具有部署便携性(上传覆盖升级的WAR包即可,无需其它动作)。我们只需要通过一个系统参数定义配置文件的位置即可完美满足开发便携性和部署便携性了。

<plugin>
	<groupId>org.mortbay.jetty</groupId>
	<artifactId>maven-jetty-plugin</artifactId>
	<version>6.1.5</version>
	<configuration>
		<webDefaultXml>src/resources/dev/webdefault.xml</webDefaultXml>
		<systemProperties>
                        <!-- ①注意这里,我们用一个JVM系统属性指定配置文件的路径 -->
			<systemProperty>
				<name>CONFFILE_PATH</name>
				<value>classpath:conf/conf.properties</value>
			</systemProperty>
		</systemProperties>
		<webAppSourceDirectory>src/main/webapp</webAppSourceDirectory>
		<scanIntervalSeconds>0</scanIntervalSeconds>
		<contextPath>/</contextPath>
		<connectors>
			<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
				<port>7100</port>
			</connector>
		</connectors>
	</configuration>
</plugin>

   在①处,我们用一个JVM系统参数指定配置文件的路径,此处是开发环境,我们将配置文件放在项目的类路径下,可通过项目的SVN同步,项目团队所有成员都可共享之。
   上面的Spring配置文件调整下,通过这个系统参数CONFFILE_PATH引用属性配置文件
<!-- ① 注意这儿,通过SpringEL表示式访问系统参数的值 -->
<context:property-placeholder location="#{systemProperties.CONFFILE_PATH}"/>
<rop:annotation-driven
            core-pool-size="${rop.corePoolSize}"
            max-pool-size="${rop.maxPoolSize}"
            queue-capacity="${rop.queueCapacity}"
            keep-alive-seconds="${rop.keepAliveSeconds}"
            thread-ferry-class="${rop.threadFerryClass}"
            sign-enable="${rop.signEnable}"
            ext-error-base-names="${rop.customErrorBasenames}"
            service-timeout-seconds="${rop.serviceTimeoutSeconds}"
            session-manager="sessionManager"
            app-secret-manager="appSecretManager"
            formatting-conversion-service="conversionService"/>

   在开发环境下,使用Maven的Jetty插件,Jetty插件指定的CONFFILE_PATH系统参数为类路径下的conf/conf.properties。
   在部署环境下,我们在WEB应用服务器中定义JVM的系统参数,拿Websphere来说,定义JVM系统参数如下所示:
  

引用
   操作步骤:
   服务器->应用程序服务器(选择对应的应用程序服务器)->服务器基础结构(Java 和进程管理/进程定义)->其它属性(Java虚拟机)->其他属性(定制属性)

   在此,我们将配置文件放在file:/D:/framework/conf/framework.properties文件中。
(注:对于Tomcat,Jetty都可在应用服务器的配置文件中定义JVM参数,大家请自行网上找下)
  
   这样,部署时直接覆盖旧版的项目WAR包即可,由于配置文件已经放在独立于WAR包的外部操作系统的文件目录下,就不用考虑WAR升级对配置文件的影响了。

数据源的配置

    WEB应用基本上都有数据源,传统的WEB项目很多采用DBCP,C3P0等数据源在Spring配置文件中定义,这样会给部署带来问题:
  • 无法共享数据源,如果一个Server中存在多个WAR项目,这些WAR项目都访问同一个数据库时,由于在各自项目中独立配置数据源,会造成有多少个项目就有多少个数据源的问题,无法实现数据源的共享。
  • 数据源的优化不方便,如果通过Spring配置文件中配置DBCP,C3P0等数据源,数据源的优化参数抽取到配置文件中。由于数据源优化参数很多,往往并不是每个参数都抽取配置文件中,使数据源的优化受限。

   因此,应该让Spring引用JNDI的数据源,而不应该在Spring配置文件中通过DBCP,C3P0自行定义数据源。
   当然,一个很现实的问题是,你如何在开发环境下使用JNDI数据源,其实这已经不是问题了,Jetty很早就可以定义JNDI数据源了,并不是只有Websphere,Weblogic才能定义JNDI数据源。
   下面是使用Maven的maven-jetty-plugin插件定义JNDI数据源的配置:
<plugin>
	<groupId>org.mortbay.jetty</groupId>
	<artifactId>maven-jetty-plugin</artifactId>
	<version>6.1.5</version>
	<configuration>
		<webDefaultXml>src/resources/dev/webdefault.xml</webDefaultXml>
                <!--①添加一个jetty的额外配置文件 -->
                <jettyEnvXml>src/resources/jetty.xml</jettyEnvXml>
		<systemProperties>
			<systemProperty>
				<name>CONFFILE_PATH</name>
				<value>classpath:conf/conf.properties</value>
			</systemProperty>
		</systemProperties>
		<webAppSourceDirectory>src/main/webapp</webAppSourceDirectory>
		<scanIntervalSeconds>0</scanIntervalSeconds>
		<contextPath>/</contextPath>
		<connectors>
			<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
				<port>7100</port>
			</connector>
		</connectors>
	</configuration>
</plugin>

   
  在①处添加了一个额外的jetty配置文件jetty.xml,其配置内容如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
        "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">

<New id="myds" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/myds</Arg>
    <Arg>
        <New class="org.apache.commons.dbcp.BasicDataSource">
            <Set name="driverClassName">oracle.jdbc.driver.OracleDriver</Set>
            <Set name="url">jdbc:oracle:thin:@127.0.0.1:1521:orcl</Set>
            <Set name="username">test</Set>
            <Set name="password">test</Set>
        </New>
    </Arg>
</New>
</Configure>

  这里定义了一个名为jdbc/myds的JNDI数据源,这样项目的Spring配置文件就可直接引用这个JNDI数据源了:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
   ...
    <jee:jndi-lookup id="frameworkDS" jndi-name="java:comp/env/jdbc/myds"/>
</beans>

  由于JNDI的数据源名称不是固定的,比如在部署环境下,可能就叫"jdbc/yourds"了,因此需要将jndi的名字属性化。结合上面我们所说的配置文件,可以在配置文件中添加一个属性,暂且我们将该属性命名为ds.jndi:

  conf/conf.properties
  ds.jndi=java:comp/env/jdbc/yourds

  Spring配置文件中通过参数名引用JNDI的数据源:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
    ...
    <context:property-placeholder location="#{systemProperties.CONFFILE_PATH}"/>
    <jee:jndi-lookup id="frameworkDS" jndi-name="${ds.jndi}"/>
</beans>


   Prefect!至此,开发人员和部署人员都皆大欢喜了,部署环境下定义好JNDI数据源后,各WAR包即可利用之。
   是不是发现Maven和Spring真的无所不能呢?
  • 大小: 31.8 KB
分享到:
评论
1 楼 thc1987 2015-12-30  
对于属性文件的管理,我们公司是这样的:
把所有属性文件放在一个文件夹下,如src/main/config/
然后maven使用maven-assembly-plugin插件
构建平台打war包时,属性文件会单独压缩到一个zip中
然后使用环境变量指向到属性文件所在的文件夹
<context:property-placeholder 		location="file:${CONFIG_HOME}/server.properties" /> 

跟您的大同小异

相关推荐

    《Java Web应用开发技术实用教程》-王红-电子教案

    《Java Web应用开发技术实用教程》是一本专为学习Java Web开发的初学者和进阶者编写的教材,由王红老师倾力打造。这本书涵盖了Java Web开发的基础知识到高级技术,旨在帮助读者掌握构建动态网页和Web应用程序的技能...

    web项目整体开发流程及规范

    在IT行业中,Web项目开发是一项复杂且系统的工作,涉及到多个环节和团队成员的协作。为了确保项目的高效、稳定和可持续发展,"web项目...只有这样,才能打造出高质量、易于维护的Web应用,满足客户需求并适应市场变化。

    使用open source产品组装你的web应用架构(转载)

    在构建Web应用架构时,开源产品提供了丰富的选择和强大的功能,可以帮助开发者以更低的成本和更高的效率构建出稳定、可扩展的系统。...通过合理选择和组合这些工具,可以打造出高效、稳定的Web应用架构。

    ssmdemoMybatis+Spring+SpringMVC5.0.zip_CE5.0_V淘宝网上商城_java web项目_

    这个项目包含了用户登录、注册、购物车等一系列关键功能,为我们展示了如何有效集成并利用SSM框架来打造高效稳定的Web应用。 首先,Spring作为核心的依赖注入(DI)框架,负责管理整个应用程序的组件。在...

    使用_CakePHP_快速打造_Web_站点

    在实际操作中,通常会将 CakePHP 应用部署在一个子目录中,而不是直接放在 Web 根目录,以保持项目结构的清晰。 接下来,我们将接触 MVC 设计模式。MVC 是软件开发中的一个重要概念,它将应用程序分为三个主要部分...

    favorites-web-开源项目-云收藏

    总结起来,"favorites-web-开源项目-云收藏"是一个集成了Spring Boot 2.0、SNS社交功能的收藏类应用,提供了用户个人化的收藏管理以及社交分享。项目的核心技术和功能设计展示了其在互联网信息管理和社交互动方面的...

    Node.js-基于TypescriptKoa2打造的web开发工程模板

    而本项目“Node.js-基于Typescript Koa2打造的web开发工程模板”则是在Node.js的基础上,利用TypeScript和Koa2框架,构建了一个高效、稳定且易于维护的Web应用开发模板。 TypeScript是JavaScript的一个超集,它引入...

    应用Yii1.1和PHP5进行敏捷Web开发

    - **国际化与本地化**:支持多语言环境,易于全球化部署,满足不同地域用户的使用习惯。 - **扩展类库Zii**:自1.1版本起,Yii引入官方扩展类库Zii,集合了核心团队成员的开发成果,极大地丰富了框架功能,提升了...

    ASP.NET应用程序规划与设计

    ASP.NET应用程序规划与设计是构建高效、稳定和用户友好的Web应用的关键步骤。...每个环节都对最终产品的成功起到关键作用,只有全面考虑和精心策划,才能打造出满足用户需求、易于维护和扩展的高质量Web应用。

    基于Django-REST-Framework框架打造前后端彻底分离项目实战.zip

    在本实战项目中,我们将利用Django-REST-Framework(简称DRF)这一强大的Web服务框架,构建一个完全的前后端分离应用。Django-REST-Framework是一个为Django设计的高级Web API框架,它使得开发高质量、RESTful风格的...

    jetty 7 安装包

    Jetty 7是一款轻量级、高性能的Java Web服务器和Servlet容器,被广泛用于开发、测试和部署Web应用程序。在本场景中,我们讨论的是Jetty 7.5.0的安装包,这是一个非常重要的版本,因为它包含了多个改进和新功能。 ...

    开启MATLAB Web API之门:打造自定义接口的艺术

    这种方式不仅可以让MATLAB的功能更易于被其他应用程序调用,还可以通过Web API的形式实现MATLAB的强大计算能力与其他系统的无缝集成。 #### 九、参考文献 1. "Creating a MATLAB Web API", MathWorks.

    基于web的学生选课系统

    Tomcat作为Java EE应用服务器,是部署和运行Java Web应用的重要工具。它支持Servlet和JSP规范,为开发者提供了轻量级、高效的运行环境。在开发过程中,开发者需要将项目打包成WAR(Web Application Archive)文件,...

    《精通Java Web动态图表编程》源码

    《精通Java Web动态图表编程》是一本专注于Java Web应用程序中动态图表生成的书籍,其源码提供了丰富的实例和示例,帮助开发者深入了解如何在实际项目中实现数据可视化。动态图表在现代Web应用中扮演着重要角色,...

    Vue+DjangoRESTframework打造前后端分离的生鲜电商项目.zip

    在本项目中,“Vue+DjangoRESTframework打造前后端分离的生鲜电商项目”结合了现代Web开发中的两个重要技术:前端的Vue.js框架和后端的Django REST framework,用于构建一个功能完善的在线生鲜超市应用。这个项目...

    项目配置管理中心代码

    `Java web`是使用Java语言开发的Web应用程序,它涵盖了Servlet、JSP(Java Server Pages)等技术。在配置中心中,Java web技术可能用于构建Web接口,供其他服务调用以获取或更新配置。 最后,`vue`是一个轻量级的...

    VUE网页带视频播放器无需部署直接打开

    总结来说,这个项目展示了Vue.js在构建Web应用时的高效性和灵活性,特别是对于多媒体内容的处理。通过学习这个项目,开发者不仅可以深入了解Vue的组件化开发模式,还能掌握如何利用HTML5的视频功能和Vue的响应式特性...

    NET企业级应用架构设计(2nd)

    书中可能会讲解如何使用ASP.NET MVC或ASP.NET Core构建Web应用程序,以及如何利用WCF(Windows Communication Foundation)或gRPC进行服务间通信。负载均衡、缓存策略(如Redis)和消息队列(如RabbitMQ)等技术也会...

    前端项目-ionic.zip

    此外,Ionic 支持多种移动平台,包括iOS、Android以及Windows Phone,通过Cordova或 Capacitor可以将Web应用打包为原生应用。 二、AngularJS基础 作为Ionic的基石,AngularJS是一个强大的MVVM(Model-View-...

Global site tag (gtag.js) - Google Analytics