跳至主要內容

项目开发技术分享

龚帅大约 7 分钟

项目开发技术分享

  • IDEA基础配置
  • 平时开发时项目搭建
  • 项目部署

IDEA基础配置##

tomcat项目的搭建和启动,端口信息

  • 外置tomcat启动项目
    将项目打成war包,使用外部tomcat容器进行项目启动,项目中需要修改的配置如下
    1.在项目中的pom文件依赖中加入以下依赖
       <--provided依赖,在编译和测试过程中有效,最后生成的war包时不会加入-->
       <--compile 编译、测试、运行过程中有效,默认范围-->
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

2.修改springboot启动类,如下图所示
drawing


3.修改pom的打包方式为war方式
drawing


4.执行maven的package命令,打成war包
drawing


5.配置tomcat信息
第一步:选择tomcat容器目录
第二步:选择指定war包
第三步:指定war包的项目名,若指定该项目名则访问该项目的时候必须加上项目名才能访问
drawing
drawing

  • 内置tomcat启动
    springboot内置tomcat容器,直接启动Application文件即可

项目启动乱码解决
tomcat的默认收集的日志编码为utf-8,而windows系统中文环境是GBK,会导致乱码,修改以下对应的编码配置即可
drawing


打印日志乱码或者控制台输出乱码,java启动参数加上图中的配置
drawing

平时开发时项目搭建

  • 本地项目
    本地开发环境为使用springboot开发,具体目录结构如下图所示。

模块介绍
application:组织机构、业务模块、启动模块
db-version:数据库版本管理模块,管理脚本信息
src:项目统一配置目录,根据不同的环境选择不同的配置,在application文件中使用 即可使用src目录下配置文件的参数
在starter模块下的pom文件中的build节点下加入以下代码,配置根据不同的环境加载不同的配置(指定src目录下的配置文件),参考代码如下(路径根据实际情况改变)

<filters>      <filter>../../src/main/filters/config-${profile.active}.properties</filter>
</filters>

  • 公司开发环境
    将开发环境部署到公司服务器,提供给前端开发使用,参考jenkins 项目:jenkins项目open in new window
    前端开发人员直接连接公司开发环境进行开发,省去本地搭建后端服务的步骤

关键配置如下图所示:

import java.io.File

new File(build.workspace.toString()+'/docker/').mkdir()

// 相关参数
def cnName = 'SSMS'
def projectRoot = 'srig-ssms'
def projectName = 'server'
// 镜像名称
def dockerImageName = 'srig/sirg_ssms_server'
// 容器名称
def dockerInstName  = 'srig-ssms-server'
// 内网访问端口
def dockerPort = '30000'
// 数据存储目录
def dataRoot = '/home/project/'


// 1.  Dockerfile
def dockerfile = """FROM java:8
# 将jar包添加到容器中并更名为app.jar
ADD ./side-slope-monitor.jar app.jar
ADD ./geo.lic nullgeo.lic
ADD ./echarts-convert/ datadir/echarts-convert
ADD ./kmls/ datadir/kmls
ADD ./fonts/ /usr/share/fonts


# 运行jar包
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

## 解决时区的问题
ENV TZ=Asia/Shanghai

## 解决中文乱码
ENV LC_ALL C.UTF-8

"""

new File(build.workspace.toString()+'/docker','Dockerfile').withWriter('utf-8') { 
         writer -> writer.writeLine dockerfile
}

// 2.  build.bat
def buildbat = "docker build -f ./Dockerfile -t ${dockerImageName}:latest ."

new File(build.workspace.toString()+'/docker','build.sh').withWriter('utf-8') { 
         writer -> writer.writeLine buildbat
}

