Spring Cloud开发实践(六): 基于Consul和Spring Cloud 2021.0的演示项目

目录

  • Spring Cloud开发实践(一): 简介和根模块
  • Spring Cloud开发实践(二): Eureka服务和接口定义
  • Spring Cloud开发实践(三): 接口实现和下游调用
  • Spring Cloud开发实践(四): Docker部署
  • Spring Cloud开发实践(五): Consul - 服务注册的另一个选择
  • Spring Cloud开发实践(六): 基于Consul和Spring Cloud 2021.0的演示项目

Consul 服务

启动Consul服务, 在Win10下可以执行以下命令, 或者存成bat文件运行, 保持窗口打开

consul agent -dev -client=0.0.0.0 -data-dir .\ -advertise 127.0.0.1 -ui -config-dir .\

浏览器访问 http://127.0.0.1:8500 , 用于观察后面注册的Node和Health情况

Spring Cloud 项目

这个演示项目使用的 Spring Boot 和 Spring Cloud 都不是最新版本, 因为最新版本最低要求 JDK17. 这里选择的是对应 JDK11 可用的最高版本, 各组件版本明细为

  • Consul 1.15
  • JDK 11
  • Spring Boot 2.7.11
  • Spring Cloud 2021.0.6

整体结构

这个用于演示的项目名称为 Dummy, 包含3个子模块, 分别是 dummy-common-api, dummy-common-impl 和 dummy-admin, 其中

  • dummy-common-api 和 dummy-common-impl 逻辑上属于同一个模块 dummy-common. api 是对外输出的接口, impl是对应的实现
  • dummy-admin 依赖 dummy-common-api , 使用其提供的接口

打包后, 需要部署的是两个jar: dummy-common.jar 和 dummy-admin.jar, 前者提供服务接口, 后者消费前者提供的接口, 并对外(例如前端, 小程序, APP)提供接口

项目的整体结构如下

│   pom.xml
├───dummy-admin
│   │   pom.xml
│   ├───src
│   │   ├───main
│   │   │   ├───java
│   │   │   └───resources
│   │   │           application.yml
│   │   └───test
│   └───target
├───dummy-common-api
│   │   pom.xml
│   ├───src
│   │   ├───main
│   │   │   ├───java
│   │   │   └───resources
│   │   └───test
│   └───target
└───dummy-common-impl
    │   pom.xml
    ├───src
    │   ├───main
    │   │   ├───java
    │   │   └───resources
    │   │           application.yml
    │   └───test
    └───target

根模块 Dummy

根模块的 pom.xml 中,

  • 定义了子模块, module标签中的内容, 要和子模块目录名一致.
  • 设置JDK版本 11
  • 引入全局 Spring Boot Dependencies, 版本 2.7.11
  • 引入全局 Spring Cloud Dependencies, 版本 2021.0.6
  • 还有一些是Plugin相关的版本, 略
<?xml version="1.0" encoding="UTF-8"?>
    ...
    <name>Dummy: Root</name>
    <modules>
        <module>dummy-common-api</module>
        <module>dummy-common-impl</module>
        <module>dummy-admin</module>
    </modules>

    <properties>
        <!-- Global encoding -->
        <project.jdk.version>11</project.jdk.version>
        <project.source.encoding>UTF-8</project.source.encoding>

        <!-- Global dependency versions -->
        <spring-boot.version>2.7.11</spring-boot.version>
        <spring-cloud.version>2021.0.6</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot Dependencies -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Cloud Dependencies -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <build>
        ...
    </build>

</project>

Dummy Common API 模块

这个模块用于生成依赖的jar包, 作用非常重要. 以下详细说明

pom.xml 中除了定义和父模块的关系, 需要引入 openfeign

<?xml version="1.0" encoding="UTF-8"?>
    ...
    <parent>
        <groupId>com.rockbb.test</groupId>
        <artifactId>dummy</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>dummy-common-api</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>

    <name>Dummy: Commons API</name>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        ...
    </dependencies>

    <build>
        ...
    </build>
</project>

定义一个 UserDTO, 这个是用于传输的数据对象

@Data
public class UserDTO implements Serializable {
    private Long id;
    private String name;
}

