更新时间:2024-10-21 GMT+08:00
分享

开发业务代码

准备工作

  • 下载安装Maven,根据以下步骤配置Maven。
    1. 在<localRepository>标签内添加自己的本地仓库位置路径,这个本地仓库位置是自己创建的。

      D:\apache-maven-3.8.6-bin\repository

      <localRepository>D:\apache-maven-3.8.6-bin\repository</localRepository> 
    2. 修改maven默认的JDK版本。

      在<profiles>标签下添加一个<profile>标签,修改maven默认的JDK版本。

      <profile>     
          <id>JDK-1.8</id>       
          <activation>       
              <activeByDefault>true</activeByDefault>       
              <jdk>1.8</jdk>       
          </activation>       
          <properties>       
              <maven.compiler.source>1.8</maven.compiler.source>       
              <maven.compiler.target>1.8</maven.compiler.target>       
              <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>       
          </properties>       
      </profile>
  • 安装并配置IntelliJ IDEA开发工具。
    1. 在IntelliJ IDEA中选择File > Settings > Bulid,Execution,Deployment > Bulid Tools > Maven。
    2. 在User settings file中配置setting.xml。
    3. 在Local repository中配置自定义的Maven仓库地址。
  • JAVA开发环境的配置。

    AppStage提供的SDK是基于java1.8版本开发的,如果Spring Cloud项目使用java11及以上版本,则不支持使用AppStage提供的SDK进行应用开发。以下步骤以win7环境配置JDK8 64位为例,若已经下载JDK并配置好环境请跳过本步骤。

    1. 下载JDK文件。
    2. 下载完成后按照提示安装,位置自选,比如安装到本地C:\Program Files\Java\jdk1.8.0_131。
    3. 配置Java环境变量:右键“计算机>属性>高级系统设置>环境变量”,进行如下操作。
      1. 新建系统变量JAVA_HOME,变量值为实际JDK安装位置。
      2. 在Path中添加%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin (注意用英文分号分隔)。
      3. 新建系统变量CLASSPATH,变量值为%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar。
      4. 打开命令行窗口,输入“java -version”,显示如图1表示配置成功。
        图1 配置成功示例
  • 获取SDK并进行完整性校验。

