Maven: Retrieve Code, Compile, Deploy

本文介绍了一种使用Maven进行自动化部署的方法,包括配置pom.xml以实现项目的编译、从SVN获取最新代码及通过批处理命令完成整个部署过程。文章详细展示了如何设置tomcat-maven-plugin和maven-scm-plugin,以及所需的settings.xml和tomcat-users.xml配置。
[b]1, Compile, Deploy[/b]
1) pom.xml

<project>
...
</build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<configuration>
<url>http://127.0.0.1:8080/manager</url>
<server>mytomcat</server>
</configuration>
</plugin>
</plugins>
</build>
</project>


2) settings.xml in \Users\[account]\.m2\ of Operation System

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository/>
<interactiveMode/>
<usePluginRegistry/>
<offline/>
<pluginGroups/>
<servers>
<server>
<id>mytomcat</id>
<username>test</username>
<password>pass</password>
</server>
</servers>
<mirrors/>
<proxies/>
<profiles/>
<activeProfiles/>
</settings>



3) tomcat-users.xml

<role rolename="manager"/>
<role rolename="admin"/>
<user username="test" password="pass" roles="manager"/>


2, Get latest code from SVN
1) pom.xml

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.3</version>
<configuration>
<goals>install</goals>
<username>***</username>
<password>***</password>
</configuration>
</plugin>



...
<scm>
<connection>scm:svn:file://192.168.1.***//repository/***/</connection>
<developerConnection>scm:svn:file://192.168.1.***//repository/***//</developerConnection>
<url>scm:svn:file://192.168.1.180/repository/***//</url>
</scm>
</project>


3, install software with svn command. i.e. Slik-Subversion-1.6.12-win32.msi

svn --username *** --password *** --non-interactive update F:\***

svn help update

http://www.sliksvn.com/en/download



4, batch DOS command

Echo ------Start To Deploy Project------
Echo ------
Echo ------Start To Retrieve Latest Content From SVN------
call mvn scm:update
Echo ------
Echo ------Start To Install Application------
call mvn install
Echo ------
Echo ------Start To Deploy Application On Tomcat------
call mvn tomcat:redeploy
Echo ------
Echo ------Deploy Done------



[b]Note:[/b]
1, SCM URL

scm:svn:svn://[username[:password]@]server_name[:port]/path_to_repository
scm:svn:svn+ssh://[username@]server_name[:port]/path_to_repository
scm:svn:file://[hostname]/path_to_repository
scm:svn:http://[username[:password]@]server_name[:port]/path_to_repository
scm:svn:https://[username[:password]@]server_name[:port]/path_to_repository


2, SCM example

scm:svn:file:///svn/root/module
scm:svn:file://localhost/path_to_repository
scm:svn:file://my_server/path_to_repository
scm:svn:http://svn.apache.org/svn/root/module
scm:svn:https://username@svn.apache.org/svn/root/module
scm:svn:https://username:password@svn.apache.org/svn/root/module


3, SCM Command


mvn scm:changelog
mvn -DstartDate=YYYY-MM-DD -DendDate=YYYY-MM-DD scm:changelog

mvn scm:diff
mvn -DstartRevision=<revision> -DendRevision=<revision> scm:diff