对应的服务接口. 这里用到了 @FeignClient 注解

  • @FeignClient 是给 dummy-admin 模块用的
    • name= CommonConstant.SERVICE_NAME 就是 "dummy-common", 因为这个API模块中所有Service接口都使用同样的名称, 这边做成常量
    • contextId = "userDTOService" 如果不加这个参数, 多个 FeignClient 使用同样的 name 时, 就会冲突. 这个一般直接定义为这个 service 的bean名称
    • path = "/userDTOService" 用于指定当前类中所有接口的请求前缀. 在更早的版本中, 可以将 @RequestMapping 和 @FeignClient 联用, 这个是定义在 @RequestMapping 中的, 后来不允许了, 因为有安全风险.
  • @GetMapping 和 @PostMapping 同时用于 dummy-admin 和 dummy-common
    • 对于 dummy-admin, 这就是 FeignClient 的请求路径
    • 对于 dummy-common, 这就是 Contoller 方法的服务路径
    • 需要注意 @GetMapping 请求的接口形式, 必须显式添加 @RequestParam("id") 这类 GET 模式的参数注解, 否则使用 @GetMapping 的 Feign 请求也会被转为 POST 而导致请求错误.
@FeignClient(name = CommonConstant.SERVICE_NAME, contextId = "userDTOService", path = "/userDTOService")
public interface UserDTOService {

    @GetMapping("/get")
    UserDTO get(@RequestParam("id") long id);

    @PostMapping("/add")
    int add(@RequestBody UserDTO dto);
}

在 dummy-admin 中, 这个接口会被实例化为 feign 代理, 在模块中可以像普通 service 一样调用, 而在 dummy-common 中, 不引入 feign 依赖, 或者在 @EnableFeignClients 的 basePackages 中避开本包路径, 就会忽略这个注解, 从而实现模块间接口的关联.

与现在很多 Spring Cloud 项目中单独拆出一个 Service 模块的做法, 这种实现有很多的优点

  • 开发过程友好. 与单机开发几乎一样的代码量, 唯一区别是要注意 Get 和 Post 对请求参数的格式和个数的约束
  • 易重构易扩展. 可以借助 IDE 的代码分析能力, 改动自动标红, 避免人为错误和遗漏
  • 性能开销小, 如果 DTO 直接映射到数据库字段, 可以全程使用一个类.

Dummy Common Impl 模块

模块的 pom.xml

  • 引入 spring-boot-starter-web, 因为要提供 RestController 的能力
  • 引入 spring-cloud-starter-consul-discovery 或 spring-cloud-starter-consul-all, 因为要接 Consul
  • 引入 dummy-common-api 依赖, 因为 Controller 请求定义在 API 中
  • 打包使用 spring-boot-maven-plugin 的 repackage, 因为要打 fat jar, 在服务器上实现单包部署
<?xml version="1.0" encoding="UTF-8"?>
    ...
    <name>Dummy: Common Implementation</name>

    <dependencies>
        <!-- Spring Boot Dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Cloud Dependencies  consul-discovery 和 consul-all 二选一 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-all</artifactId>
        </dependency>
        ...
        <dependency>
            <groupId>com.rockbb.test</groupId>
            <artifactId>dummy-common-api</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>dummy-common</finalName>
        <resources>
            ...
        </resources>
        <plugins>
            ...
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

配置部分 application.yml

  • 定义服务端口 8762
  • 定义 servlet 路径, 必须定义, 否则不会配置 Controller 请求
  • spring.application.name: dummy-common 定义了本服务的名称, 这个名称就是在 FeignClient 中引用的服务名称, 需要与 FeignClient 中的值一致
  • spring.config.import 如果使用这个设置, 依赖要使用 consul-all, 因为 consul-discovery 中不带 consul-config. 使用这个设置后, 会自动使用默认的 Consul 地址和端口
  • cloud.consul.host 和 port 如果使用了config.import, 在这里可以修改默认的值, 如果不使用config.import, 则必须配置 host 和 port, 依赖可以换成 consul-discovery
  • cloud.consul.discovery.health-check-path 用于更改默认的 health 检查请求路径, 默认的是 /actuator/health, 这里改为 /health
  • cloud.consul.discovery.instance-id 用于定义当前实例在 Consul 里的实例ID. 默认使用 application.name-port, 如果正好这个服务在两个服务器上分别跑了一个实例, 且实例端口一样, 就会产生冲突, 可以改为 application.name-[随机串] 的形式避免冲突
