在上一篇中提到了spring cloud 面向接口调用的开发风格,这一篇会举一个简单的但完整的例子来说明整个代码结构。
代码已上传到 https://github.com/maruixiang/spring-cloud-demo/tree/master/demo1
整个代码在demo1目录下面,包含了一个根级的parent pom文件和三个maven应用。
- 根pom文件:所有应用的parent pom文件。
- eureka :注册中心,用于服务注册和发现。
- demo :demo微服务,它本身包含了两个模块,demo-api提供给第三方使用的接口;demo-service是服务的具体实现。
为什么每个微服务多加了一层目录结构呢?因为从微服务职责划分来说,不同团队负责不同的微服务开发,每个微服务独立成项目,代码可以随时分离,不混合在一起。
- client : 客户端调用服务。
每个应用maven代码结构可以通过http://start.spring.io/ 、IDE工具或手动生成,这里不多述。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.cehome.cloudgroupId>
<artifactId>cehome-cloud-parentartifactId>
<version>1.0.0-SNAPSHOTversion>
<packaging>pompackaging>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.5.7.RELEASEversion>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>1.5.7.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Dalston.SR3version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<finalName>${project.artifactId}finalName>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
<modules>
<module>eurekamodule>
<module>demomodule>
<module>clientmodule>
modules>
project>
读音[ ju:`rika:]
继承spring-cloud-parent ,引入依赖 spring-cloud-starter-eureka-server即可
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>com.cehome.cloudgroupId>
<artifactId>spring-cloud-parentartifactId>
<version>1.0.0-SNAPSHOTversion>
<relativePath>../pom.xmlrelativePath>
parent>
<groupId>com.cehome.cloudgroupId>
<artifactId>eurekaartifactId>
<version>1.0.0-SNAPSHOTversion>
<packaging>jarpackaging>
<name>eurekaname>
<description>Demo project for Spring Bootdescription>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eureka-serverartifactId>
dependency>
dependencies>
project>
tomcat端口使用eureka约定的8761
server.port=8761
spring.application.name=eureka
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/
#是不是client?肯定不是啦。为true时,可以启动,但报异常:Cannot execute request on any known server
eureka.client.fetch-registry=false
#单注册中心设为false,集群是需要设为true以便多eureka互相同步
eureka.client.eureka-with-eureka=false
package com.cehome.cloud.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
运行main 方法,然后访问 http://localhost:8761/
demo 本身是包含两个模块的maven应用,一个是api供第三方调用,一个是具体逻辑。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.cehome.cloudgroupId>
<artifactId>demo-apiartifactId>
<version>1.0.0-SNAPSHOTversion>
<packaging>jarpackaging>
<parent>
<groupId>com.cehome.cloudgroupId>
<artifactId>demo-parentartifactId>
<version>1.0.0-SNAPSHOTversion>
<relativePath>../pom.xmlrelativePath>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-feignartifactId>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimentalgroupId>
<artifactId>spring-boot-thin-layoutartifactId>
<version>1.0.5.RELEASEversion>
dependency>
dependencies>
plugin>
plugins>
build>
project>
package com.cehome.cloud.demo.api;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(name= "demo-service" )
public interface Demo1Service {
@RequestMapping("/demo1/get")
String get();
}
package com.cehome.cloud.demo.api;
public class DemoAPI {
public static void main(String[] args) {
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.cehome.cloudgroupId>
<artifactId>demo-serviceartifactId>
<version>1.0.0-SNAPSHOTversion>
<packaging>jarpackaging>
<name>demo-servicename>
<description>Demo project for Spring Bootdescription>
<parent>
<groupId>com.cehome.cloudgroupId>
<artifactId>demo-parentartifactId>
<version>1.0.0-SNAPSHOTversion>
<relativePath>../pom.xmlrelativePath>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-feignartifactId>
dependency>
<dependency>
<groupId>com.cehome.cloudgroupId>
<artifactId>demo-apiartifactId>
<version>1.0.0-SNAPSHOTversion>
dependency>
dependencies>
project>
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/
server.port = 8762
spring.application.name = demo-service
package com.cehome.cloud.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
//-- provider and consumer service
@EnableEurekaClient
@ComponentScan("com.cehome.cloud.demo")
public class DemoServiceApplication {
public static void main(String[] args) {
SpringApplication.run(DemoServiceApplication.class);
}
}
package com.cehome.cloud.demo.service;
import com.cehome.cloud.demo.api.Demo1Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Demo1ServiceImpl implements Demo1Service {
@Override
public String get() {
return "This is Demo1 Service";
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.cehome.cloudgroupId>
<artifactId>spring-cloud-parentartifactId>
<version>1.0.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<groupId>com.cehome.cloudgroupId>
<artifactId>clientartifactId>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-feignartifactId>
dependency>
<dependency>
<groupId>com.cehome.cloudgroupId>
<artifactId>demo-apiartifactId>
<version>1.0.0-SNAPSHOTversion>
dependency>
dependencies>
project>
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/
server.port = 8763
spring.application.name = client-demo
package com.cehome.cloud.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
//-- consumer http://blog.didispace.com/spring-cloud-tips-feign-rpc/
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.cehome.cloud"})
@RestController
@ComponentScan("com.cehome.cloud.client")
public class ClientApplication {
public static void main(String[] args) {
SpringApplication springApplication=new SpringApplication(ClientApplication.class);
ConfigurableApplicationContext applicationContext=springApplication.run(args);
}
}
package com.cehome.cloud.client.controller;
import com.cehome.cloud.demo.api.Demo1Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/demo1")
public class Demo1Controller {
private static final Logger logger = LoggerFactory.getLogger(Demo1Controller.class);
@Autowired
private Demo1Service demo1Service;
@GetMapping("/get")
public String get() {
logger.info("begin to get ......");
return demo1Service.get();
}
}