操作步骤

  1. 打开本地Spring Cloud项目。
  2. 手动导入SDK jar包。

    1. 在项目目录下新建一个lib目录,存放jar包。
    2. 将本地的jar包复制粘贴至lib目录下。
    3. 将jar导入到项目中。
      1. 选择“File>Project Structure> Project Settings>Module”
      2. 单击“+”,选择“JARs or Directories...”
      3. 选中jar包,单击“apply”。导包完成。

  3. (可选)集成OrgID登录功能。

    DemoOrgidLogin项目用于对接OrgID组织成员账号服务,对接后可以使用OrgID服务完成自身应用的登录、组织管理功能。具体请参考集成OrgID登录功能

  4. 配置微服务。

    1. 微服务接入STS。

      STS提供了微服务之间请求认证以及敏感配置项管理的功能,STS是接入Cloud Map的前提条件,Cloud Map依赖STS认证能力。

      1. 将在AppStage业务控制台中创建的DemoOrgidLogin、DemoServiceAService、DemoServiceBService注册到运维中心的ACMS管理台中,具体请参见微服务注册
        图2 注册微服务
      2. 在DemoOrgidLogin、DemoServiceA、DemoServiceB的pom.xml中添加STS依赖。
        • 如果将SDK放到外部maven仓中,则只需要添加sts-spring-boot依赖。
        • 本例是以本地依赖的方式引入SDK,即手动将本地下载的SDK jar包引入到工程的lib目录下,需要添加的依赖如下所示。实际需要依赖的包只有sts-spring-boot,其他均是间接依赖,若启动过程中需要其他开源依赖也需要手动加入。
        <dependency>      
             <groupId>com.huawei.wisecloud.sts</groupId>
             <artifactId>sts-spring-boot</artifactId>
             <version>1.1.19.100</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/sts-spring-boot-1.1.19.100.jar</systemPath>
        </dependency>
        <dependency>      
             <groupId>com.huawei.wisecloud.sts</groupId>
             <artifactId>sts-key-sdk</artifactId>
             <version>1.1.19.100</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/sts-key-sdk-1.1.19.100.jar</systemPath>
        </dependency>
        <dependency>      
             <groupId>com.huawei.wisecloud.sts</groupId>
             <artifactId>sts-sdk-base</artifactId>
             <version>1.1.19.100</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/sts-sdk-base-1.1.19.100.jar</systemPath>
        </dependency>
        <dependency>      
             <groupId>com.huawei.wisecloud.kms</groupId>
             <artifactId>cloudsoa-security</artifactId>
             <version>1.1.14.101</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/cloudsoa-security-1.1.14.101.jar</systemPath>
        </dependency>
      3. 增加STS配置项。

        在DemoOrgidLogin、DemoServiceA、DemoServiceB的ClassPath下增加application.properties配置文件,本实践配置项如下:

        sts.server.domain=10.33.102.162:8080      #STS接入地址
        sts.config.path=/opt/huawei/certs/jamesService22A/DemoServiceAService/DemoServiceAService.ini       #STS微服务证书路径,IaC3.0会将证书放在固定路径下,格式为/opt/huawei/certs/服务名/微服务名/微服务名.ini
      4. 启动STS。

        在微服务的启动类中添加注解,本实践是在ServiceASpringbootApplication.java、ServiceBSpringbootApplication.java和DemoOrgidLogin的OrgLogin.java文件中添加@EnableStsAutoInitialization(value = "application.properties")注解。注解的含义是启动STS自动初始化,其中value是指定STS的配置文件路径。

    2. 敏感信息配置项托管。
      1. 使用STS的敏感配置项管理功能 ,需要在ACMS中录入敏感配置项,具体请参见录入敏感配置
      2. 在IaC脚本中的业务配置项配置文件中指定敏感配置项取值路径。
      3. 在IaC脚本中的业务配置项属性定义文件中,声明该配置项为敏感配置项。
      4. 在配置文件中增加敏感配置项名称的配置。
      5. 启动敏感配置项自动解密。
      使用OrgID登录时所需的客户端密钥,属于敏感配置项,需要使用STS的配置敏感配置项托管功能。本实践中配置如下:
      1. 在ACMS中录入配置敏感配置项,如图3所示。
        图3 录入敏感配置项
      2. 本实践在IaC脚本DemoOrgidLogin的业务配置项文件config_records.yaml增加一个名为spring.redis.password的敏感配置项,这个敏感配置项是访问Redis的密码。
        spring.redis.password: MicroService/jamesService22A/DemoOrgidLogin/spring.redis.password/default  #Redis访问密码,属于敏感配置项,已被STS(ACMS)纳管,配置路径为:MicroService/服务名/微服务名/敏感配置项名称/敏感配置项标签
      3. 本实践中访问Redis的密码spring.redis.password为敏感配置项,在IaC脚本DemoOrgidLogin的业务配置项属性定义文件config_schema.yaml中声明。
        type: object
        properties:
           spring.redis.password:
             format: sensitive
      4. 在application.yml配置文件中增加敏感配置项名称的配置。
        nuwa:
           security:
             config:
               sensitiveWords: spring.redis.password,org.app.protocol-login.oauth.clientSecret,org.app.jwt-key
      5. 在DemoOrgidLogin的启动类中添加注解,启动敏感配置项自动解密。本实践是在OrgLogin.java文件中添加@EnableStsEncryptableProperties注解。
    3. 微服务接入Cloud Map。
      Spring Cloud通常是使用其自带的Eureka注册中心,接入AppStage可以将Eureka注册中心替换为Cloud Map,Cloud Map其优势为除了能够提供服务发现的功能,还可以提供数据库、敏感信息等的纳管功能。
      1. 在DemoOrgidLogin、DemoServiceA、DemoServiceB的pom.xml中添加Cloud Map依赖。
        • 如果将SDK放到外部maven仓中,则只需要添加nuwa-cloudmap-core依赖。
        • 本例是以本地依赖的方式引入SDK,即手动将本地下载的SDK jar包引入到工程的lib目录下,需要添加的依赖如下所示。实际需要依赖的包只有nuwa-cloudmap-core,其他均是间接依赖,若启动过程中需要其他开源依赖也需要手动加入。
        <dependency>     
             <groupId>com.huawei.wisecloud.nuwa</groupId>
             <artifactId>spring-cloud-starter-cloudmap-discovery</artifactId>
             <version>1.0.12.100</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/spring-cloud-starter-cloudmap-discovery-1.0.12.100.jar</systemPath>
        </dependency>
        <dependency>     
             <groupId>com.huawei.wisecloud.nuwa</groupId>
             <artifactId>nuwa-cloudmap-core</artifactId>
             <version>1.0.12.100</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/nuwa-cloudmap-core-1.0.12.100.jar</systemPath>
        </dependency>
        <dependency>     
             <groupId>com.huawei.wisecloud.nuwa</groupId>
             <artifactId>nuwa-cloudmap-spring-boot-starter</artifactId>
             <version>1.0.12.100</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/nuwa-cloudmap-spring-boot-starter-1.0.12.100.jar</systemPath>
        </dependency>
      2. 增加Cloud Map配置项。

        本实践分别在DemoServiceA、DemoServiceB的application.yaml配置文件及DemoOrgidLogin的application.yml文件中添加以下配置项:

        nuwa:
          cloudmap:
            read: cloudmap                              #使用Cloud Map方式进行微服务间通信
            clusterName: SpringCloudDemo                #微服务注册到Cloud Map的集群 
            provider:
              cluster: SpringCloudDemo                  #提供服务的其他同样被注册到Cloud Map的微服务集群名 
            serverAddr: http://10.34.32.243:80          #Cloud Map访问地址
            version: 1.0.0.100                          #微服务版本号
            namespaceName: cn_dev_default               #Cloud Map访问命名空间
      3. 启动初始化Cloud Map,将微服务注册到Cloud Map。

        在微服务的启动类中添加注解,本实践是在ServiceASpringbootApplication.java、ServiceBSpringbootApplication.java和DemoOrgidLogin的OrgLogin.java文件中添加@EnableDiscoveryClient注解。同时在启动类中完成将RestTemplate注册到spring容器中,后续微服务间调用使用注册到spring容器中的RestTemplate,代码如下:

        package com.huawei.demo.servicea;
        
        import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
        import org.springframework.cloud.client.loadbalancer.LoadBalanced;
        import org.springframework.context.annotation.Bean;
        import org.springframework.web.client.RestTemplate;
        
        import com.huawei.wisesecurity.sts.springboot.security.annotation.EnableStsAutoInitialization;
        
        @SpringBootApplication
        @EnableStsAutoInitialization(value = "application.properties")
        @EnableDiscoveryClient
        public class ServiceASpringbootApplication {
            public static void main(String[] args) {
                SpringApplication.run(ServiceASpringbootApplication.class, args);
            }
        
            @Bean
            @LoadBalanced
            public RestTemplate restTemplate() {
                return new RestTemplate();
            }
        }

        微服务间调用:

        public OrderInfo findOrder(String orderId, HttpServletRequest request) {
                OrderInfo orderInfo = orderMapper.getOrderById(orderId);
                String url = demoServiceAUrl + "/user/" + orderInfo.getUserId();
                HttpHeaders headers = createHeaders(request);
                HttpEntity<String> entity = new HttpEntity<>(null, headers);
                ResponseEntity<UserInfo> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, UserInfo.class); ;
                if (responseEntity != null) {
                    orderInfo.setUserInfo(responseEntity.getBody());
                }
                return orderInfo;
            }
      4. 在AppStage运维中心的Cloud Map中验证微服务注册,具体请参见查看微服务列表
        图4 验证微服务注册
    4. 使用WiseDBA进行数据库纳管。
      1. 在AppStage运维中心的WiseDBA中申请数据库并创建Schema,具体请参见创建数据库实例及创建Schema

        本实践中申请的数据库性能规格为:独享型/gaussdb.mysql.large.x86.8/2vCPUs/16GB,数据库实例名称为:gauss-SpringCloudDemo2,DemoServiceAService和DemoServiceBService的Schema名称分别为:springclouddemoa、springclouddemob。

      2. 在WiseDBA管理台配置连接信息,并注册到Cloud Map中,在创建数据库连接时,直接调用Cloud Map中的注册信息。
        单击WiseDBA实例列表中的数据库实例名称,单击左侧导航栏的“SDK配置”,新增微服务和数据库的对应配置,具体请参见新增SDK配置,本实践中配置如图5所示。
        图5 SDK配置
      3. 在DemoServiceA和DemoServiceB的pom.xml中添加Rainbow SDK依赖。
        • 如果将SDK放到外部maven仓中,则只需要添加rainbow-proxy依赖。
        • 本例是以本地依赖的方式引入SDK,即手动将本地下载的SDK jar包引入到工程的lib目录下,需要添加的依赖如下所示。实际需要依赖的包只有rainbow-proxy,其他均是间接依赖,若启动过程中需要其他开源依赖也需要手动加入。
        <dependency>          
             <groupId>com.huawei.wisecloud.nuwa</groupId>
             <artifactId>rainbow-proxy</artifactId>
             <version>1.2.18.102</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/rainbow-proxy-1.2.18.102.jar</systemPath>
        </dependency>
        <dependency>          
             <groupId>com.huawei.wisecloud.nuwa</groupId>
             <artifactId>rainbow-core-drds</artifactId>
             <version>1.2.18.201</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/rainbow-core-drds-1.2.18.201.jar</systemPath>
        </dependency>
        <dependency>        
             <groupId>com.huawei.wisecloud.gpaas</groupId>
             <artifactId>gpaas-middleware-common</artifactId>
             <version>2.2.6.100</version>
             <scope>system</scope>
             <systemPath>${project.basedir}/lib/gpaas-middleware-common-2.2.6.100.jar</systemPath>
        </dependency>
      4. 初始化Rainbow。
        在DemoServiceA、DemoServiceB的com/huawei/demo/servicea/config/下添加ApplicationAutoConfig.java文件,代码如下:
        package com.huawei.demo.serviceb.config;
        
        import javax.sql.DataSource;
        
        import org.mybatis.spring.SqlSessionFactoryBean;
        import org.mybatis.spring.mapper.MapperScannerConfigurer;
        import org.springframework.context.EnvironmentAware;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.context.annotation.DependsOn;
        import org.springframework.context.annotation.Import;
        import org.springframework.core.Ordered;
        import org.springframework.core.annotation.Order;
        import org.springframework.core.env.Environment;
        import org.springframework.jdbc.core.JdbcTemplate;
        import org.springframework.jdbc.datasource.DataSourceTransactionManager;
        import org.springframework.transaction.support.TransactionTemplate;
        
        import com.huawei.nuwa.map.client.NuwaMapClient;
        import com.huawei.nuwa.map.spring.boot.autoconfigure.NuwaCloudMapAutoConfiguration;
        import com.huawei.rainbow.jdbc.DbGroupDataSource;
        import com.huawei.wisesecurity.sts.springboot.security.configuration.StsEncryptablePropertiesConfiguration;
        
        /**
         * Rainbow启动
         */
        @Configuration
        @Order(Ordered.HIGHEST_PRECEDENCE)
        @Import(value = {NuwaCloudMapAutoConfiguration.class, StsEncryptablePropertiesConfiguration.class})
        public class ApplicationAutoConfig implements EnvironmentAware {
            private Environment environment;
        
            /**
             * Rainbow需要依赖STS和Cloud Map启动,创建dataSource
             *
             * @param client NuwaMapClient值对象
             * @return DataSource 初始化完成的数据源数据源
             */
            @Bean
            @DependsOn({"stsBootStrap"})
            public DataSource createDataSource(NuwaMapClient client) {
                DbGroupDataSource dataSource = new DbGroupDataSource();
                dataSource.setUseSts(true);
                dataSource.setAppName(environment.getProperty("wiseDba.appName"));
                dataSource.setDbGroupKey(environment.getProperty("wiseDba.groupKey"));
                dataSource.setDbName(environment.getProperty("wiseDba.dbName"));
                dataSource.init();
                return dataSource;
            }
        
            /**
             * 事务管理创建
             *
             * @param dataSource 数据源
             * @return DataSourceTransactionManager 事务管理
             */
            @Bean
            public DataSourceTransactionManager createTransaction(DataSource dataSource) {
                DataSourceTransactionManager transaction = new DataSourceTransactionManager();
                transaction.setDataSource(dataSource);
                return transaction;
            }
        
            @Bean
            public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
                return new JdbcTemplate(dataSource);
            }
        
            @Bean("sqlSessionFactoryBean")
            public SqlSessionFactoryBean createMybatisSqlSessionFactoryBean(DataSource dataSource) {
                SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
                sessionFactoryBean.setDataSource(dataSource);
        
                // 数据源配置项
                org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        
                //允许jdbc自动生成主键
                configuration.setUseGeneratedKeys(true);
        
                // 使用列标签代替列名
                configuration.setUseColumnLabel(true);
        
                // 打开下划线命名自动转换为驼峰命名开关
                configuration.setMapUnderscoreToCamelCase(true);
                sessionFactoryBean.setConfiguration(configuration);
                return sessionFactoryBean;
            }
        
            @Bean
            public TransactionTemplate createTransactionTemplate(DataSourceTransactionManager dataSourceTransactionManager) {
                TransactionTemplate template = new TransactionTemplate();
                template.setTransactionManager(dataSourceTransactionManager);
                return template;
            }
        
            @Bean
            public MapperScannerConfigurer createMapperScannerConfigurer() {
                MapperScannerConfigurer configurer = new MapperScannerConfigurer();
                configurer.setBasePackage("com.huawei.demo");
                configurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
                return configurer;
            }
        
            @Override
            public void setEnvironment(Environment environment) {
                this.environment = environment;

相关文档