server:
  port: 8762
  tomcat:
    uri-encoding: UTF-8
  servlet:
    context-path: /

spring:
  application:
    name: dummy-common

  config:
    import: 'optional:consul:' #This will connect to the Consul Agent at the default location of "http://localhost:8500"

#  cloud:
#    consul:
#      host: 127.0.0.1
#      port: 8500
#      discovery:
#        health-check-path: /health # replace the default /actuator/health
#        instance-id: ${spring.application.name}:${random.value}

代码部分, 首先是实现 health 检查的处理方法, 这部分是普通的 RestController 方法. 返回字符串可以任意指定, 只要返回的 code 是 200 就可以

@RestController
public class HealthCheckServiceImpl {

    @GetMapping("/health")
    public String get() {
        return "SUCCESS";
    }
}

服务接口的实现类, 这里实现了两个接口方法 get 和 add

  • 使用 @RestController 注解, 与 API Service 中方法上的 @GetMapping 和 @PostMapping 配合, 将 Service 方法映射为 Controller 方法
  • 在类上的 @RequestMapping("userDTOService") 方法是必须的, 因为在 API Service 中与 @FeignClient 冲突无法定义, 只能在这里定义
  • 方法和参数上除了 @Override 不需要任何注解, 因为都在 API Service 上定义过了. 这里加上注解也没问题, 但是要手工保持一致.
@RestController
@RequestMapping("userDTOService")
public class UserDTOServiceImpl implements UserDTOService {

    @Autowired
    private UserRepo userRepo;

    @Override
    public UserDTO get(long id) {
        log.debug("Get user: {}", id);
        UserDTO user = new UserDTO();
        user.setId(id);
        user.setName("dummy");
        return user;
    }

    @Override
    public int add(UserDTO dto) {
        log.debug("Add user: {}", dto.getName());
        return 0;
    }
}

dummy-common 模块运行后会将接口注册到 Consul, 启动后注意观察两部分:

  1. Consul 的日志输出和控制面板显示, 在-dev模式下, 节点注册后 Consul 日志会显示模块的名称和心跳检测记录, 面板上会显示新的 Node
  2. Consul 控制面板中显示的 Health Checks 是否正常, 如果不正常, 需要检查 /health 路径为什么访问失败

Dummy Admin 模块

dummy-admin 是调用接口, 并对外提供服务的模块

pom.xml 和 dummy-common 基本一样, 因为都要连接 Consul, 都要提供 Controller 方法

<?xml version="1.0" encoding="UTF-8"?>
    ...
    <name>Dummy: Admin API</name>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>com.rockbb.test</groupId>
            <artifactId>dummy-common-api</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>dummy-admin</finalName>
        <resources>
           ...
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
</project>

在主应用入口, 除了 @SpringBootApplication 以外, 还需要增加两个注解

  • @EnableDiscoveryClient(autoRegister=false) 连接到 Consul 并使用服务发现, 默认会将当前节点也注册到 Consul 作为服务. 对于纯消费节点, 不对其它节点提供接口的, 使用 autoRegister=false 可以避免将自己注册到 Consul
  • @EnableFeignClients(basePackages = {"com.rockbb.test.dummy.common.api"}) 扫描对应的包, 对 @FeignClient 注解实例化接口代理
/* Attach to discovery service without registering itself */
@EnableDiscoveryClient(autoRegister=false)
@EnableFeignClients(basePackages = {"com.rockbb.test.dummy.common.api"})
@SpringBootApplication
public class AdminApp {
    public static void main(String[] args) {
        SpringApplication.run(AdminApp.class, args);
    }
}

在调用方法的地方, 按普通 Service 注入和调用

@Slf4j
@RestController
public class IndexController {

    @Autowired
    private UserDTOService userDTOService;

    @GetMapping(value = "/user_get")
    public String doGetUser() {
        UserDTO user = userDTOService.get(100L);
        return user.getId() + ":" + user.getName();
    }