// 3.  deploy.bat
def deploybat = """docker stop ${dockerInstName} && docker rm ${dockerInstName}
docker run --name ${dockerInstName} --restart=on-failure:10 -p ${dockerPort}:8080  -v \$(pwd)/datadir:/datadir  --label io.portainer.accesscontrol.teams=srig --link srig-ssms-dev-warn:srig-ssms-dev-warn --link ssms_elasticsearch:ssms_elasticsearch -d ${dockerImageName}
"""
new File(build.workspace.toString()+'/docker','deploy.sh').withWriter('utf-8') { 
         writer -> writer.writeLine deploybat
}
  • 数据库脚本
    一般配置flyway插件就只配置了一个数据库,如果多个数据库需要同步更新就麻烦,所以配置了flyway多数据源同步更新,application配置如下。
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    //主数据源配置
    @Primary
    @Bean(name = "ds1DataSourceProperties")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSourceProperties ds1DataSourceProperties() {
        return new DataSourceProperties();
    }

    //主数据源
    @Primary
    @Bean(name = "ds1DataSource")
    public DataSource ds1DataSource(@Qualifier("ds1DataSourceProperties") DataSourceProperties dataSourceProperties) {
        return dataSourceProperties.initializeDataSourceBuilder().build();
    }

//第二个数据源配置
@Bean(name = "ds2DataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSourceProperties ds2DataSourceProperties() {
    return new DataSourceProperties();
}

//第二个数据源
@Bean("ds2DataSource")
public DataSource ds2DataSource(@Qualifier("ds2DataSourceProperties") DataSourceProperties dataSourceProperties) {
    return dataSourceProperties.initializeDataSourceBuilder().build();
}

//第三个数据源配置
@Bean(name = "ds3DataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.db3")
public DataSourceProperties ds3DataSourceProperties() {
    return new DataSourceProperties();
}

//第三个数据源
@Bean("ds3DataSource")
public DataSource ds3DataSource(@Qualifier("ds3DataSourceProperties") DataSourceProperties dataSourceProperties) {
    return dataSourceProperties.initializeDataSourceBuilder().build();
}

//第四个数据源配置
@Bean(name = "ds4DataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.db4")
public DataSourceProperties ds4DataSourceProperties() {
    return new DataSourceProperties();
}

//第四个数据源
@Bean("ds4DataSource")
public DataSource ds4DataSource(@Qualifier("ds4DataSourceProperties") DataSourceProperties dataSourceProperties) {
    return dataSourceProperties.initializeDataSourceBuilder().build();
}
}   

执行脚本文件程序,代码如下

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
public class FlywayDbInitializer {
@Resource(name = "ds1DataSource")
private DataSource dataSource1;
@Resource(name = "ds2DataSource")
private DataSource dataSource2;
@Resource(name = "ds3DataSource")
private DataSource dataSource3;
@Resource(name = "ds4DataSource")
private DataSource dataSource4;
@PostConstruct
public void migrateFlyway() {
// 如果sql脚本文件内容含有${ 信息,需要设置为false,否则会执行出错
    Flyway flyway1 = Flyway.configure().placeholderReplacement(false).dataSource(dataSource1).load();
    Flyway flyway2 =Flyway.configure().placeholderReplacement(false).dataSource(dataSource2).load();
    Flyway flyway3 =Flyway.configure().placeholderReplacement(false).dataSource(dataSource3).load();
    Flyway flyway4 =Flyway.configure().placeholderReplacement(false).dataSource(dataSource4).load();
    flyway1.repair();
    flyway1.migrate();
    log.info("**************************************************************************");
    log.info("数据库1已执行,sql版本执行到:【{}】",flyway1.info().getInfoOutput().schemaVersion);
    flyway2.repair();
    flyway2.migrate();
    log.info("**************************************************************************");
    log.info("数据库2已执行,sql版本执行到:【{}】",flyway2.info().getInfoOutput().schemaVersion);
    flyway3.repair();
    flyway3.migrate();
    log.info("**************************************************************************");
    log.info("数据库3已执行,sql版本执行到:【{}】",flyway3.info().getInfoOutput().schemaVersion);
    flyway4.repair();
    flyway4.migrate();
    log.info("**************************************************************************");
    log.info("数据库4已执行,sql版本执行到:【{}】",flyway4.info().getInfoOutput().schemaVersion);
}
}

