背景:
软件开发过程一般涉及“开发 -> 测试 -> 部署上线”多个阶段,每个阶段的环境的配置参数会有不同,如数据源,文件路径等。为避免每次切换环境时都要进行参数配置等繁琐的操作,可以通过spring的profile功能来进行配置参数的切换。
部署阶段最原始的方式是连接服务器,停掉tomcat,备份之前的war,替换war,启动tomcat,这个过程不繁复,但是一天来两次也是够烦的了。
环境配置:
jdk8,gradle3.2,IntelliJ IDEA,tomcat8。
1:springprofile
1:建立文件夹environment,里面放着三个不同环境的配置文件
2:在配置文件中配置profile-beans。注意:需要放在最下面,并且,所有的配置文件都需要加上profile-beans,不然会失效,切记切记。
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- 定义数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="minIdle" value="${jdbc.minIdle}" /> <!-- 队列中的最小等待数 --> <property name="maxIdle" value="${jdbc.maxIdle}" /> <!-- 队列中的最大等待数 --> <property name="maxWait" value="${jdbc.maxWait}" /> <!-- 最长等待时间,单位毫秒 --> <property name="maxActive" value="${jdbc.maxActive}" /> <!-- 最大活跃数 --> <property name="initialSize" value="${jdbc.initialSize}" /><!-- 初始大小 --> <property name="validationQuery" value="select 1" /><!-- 检测语句 --> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath*:com/jniu/*/dao/mapper/*.xml" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.jniu.*.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> <!-- 定义事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="transactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition"> <property name="propagationBehaviorName" value="PROPAGATION_NESTED" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com/jniu/*/dao/mapper/*"/> </bean> <!-- 使用annotation注解方式配置事务 --> <tx:annotation-driven transaction-manager="transactionManager" /> <beans profile="dev"> <context:property-placeholder ignore-resource-not-found="true" location="classpath:environment/dev_xyfapp.properties"/> </beans> <beans profile="tes"> <context:property-placeholder ignore-resource-not-found="true" location="classpath:environment/test_xyfapp.properties"/> </beans> <beans profile="pro"> <context:property-placeholder ignore-resource-not-found="true" location="classpath:environment/pro_xyfapp.properties"/> </beans> </beans>
3:通过设置spring.profiles.default和spring.profiles.active这两个属性来激活和使用对应的配置文件。
设置方式有多种:
在web.xml中作为web应用的上下文参数context-param;
在web.xml中作为DispatcherServlet的初始化参数;
作为JNDI条目;
作为环境变量;
作为JVM的系统属性;
在集成测试类上,使用@ActiveProfiles注解配置。
在web.xml中作为DispatcherServlet的初始化参数;
作为JNDI条目;
作为环境变量;
作为JVM的系统属性;
在集成测试类上,使用@ActiveProfiles注解配置。
如果在程序中也使用到了spring.profiles.active,可以按照以下代码获取web.xml中的value值:
import javax.servlet.ServletContext; import org.springframework.web.context.WebApplicationContext; public class WebContextListener extends org.springframework.web.context.ContextLoaderListener{ public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { String env = servletContext.getInitParameter("spring.profiles.active"); //env可以设置在缓存中,供项目使用 return super.initWebApplicationContext(servletContext); } }
2:使用gradle进行一键部署(该步骤全部都是修改gradle配置文件)
1:安装插件 apply plugin: 'war'
2:设置remotes
remotes {
deployServer_test {
host = '1.1.1.1'
user = 'root'
password = 'password '
}
deployServer_pro {
host = '2.2.2.2'
user = 'root'
password = 'password'
}
}
deployServer_test {
host = '1.1.1.1'
user = 'root'
password = 'password '
}
deployServer_pro {
host = '2.2.2.2'
user = 'root'
password = 'password'
}
}
3:编写shell命令,这段配置就不写了,最会下面贴出整个gradle文件
4:最后,打开idea的Terminal面板,该面板默认就是项目根目录,输入gradle clean war deploy_test回车即可
apply plugin: 'org.hidetake.ssh' apply plugin: 'war' apply plugin: 'java' apply plugin: 'idea' sourceCompatibility = 1.7 targetCompatibility = 1.7 group 'com.xyf' tasks.withType(JavaCompile) { options.encoding = "UTF-8" } war { archiveName 'xyfapp.war' } sourceSets { main { java { srcDir 'src/main/java' } resources { srcDir 'src/main/config' } } } //version = '1.0.0.SNAPSHOT' version = '1.0.0.RELEASE' webAppDirName = 'src/main/webapp' repositories { //mavenCentral() maven { url 'http://1.1.1.1:8081/nexus/content/groups/public/' } } buildscript{ repositories { jcenter() } dependencies { classpath 'org.hidetake:gradle-ssh-plugin:2.6.0' } } configurations { compile.exclude module: 'jcl-over-slf4j' compile.exclude module: 'XmlSchema' } dependencies { compile project(':bo') compile project(':basebo') compile group: 'com.alibaba', name: 'fastjson', version: '1.2.37' compile 'org.springframework:spring-core:4.1.2.RELEASE' compile 'org.springframework:spring-beans:4.1.2.RELEASE' compile 'org.springframework:spring-context:4.1.2.RELEASE' compile 'org.springframework:spring-context-support:4.1.2.RELEASE' compile 'org.springframework:spring-expression:4.1.2.RELEASE' compile 'org.springframework:spring-jdbc:4.1.2.RELEASE' compile 'org.springframework:spring-tx:4.1.2.RELEASE' compile 'org.springframework:spring-web:4.1.2.RELEASE' compile 'org.springframework:spring-webmvc:4.1.2.RELEASE' compile 'org.springframework:spring-aop:4.1.2.RELEASE' compile 'org.springframework.data:spring-data-commons:1.8.4.RELEASE' compile 'org.springframework.data:spring-data-redis:1.4.1.RELEASE' compile 'org.springframework.amqp:spring-rabbit:1.4.0.RELEASE' compile 'com.fasterxml.jackson.core:jackson-core:2.1.3' compile 'com.fasterxml.jackson.core:jackson-annotations:2.1.4' compile 'com.fasterxml.jackson.core:jackson-databind:2.1.3' compile 'commons-beanutils:commons-beanutils-core:1.8.3' compile 'commons-dbcp:commons-dbcp:1.4' compile 'commons-lang:commons-lang:2.6' compile 'commons-pool:commons-pool:1.6' compile 'commons-logging:commons-logging:1.2' compile 'commons-digester:commons-digester:1.7' compile 'org.mybatis:mybatis:3.2.8' compile 'org.mybatis:mybatis-spring:1.2.2' compile 'org.quartz-scheduler:quartz:2.2.1' compile 'org.quartz-scheduler:quartz-jobs:2.2.1' compile 'commons-lang3:commons-lang3:3.4' compile 'javax.validation:validation-api:1.1.0.Final' compile 'org.hibernate:hibernate-validator:5.1.3.Final' compile 'redis.clients:jedis:2.6.1' compile 'net.sf.ehcache:ehcache:2.9.0' compile 'com.rabbitmq:amqp-client:3.4.3' compile 'org.aspectj:aspectjweaver:1.8.4' compile 'log4j:log4j:1.2.17' compile 'org.slf4j:slf4j-log4j12:1.7.7' compile 'mysql:mysql-connector-java:5.1.34' testCompile 'org.springframework:spring-test:4.1.2.RELEASE' testCompile "junit:junit:4.12" compile 'org.apache.httpcomponents:httpclient:4.3.5' compile 'org.apache.httpcomponents:httpclient-cache:4.3.5' compile 'org.apache.httpcomponents:httpmime:4.3.5' compile 'dom4j:dom4j:1.6.1' compile 'com.google.code.gson:gson:2.6.2' compile 'commons-io:commons-io:1.3.2' compile 'antlr:antlr:2.7.7' compile 'com.sdicons.jsontools:jsontools-core:1.7' compile 'org.json:json:20140107' compile 'org.bouncycastle:bcprov-ext-jdk16:1.45' compile 'xmlpull:xmlpull:1.1.3.1' compile 'xpp3:xpp3_min:1.1.4c' compile 'com.thoughtworks.xstream:xstream:1.4.1' compile 'org.bouncycastle:bcprov-jdk15:1.45' compile 'org.apache.shiro:shiro-core:1.2.2' compile 'org.apache.shiro:shiro-web:1.2.2' compile 'org.apache.shiro:shiro-spring:1.2.2' compile 'com.alibaba:aliyun-sdk-mns:1.1.8' compile 'org.apache.http:httpclient:4.4.1' compile 'org.apache.http:httpcore:4.4.1' compile 'org.apache.http:httpcore-nio:4.4.1' compile 'org.apache.http:httpasyncclient:4.1' compile 'com.swetake:swetakeQRcode:1.1' providedCompile 'javax.servlet:servlet-api:2.5' providedRuntime 'javax.servlet:jstl:1.2' compile group: 'taglibs', name: 'standard', version: '1.1.2' // https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3' compile fileTree(dir: 'src/main/webapp/WEB-INF/lib', include: '*.jar') compile group: 'jdom', name: 'jdom', version: '1.0' compile group: 'com.google.zxing', name: 'core', version: '3.3.0' compile group: 'org.glassfish', name: 'javax.el', version: '3.0.1-b08' compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.6.5' compile group: 'com.alibaba', name: 'fastjson', version: '1.2.36' } ssh.settings { knownHosts = allowAnyHosts } remotes { deployServer_test { host = '1.1.1.1' user = 'root' password = 'password' } deployServer_pro { host = '2.2.2.2' user = 'root' password = 'password' } } //测试部署 task shutdownTomcat_test() { doLast{ ssh.run { session(remotes.deployServer_test) { println 'shutdown tomcat...' executeScript '''#!/bin/sh cd /app/t8080/bin ./shutdown.sh ''' } } } } task del_test(dependsOn:shutdownTomcat_test) { doLast{ ssh.run { session(remotes.deployServer_test) { println 'start deleting...' executeScript '''#!/bin/sh rm -rf /app/backups/xyfapp mv /app/t8080/webapps/xyfapp /app/backups/ rm -f /app/t8080/webapps/xyfapp.war ''' } } } } task copy_test(dependsOn:del_test) { doLast{ ssh.run { session(remotes.deployServer_test) { println 'start copying war...' put from: buildDir.toString() + '/libs/xyfapp.war', into: '/app/t8080/webapps' executeScript '''#!/bin/sh cd /app/t8080/webapps unzip -oq xyfapp.war -d xyfapp/ ''' } } } } task deploy_test(dependsOn:copy_test) { doLast{ ssh.run { session(remotes.deployServer_test) { println 'start tomcat...' executeScript '''#!/bin/sh cd /app/t8080/bin ./startup.sh ''' } } } } //生产部署 task shutdownTomcat_pro() { doLast{ ssh.run { session(remotes.deployServer_pro) { println 'shutdown tomcat...' executeScript '''#!/bin/sh cd /xyf/t8080/bin ./shutdown.sh ''' } } } } task del_pro(dependsOn:shutdownTomcat_pro) { doLast{ ssh.run { session(remotes.deployServer_pro) { println 'start deleting...' executeScript '''#!/bin/sh rm -rf /xyf/backups/xyfapp mv /xyf/t8080/webapps/xyfapp /xyf/backups/ rm -f /xyf/t8080/webapps/xyfapp.war ''' } } } } task copy_pro(dependsOn:del_pro) { doLast{ ssh.run { session(remotes.deployServer_pro) { println 'start copying war...' put from: buildDir.toString() + '/libs/xyfapp.war', into: '/xyf/t8080/webapps' executeScript '''#!/bin/sh cd /xyf/t8080/webapps unzip -oq xyfapp.war -d xyfapp/ ''' } } } } task deploy_pro(dependsOn:copy_pro) { doLast{ ssh.run { session(remotes.deployServer_pro) { println 'start tomcat...' executeScript '''#!/bin/sh cd /xyf/t8080/bin ./startup.sh ''' } } } }