    @GetMapping(value = "/user_add")
    public String doAddUser() {
        UserDTO user = new UserDTO();
        user.setName("foobar");
        int result = userDTOService.add(user);
        return String.valueOf(result);
    }

可以通过注入的 DiscoveryClient 对象, 查看对应服务的服务地址(一般不需要)

@Autowired
private DiscoveryClient discoveryClient;

@GetMapping("/services")
public Optional<URI> serviceURL() {
    return discoveryClient.getInstances(CommonConstant.SERVICE_NAME)
            .stream()
            .map(ServiceInstance::getUri)
            .findFirst();
}

参考

  • Consul和Spring Boot非常详细的配置教程 http://medium.com/javarevisited/hands-on-consul-with-spring-boot-1ebf2918165c
本文转载于网络 如有侵权请联系删除

相关文章

  • tcp滑动窗口和读写缓冲区

    最近突然忘记了滑动窗口的原理,在网上找到了比较好的视频,现在在这里同大家分享:注:反正进程间切换视频链接:https://www.youtube.com/watch?v=R6ArbkVj-N8资源来源自网络,如果对您有帮助请点击推荐,如果有其他的任何问题,欢迎大家留言!cnblogs.com/xuyaowen

  • Keras:Unet网络实现多类语义分割方式

    1介绍U-Net最初是用来对医学图像的语义分割,后来也有人将其应用于其他领域。但大多还是用来进行二分类,即将原始图像分成两个灰度级或者色度,依次找到图像中感兴趣的目标部分。本文主要利用U-Net网络结构实现了多类的语义分割,并展示了部分测试效果,希望对你有用!2源代码(1)训练模型from__future__importprint_function importos importdatetime importnumpyasnp fromkeras.modelsimportModel fromkeras.layersimportInput,concatenate,Conv2D,MaxPooling2D,Conv2DTranspose,AveragePooling2D,Dropout,\ BatchNormalization fromkeras.optimizersimportAdam fromkeras.layers.convolutionalimportUpSampling2D,Conv2D fromkeras.callbacksimportModelCheckpoint fromke

  • Traceback (most recent call last) 无法定位到元素python+selenium

    Traceback(mostrecentcalllast)?TOC#selenium.common.exceptions.InvalidArgumentException:Message:Expected[objectUndefined]undefinedpython+selenium运行报错,定位元素的方法都正确,但就是找不到元素, 下面是解决办法 查看项目配置 这里提示selenium可以升级 打开dos窗口 先找到python的安装路径 进入到python安装路径 查看目前安装的工具piplist 发现selenium不是最新版,把它卸载掉pipuninstallselenium 再查看,已经卸载成功 安装指定版本的selenium pipinstallselenium==4.0.0a1 查看已经安装成功 现在再运行脚本,就没有问题了。

  • Linux内存初始化(上)

    有了armv8架构访问内存的理解,我们来看下linux在内存这块的初始化就更容易理解了。创建启动页表:在汇编代码阶段的head.S文件中,负责创建映射关系的函数是create_page_tables。create_page_tables函数负责identitymapping和kernelimagemapping。identitymap:是指把idmap_text区域的物理地址映射到相等的虚拟地址上,这种映射完成后,其虚拟地址等于物理地址。idmap_text区域都是一些打开MMU相关的代码。kernelimagemap:将kernel运行需要的地址(kerneltxt、rodata、data、bss等等)进行映射。arch/arm64/kernel/head.S: ENTRY(stext) blpreserve_boot_args blel2_setup//DroptoEL1,w0=cpu_boot_mode adrpx23,__PHYS_OFFSET andx23,x23,MIN_KIMG_ALIGN-1//KASLRoffset,defaultsto0 blset_cpu_boot

  • Amabri 单机踩坑

    生活就是一系列下定决心的努力 ·正·文·来·啦·点击红色“Failed”,查看详细错误:========================== Creatingtargetdirectory... ========================== Commandstarttime2018-11-2722:13:32 chmod:cannotaccess‘/var/lib/ambari-agent/data’:Nosuchfileordirectory Connectiontomaster.hadoopclosed. SSHcommandexecutionfinished host=master.hadoop,exitcode=0 Commandendtime2018-11-2722:13:32 ========================== Copyingambarisudoscript... ========================== Commandstarttime2018-11-2722:13:32 scp/var/lib/ambari-server/