项目部署

  • docker安装
    # 安装依赖
    yum install -y yum-utils device-mapper-persistent-data lvm2

    # 添加docker下载仓库
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

    # 安装docker-ce
    yum install docker-ce

    # 启动docker-ce
    systemctl start docker

    # 验证
    docker --version
  • docker-compose安装
    简介:Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务,服务器安装步骤如下,windows环境自动安装了compose环境。
#步骤1
curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

#步骤2
chmod +x /usr/local/bin/docker-compose

#步骤3
docker-compose --version

docker-compose.yml文件示例如下

version: '2'
services:
  db:
    image: 'mysql:latest'
    restart: always
    container_name: mysql    
    privileged: true
    environment:
      MYSQL_USER: ssms
      MYSQL_PASSWORD: scsz2021
      MYSQL_DATABASE: ssms
      MYSQL_ROOT_PASSWORD: 10decade10
    ports:
      - '3306:3306'
  • 镜像准备
    制作docker镜像首先需要准备dockerfile,docker更具dockerfile文件来创建镜像。
    以后台系统部署为例,编写dockerfile文件,文件内容如下
        FROM java:8
        # 将jar包添加到容器中并更名为app.jar
        ADD ./build/side-slope-monitor.jar app.jar
        ADD ./build/application.properties application.properties
        ADD ./build/kmls/ data/kmls
        ADD ./build/fonts/ /usr/share/fonts
        ADD ./build/geo.lic config/

        ## 解决时区的问题
        ENV TZ=Asia/Shanghai
        
        ## 解决中文乱码
        ENV LC_ALL C.UTF-8
        ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

以前端项目为列,编写dockerfile文件,文件内容如下

FROM nginx
ADD dist/ /usr/share/nginx/html/
ADD build/default.conf /etc/nginx/conf.d/
## 解决时区的问题
ENV TZ=Asia/Shanghai

## 解决中文乱码
ENV LC_ALL en_US.UTF-8

docker部署

所有项目均采用docker部署,在公司服务器构建镜像,从正式服务器拉取镜像部署项目

1.jenkins制作并上传镜像
拉取源码,指定分支(如果使用了tag,则参考图中配置,如果没有则参考配置 */develop)
drawing

创建镜像(需要代码里面有Dockerfile文件),主要步骤如下图所示
drawing

步骤解释:
step1:指定Dockerfile的目录,顶层目录从项目的目录开始
step2:指定服务器来创建镜像
step3:指定镜像的名字和版本
step4:勾选是否推送镜像到私有的dock而仓库
step5:docker镜像推送服务

2.从公司服务器拉取镜像
docker pull docker.clzytech.com:1024/srig/srig-awr-demo:latest

3. 编写deploy脚本
创建deploy.sh文件,文件内容如下

docker pull docker.clzytech.com:1024/srig/srig-awr-demo:latest
docker stop srig-awr-demo && docker rm srig-awr-demo
docker run --name srig-awr-demo --restart=on-failure:10 -p 10000:80 -d docker.clzytech.com:1024/srig/srig-awr-demo:latest

本地创建docker镜像的方式
1.将Dockerfile文件以及Dockerfile文件中配置的需要的文件按照配置目录拷贝到一起

2.在Dockerfile文件目录执行镜像构建命令,命令格式为docker build -f ./Dockerfile -t 镜像名:版本 .
切勿漏掉最后的那个点,参考命令如下

docker build -f ./Dockerfile -t srig-v2x:1.0 .

3.执行docker run命令运行容器

docker run --name srig-v2x -v $(pwd)/logs:/logs -v $(pwd)/app.jar:/app.jar -v $(pwd)/application.properties:/application.properties -d srig-v2x:1.0

--name:指定容器名
-v:路径、文件映射
-d:后台运行
srig-v2x:1.0 :指定容器名和版本
--link name or id:alias
链接2个容器,使得容器之间可以互相通信,name和id是源容器的name和id,alias是源容器在link下的别名。