mvn scm:validate
spring.application.name: travel spring: datasource: url: jdbc:mysql://ca.local:3306/travel username: root password: 123456 flyway: enabled: true server: address: 0.0.0.0 # 允许所有IP访问 port: 38080 name: build maven project on: push jobs: build: runs-on: ubuntu-22.04 steps: #ssl认证 - name: Trust Gitea CA certificate run: | sudo mkdir -p /usr/local/share/ca-certificates/ echo "$CA_CERT" | sudo tee /usr/local/share/ca-certificates/ca.crt > /dev/null sudo update-ca-certificates env: CA_CERT: ${{ secrets.CA_CERT }} - name: checkout uses: https://gitea.local:3000/actions/checkout@v4 - name: 直接安装OpenJDK 17(无需移除不存在的旧版本) run: | # 更新包索引(关键,确保能找到最新包) sudo apt-get update -y # 安装OpenJDK 17(完整JDK,包含javac) sudo apt-get install -y openjdk-17-jdk # 验证安装结果 echo "Java版本:$(java -version 2>&1 | head -n1)" echo "Javac版本:$(javac -version 2>&1 | head -n1)" # 配置环境变量(强制绑定Java 17路径) echo "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64" >> $GITHUB_ENV echo "$JAVA_HOME/bin" >> $GITHUB_PATH # 确保优先级最高 - name: set up Java 17 uses: https://gitea.local:3000/actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' architecture: x64 cache: 'maven' java-package: jdk - name: set up maven uses: https://gitea.local:3000/actions/setup-maven@v5 with: maven-version: 3.9.9 - name: set up maven settings uses: https://gitea.local:3000/actions/maven-settings-action@v3.1.0 with: mirrors: | [{ "id": "huaweicloud", "mirrorOf": "*", "name": "huaweicloud", "url": "https://repo.huaweicloud.com/repository/maven/" }] - name: clean project run: mvn clean - name: compile run: mvn compile - name: 清理并重新编译(确保Java 17生成新文件) run: | rm -rf target/ mvn compile -Dmaven.compiler.executable=$JAVA_HOME/bin/javac env: JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 - name: unit test run: mvn -Dsurefire.includes=**/*UnitTests test # - name: integration test # run: mvn -Dsurefire.includes=**/*IntTests test # env: # TESTCONTAINERS_HOST_OVERRIDE: host.docker.internal - name: package run: mvn -DskipTests package - name: set version run: echo "VERSION=v$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV env: VERSION: v1.0 - name: login docker uses: https://gitea.local:3000/actions/login-action@v3 with: registry: gitea.local:3000 username: changbingyu password: 12345678 # - run: sleep infinity - name: build and publish run: | echo $VERSION docker build . --file Dockerfile -t gitea.local:3000/travel/travel:$VERSION docker push gitea.local:3000/travel/travel:$VERSION echo "RUNNING=$(docker ps | grep local-travel)" >> $GITHUB_ENV - name: remove container run: | if [ "$(docker ps -q -f name=^/local-travel$)" ]; then docker stop local-travel echo "容器已停止" else echo "容器不存在,跳过删除" fi # - name: deploy container # run: | # docker run -d -p 38080:38080 -e SPRING_PROFILES_ACTIVE=test --name test-local-travel gitea.local:3000/travel/travel:$VERSION - name: deploy app container run: | docker run -d -p 38080:38080 \ -e SPRING_PROFILES_ACTIVE=test \ -e SPRING_DATASOURCE_URL="jdbc:mysql://host.docker.internal:3306/travel?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true" \ -e SPRING_DATASOURCE_USERNAME=root \ -e SPRING_DATASOURCE_PASSWORD=123456 \ -e JAVA_OPTS="-Djava.net.preferIPv4Stack=true" \ --name test-local-travel gitea.local:3000/travel/travel:$VERSION \ /bin/sh -c " \ if command -v ufw &> /dev/null; then ufw disable; echo 'ufw disabled'; fi; \ if command -v iptables &> /dev/null; then iptables -F; echo 'iptables cleared'; fi; \ exec java $JAVA_OPTS -jar /app.jar \ " - name: system test run: | mvn -Dsurefire.includes=**/*SysTests test env: TESTCONTAINERS_HOST_OVERRIDE: ca.local # env: # TESTCONTAINERS_HOST_OVERRIDE: host.docker.internal - name: remove container run: | if [ "$(docker ps -q -f name=^/test-local-travel$)" ]; then docker stop test-local-travel echo "容器已停止" else echo "容器不存在,跳过删除" fi - name: deploy container run: | docker run -d --rm -p 18080:18080 --name local-travel gitea.local:3000/travel/travel:$VERSION # 部署应用容器(前台运行+必要环境变量) # - name: deploy app container # run: | # docker run -d -p 38080:38080 \ # -e SPRING_PROFILES_ACTIVE=test \ # -e SPRING_DATASOURCE_URL="jdbc:mysql://host.docker.internal:3306/travel?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true" \ # -e SPRING_DATASOURCE_USERNAME=root \ # -e SPRING_DATASOURCE_PASSWORD=123456 \ # -e JAVA_OPTS="-Djava.net.preferIPv4Stack=true" \ # --name test-local-travel gitea.local:3000/travel/travel:$VERSION \ # /bin/sh -c " \ # if command -v ufw &> /dev/null; then ufw disable; echo 'ufw disabled'; fi; \ # if command -v iptables &> /dev/null; then iptables -F; echo 'iptables cleared'; fi; \ # exec java $JAVA_OPTS -jar /app.jar \ # " package ead2024.travel.system; import com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.SystemDefaultDnsResolver; import com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import ead2024.travel.Application; import ead2024.travel.api.Result; import ead2024.travel.domain.Invitation; import ead2024.travel.domain.UserException; import org.junit.jupiter.api.*; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.MediaType; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestClient; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Proxy; import static org.junit.jupiter.api.Assertions.*; @ActiveProfiles("test") @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class SysTests { static RestClient restClient; static String cookie; @BeforeAll static void setUp() { // 创建一个 HTTP 代理,强制将所有请求转发到 192.168.43.28:38080 Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("192.168.43.28", 38080)); // 配置 RestClient 使用该代理 System.setProperty("http.proxyHost", "192.168.43.28"); System.setProperty("http.proxyPort", "38080"); System.setProperty("https.proxyHost", "192.168.43.28"); System.setProperty("https.proxyPort", "38080"); // 排除对 localhost 的代理(如果需要访问其他服务) System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1"); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setConnectTimeout(100 * 1000); requestFactory.setReadTimeout(100 * 1000); restClient = RestClient.builder() .baseUrl("http://ca.local:38080") // 保持原URL,但实际请求会被代理到 192.168.43.28 .requestFactory(requestFactory) .build(); } // @BeforeAll // static void setUp() { // HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); // requestFactory.setConnectTimeout(100 * 1000); // 连接超时:10秒 // requestFactory.setReadTimeout(100 * 1000); // 读取超时:10秒 // // // 2. 基于自定义请求工厂创建RestClient,并指定基础URL // restClient = RestClient.builder() // .baseUrl("http://ca.local:38080") // 基础地址 // .requestFactory(requestFactory) // 注入超时配置 // .build(); //// restClient = RestClient.create("http://localhost:28080"); // } @Test @Order(1) @DisplayName("测试注册") void testRegisterSystem(){ var user = """ { "username": "45ew79", "password": "11po17a" } """; var result = restClient.post() .uri("/travel/users") .contentType(MediaType.APPLICATION_JSON) .body(user) .retrieve().body(Result.class); assertNotNull(result); Assertions.assertEquals(200, result.getCode()); } @Test @Order(2) @DisplayName("测试登录") void testLoginSystem(){ try { var user = """ { "username": "45ew79", "password": "11po17a" } """; var response = restClient.put() .uri("/travel/users") .contentType(MediaType.APPLICATION_JSON) .body(user) .retrieve().toEntity(new ParameterizedTypeReference<Result<String>>() {}); assertNotNull(response); var value = response.getHeaders().get("Set-Cookie"); var result = response.getBody(); assertNotNull(value); cookie = value.get(0).split(";")[0]; assertNotNull(result); assertEquals(200,result.getCode()); } catch (UserException e) { fail(e.getMessage()); } } @Test @Order(3) @DisplayName("测试发布邀请函") void testPublishInvitationSystem(){ try { var invitation = """ { "description": "27845432133", "startDate": "2025-10-24", "endDate": "2025-12-24", "number": 2, "deadline": "2025-09-24", "label": "122", "title": "54454356" } """; var result = restClient.post() .uri("/travel/invitations") .contentType(MediaType.APPLICATION_JSON) .header("Cookie", cookie) .body(invitation) .retrieve().body(Result.class); assertNotNull(result); Assertions.assertEquals(200, result.getCode()); assertInstanceOf(String.class, result.getData()); } catch (Exception e){ fail(e.getMessage()); } } @Test @Order(4) @DisplayName("测试报名邀请函") void testEnrollInvitationSystem(){ var invitation = restClient.post() .uri("/travel/invitations/abc") .contentType(MediaType.APPLICATION_JSON) .header("Cookie", cookie) .retrieve().body(Invitation.class); assertNotNull(invitation); } @Test @Order(5) @DisplayName("测试取消报名邀请函") void testCancelInvitationSystem(){ var result = restClient.post() .uri("/travel/invitations"+"/abc?cancel") .contentType(MediaType.APPLICATION_JSON) .header("Cookie", cookie) .retrieve().body(Result.class); assertNotNull(result); Assertions.assertEquals(200, result.getCode()); } } 我的应用也能正常启动docker也能运行并且我通过docker容器访问地址也能通过,只有到系统测试给我报错
07-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值