  • 互联网JAVA面试常问问题(五)

    关于JAVA锁,还有以下我们需要知道的。Synchronized中的CAS在面试题(四)中,我们对Synchronized应该有所印象了,它最大的特征就是在同一时刻只有一个线程能够获得对象的监视器(monitor),从而进入到同步代码块或者同步方法之中,即表现为互斥性(排它性)。JAVA1.6之前,在没有引入轻量级锁和偏向锁之前,Synchronized最主要的问题是:在存在线程竞争的情况下会出现线程阻塞和唤醒锁带来的性能问题,因为这是一种互斥同步(阻塞同步)。此时引入CAS,它并不是简单的将线程挂起,当CAS操作失败后会进行一定的尝试,而非进行耗时的挂起唤醒的操作,因此也叫做非阻塞同步。1什么是CAS?CAS的全称是CompareAndSwap,即比较交换,其算法核心思想如下执行函数:CAS(V,E,N)复制其包含3个参数V表示要更新的变量 E表示预期值 N表示新值复制使用锁时,线程获取锁是一种悲观锁策略,即假设每一次执行临界区代码都会产生冲突,所以当前线程获取到锁的时候同时也会阻塞其他线程获取该锁。而CAS操作(又称为无锁操作)是一种乐观锁策略,它假设所有线程访问共享资源的时候不会

  • 使用 iptables 简单配置 Linux 白名单

    1.清除已有规则 [root@local~]#iptables-F [root@local~]#iptables-X [root@local~]#iptables-Z复制2.设置默认规则,其中参数-P代表默认规则,这里设置默认都不可访问 [root@local~]#iptables-PINPUTDROP [root@local~]#iptables-POUTPUTDROP复制3.设置白名单,参数-A代表这里设置10.0.1.0/24和10.0.2.0/24两个网段 [root@local~]#iptables-AINPUT127.0.0.1-jACCEPT [root@local~]#iptables-AINPUT10.0.1.0/24-jACCEPT [root@local~]#iptables-AINPUT10.0.2.0/24-jACCEPT [root@local~]#iptables-AOUTPUT127.0.0.1-jACCEPT [root@local~]#iptables-AOUTPUT10.0.1.0/24-jACCEPT [root@local~]#iptables

  • 迭代器与 for of的使用和原理

    起源一段标准的for循环代码:varcolors=["red","green","blue"]; for(vari=0,len=colors.length;i<len;i++){console.log(colors[i]);}复制看着很简单,但是再回顾这段代码,实际上我们仅仅是需要数组中元素的值,但是却需要提前获取数组长度,声明索引变量等,尤其当多个循环嵌套的时候,更需要使用多个索引变量,代码的复杂度就会大大增加,比如我们使用双重循环进行去重:functionunique(array){varres=[];for(vari=0,arrayLen=array.length;i<arrayLen;i++){for(varj=0,resLen=res.length;j<resLen;j++){if(array[i]===res[j]){break;}}if(j===resLen){res.push(array[i]);}}returnres;}复制为了消除这种复杂度以及减少循环中的错误(比如错误使用其他循环中的变量

  • git提交本地分支到远程分支 转

    git常用命令(含删除文件)Git常用操作命令收集:1)远程仓库相关命令检出仓库:$ git clone git://github.com/jquery/jquery.git查看远程仓库:$ git remote-v添加远程仓库:$ git remoteadd[name][url]删除远程仓库:$ git remoterm[name]修改远程仓库:$ git remoteset-url--push[name][newUrl]拉取远程仓库:$ git pull[remoteName][localBranchName]推送远程仓库:$ gitpush [remoteName][localBranchName]2)分支(branch)操作相关命令查看本地分支:$ git branch查看远程分支:$ git branch-r创建本地分支:$ git branch[name]----注意新分支创建后不会自动切换为当前分支切换分支:$ git checkout[name]创建新分支并立即切换到新分支:$ git checkout-b[name]删除分支:$ git branch-d[name]-

  • 深度优化局部拉普拉斯金字塔滤波器。

    算法概述 基于局部拉普拉斯金字塔的Edge-aware滤波器是在2011年由Adobe公司的研究员SylvainParis(大神级人物,写了很多文章)提出的,我在4年前曾经参考有关代码实现过这个算法,但是速度也是非常慢的,所以当时也没有继续做深入的研究,前段时间做另外一个算法时仔细的研究了下高斯和拉普拉斯金子塔的优化,因此又抽时间仔细的分析了算法的论文和代码,由于论文的理论部分还有一些我没有想清楚,因此在这里我只对研读过程中涉及的代码方面的优化做个解读。经过我最终的优化,处理1920*1024的彩色图,在保证效果不会有明显的瑕疵的取样值的情况下,大概能获得60ms的速度。先分享下参考资料:(1)论文LocalLaplacianFilters:Edge-awareImageProcessingwithaLaplacianPyramid。  (2)论文FastLocalLaplacianFilters:TheoryandApplications (3)函数:matlab2017的locallapfilt函数。 (4)插件:Paint.net的Laplacianpyramidfilteref

  • 每日一题(8)

    一个人的前程旺旺全靠他怎样用闲暇时间上题回顾与解析z=3、x=1、y=2。问z-=--y-x--?对于以下,有intx=5,y=6,z; Q1:z=++x+y++; Q2:z=++x+x++; Q3:z=++x+++x; Q4:x=++x+x++; 各题中,x、y、z结果各是多少解析: java在处理自增自减时,会使用临时变量存储,计算后再返回该值 自增自减原理一样,此处以自增为例j++实现代码相当于://temp为缓存变量 inttemp=j; j=j+1; returntemp;复制++j实现代码相当于://temp为缓存变量 inttemp=j+1; j=j+1; returntemp;复制z-=--y-x--可变形为z=z-((--y)-(x--)) 由上述原理可知,则(--y)为1,(x--)为1,所以z=z-(1-1) 最终,z=3,x=0,y=1Q1:(++x)为6,(y++)为6,y自增后为7最终,z=6+6=12,x=6,y=7 Q2:(++x)为6,此时x=6,(x++)为6,x自增后为7最终,z=6+6=12,x=7 Q3:(++x)为6,此时x=6,(++x)为

  • 中国新型智慧城市榜单:2019哪里最宜居?哪里最有发展潜力?

    导读:近日,国衡智慧、国新智库评估组通过对全国数字经济和智慧城市跨年度持续的跟踪、研究、监测、评估与分析,通报公布2017-2018中国新型智慧城市建设与发展综合影响力评估结果。 中国信息化研究与促进网、国衡智慧城市科技研究院联合太昊国际互联网大数据评级等权威社会第三方研究机构在连续16年开展全国智慧政务优秀成果推荐的基础上,连续第四次组织开展中国新型智慧城市建设与发展综合影响力评估。 本次评估共八大系列,依次为: 第一系列2017-2018年度中国最具影响力智慧城市2017-2018年度中国最具创新力智慧城市第二系列2018年度中国最具投资价值智慧城市2018年度中国最具发展潜力智慧城市第三系列2017-2018年度中国最具旅游特色智慧城市2017-2018年度中国最具魅力宜居智慧城市第四系列2017-2018年度转型升级优秀智慧城市2017-2018年度信息惠民优秀智慧城市第五系列2017-2018年度中国最佳管理实践智慧城镇25强2017-2018年度中国最佳管理实践智慧小镇50强第六系列2017-2018年度中国智慧城市居民互联网生活常用APP2017-

  • AngularJS入门教程:日期格式化

    AngularJS入门教程:日期格式化【转载】本地化日期格式化:({{today|date:'medium'}})Nov24,20152:19:24PM({{today|date:'short'}})11/24/152:19PM({{today|date:'fullDate'}})Tuesday,November24,2015({{today|date:'longDate'}})November24,2015({{today|date:'mediumDate'}})Nov24,2015({{today|date:'shortDate'}})11/24/15({{today|date:'mediumTime'}})2:19:24PM({{today|date:'shortTime'}})2:19PM年份格式化:四位年份:({{today|date:'yyyy'}})2015两位年份:({{today|date:

  • 我的工程师的能力评估和发展

    Part1 虽然是作业,但是我也准备好好地评估一下自己的能力,看看自己到底有多菜鸡,好给自己一个响亮的耳光来督促后面的自我学习!所以我就好好地给自己评估下(参照第二次作业的内容): PSP2.1ContentChinese/中文我的技能需求耗时Plan-Estimate计划-任务时间幕布-思维导图2Devolopment-Analysis开发-分析需求博客园作业指导Github_Readme.md2Devolopment-Spec开发-设计文档简书2.5Devolopment-Review开发-设计复审Devolopment-Standard开发-代码规范Qemu调试1.5Devolopment-Design开发-具体设计阅读老师示例代码0.5Devolopment-Coding开发-具体编码Mac_sublimeC编码5Devolopment-CodeReview开发-代码复审gcc代码(语法)调试结合Github实时更新1Devolopment-Test开发-测试Ubuntu下Qemu测试3RecordTimeSpent记录用时TestReport测试报告简书,博客园博客作业总

  • 数据分析经典图书大全,专治各种不懂!

    一、数据分析-入门篇1.1《谁说菜鸟不会数据分析》作者:张文霖,刘夏璐,狄松简介:本书按照数据分析工作的完整流程来讲解。全书共8章,分别讲解数据分析必知必会的知识、数据处理技巧、数据展现的技术、通过专业化的视角来提升图表之美、数据分析报告的撰写技能以及持续的修炼。本书形式活泼,内容丰富而且充实,让人有不断阅读下去的动力。读者完全可以把这本书当小说来阅读,跟随主人公小白,在Mr.林的指点下轻松掌握数据分析的技能,提升职场竞争能力。1.2《一本书学会做数据分析》作者:李宗民简介:本书结合具体的商务实例对Excel软件和数据分析进行了详细介绍,在分析实例的同时,还穿插了小知识、小技巧等内容,以帮助读者全面了解Excel的主要功能,熟练掌握数据分析的基本方法。本书内容全面、系统,具有很强的实用性。1.3《深入浅出数据分析》作者:米尔顿 著,李芳译简介:本书以类似“章回小说”的活泼形式,生动地向读者展现优秀的数据分析人员应知应会的技术:数据分析基本步骤、实验方法、最优化方法、假设检验方法、贝叶斯统计方法、主观概率法、启发法、直方图法、回归法、误差处理、相关数据库、数据整理技巧;正文以后,意犹未尽

  • 腾讯云TDSQLPostgreSQL版Oracle兼容语法

    Oracle兼容语法说明针对的是TDSQLPostgreSQL版(Oracle兼容版)。 OracleGUC参数配置session中生效SETenable_oracle_compatibletoON;复制 配置某个库默认生效alterdatabasepostgressetenable_oracle_compatibletoon;复制 配置某个用户默认生效alterroletbasesetenable_oracle_compatibletoon;复制 数据类型varchar2postgres=#createtablet_varchar2(f1varchar2,f2int); CREATETABLE postgres=#\d+t_varchar2 Table"public.t_varchar2" Column|Type|Collation|Nullable|Default|Storage|Statstarget|Description --------+----------+-----------+----------+---------+----------+----

  • 数据库入门

    一、数据库的概念 1.数据库的定义 数据库是一个以某种有组织的方式存储的数据集合。 数据库:保存有组织的数据的容器,通常是一个文件或一组文件。 2.数据库管理系统(数据库软件) 数据库管理系统(DBMS):通过它来创建和操纵数据库,常见的DBMS有MySQL、MicrosoftSQLServer、Oracle等。 DBMS的主要目标是提供一种可以方便、高效地存取数据库信息的途径。 3.关系型数据库 关系型数据库:建立在关系模型基础上的数据库,借助于集合、代数等数学概念和方法来处理数据库中的信息。 关系型数据库管理系统(RDBMS):与关系型数据库对应的数据库管理系统。 注:以下的学习以关系型数据库为主!   二、关系型数据库的特点 数据以表的形式出现,若干的表组成数据库 表中的数据是按行存储的,所保存的每个记录存储在自己的行内 表由列组成,每一列都对应着表的一个属性   术语 表 关系 行 元组 列 属性            

  • Xamarin.Android中使用ResideMenu实现侧滑菜单

      上次使用Xamarin.Android实现了一个比较常用的功能PullToRefresh,详情见:Xamarin.Android实现下拉刷新功能 这次将实现另外一个手机App中比较常用的功能:侧滑菜单。通过搜索,发现有很多侧滑菜单,有仿手机QQ的侧滑菜单,有折叠的侧滑菜单,有SlidingMenu等,不过我还是比较喜欢ResideMenu实现的效果,所以想通过Xamarin.Android的绑定实现该效果。这次实现该菜单遇到的问题比较多,花的时间也较多,花了三四个晚上才解决所有的问题。下面是详细的实现步骤: 作者:loyldg出处:http://www.cnblogs.com/loyldg/本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题,可以邮件:loyldg@126.com联系我,非常感谢。 一、生成ResideMenu.dll 从网上下载ResideMenu的源代码,我是下载的master分支的代码,如果有需要可以下载其他分支的代码。 导入到MyEclispe中,编译一下(默认情况导入后会自

  • 【填坑往事】使用Rxjava2的distinct操作符处理自定义数据类型去重的问题

        最近碰到一个问题,自定义数据类型列表中出现了重复数据,需要去重。处理去重的办法很多,比如借助Set集合类,使用双重循环拿每一个元素和其他元素对比等。这里介绍一种简单而且比较优雅的方式:使用Rxjava2中的distinct操作符来实现。     网上介绍这种方式的文章非常多,但基本上都是拿整数类型数据来演示,比如: 1Observable.just(1,1,2,2,3,4).distinct().subscribe(newConsumer<Integer>(){ 2@Override 3publicvoidaccept(Integerinteger)throwsException{ 4Log.d(TAG,"[distinct-accept]integer="+integer); 5} 6});复制 但实际工作中碰到的数据类型却是自定义类型,看到上述代码后本人还是有时有点手足无措,没法直接拿到依葫芦画瓢。后来自己研究了一下,在上述代码基础上转了一个弯,解决了这个问题,下面记录一下。 使

  • JS实现继承 JavaScript

    JS实现继承JavaScript 定义一个父类: //定义一个动物类 functionAnimal(name){ //属性 this.name=name||‘Animal’; //实例方法 this.sleep=function(){ console.log(this.name+‘正在睡觉!’); } } //原型方法 Animal.prototype.eat=function(food){ console.log(this.name+‘正在吃:’+food); }; 复制 1.原型链继承 核心:将父类的实例作为子类的原型,JavaScript常见的六种继承方式 functionCat(){ } Cat.prototype=newAnimal(); Cat.prototype.name=‘cat’; // TestCode varcat=newCat(); console.log(cat.name); console.log(cat.eat(‘fish’)); console.log(cat.sleep()); console.log(catinstanceofAnimal);/

  • 阿里数据分析师实习生笔试题2014年3月29日

    时间为90分钟 题型:10道选择,3道简答,2道分析题 回忆版 选择题: 1)若r=0,则两者的关系: 我选择的是没有线性关系 2)以下两种行为分别对应哪种分类算法的评价标准: 行为1:警察如何判别某人是小偷 行为2:小偷是如何被识别出来(+_+行为记不清楚,请记得的童鞋补上) 选项是RecallPrecisionROC的组合,这题不会 3)以下哪项对Hadoop的描述是不正确的 4)HIVE的描述 5)公司员工的平均工资是3000,中位数是2500,众数是2000,则下面哪个说法不正确: 我选择的是大部分员工的工资都在2000 6)有个小松鼠从离家100米的地方搬松子回家,共有1000颗(?),小松鼠每次最多能搬50颗,小松鼠很馋,每走两米就要吃掉一颗,问小松鼠最后能搬多少颗松子回家? A0B5C10D25呜呜~记不太清,我选了0 7)正态分布的区间估计,若其他条件不变,置信水平L越小,则置信上限和置信下限的差 A越大B越小C不变D不确定 简答: 1)世界上每十万人中有一个患有艾滋病,如果某人患有艾滋病,则一定会被检查出来,如果某人没有患艾滋病,被错误诊断的概率为1%,假设有一个人被

相关推荐

推荐阅读