* 创建一个 Maven 项目 microservice-provider-user
~~~bash
mvn archetype:generate -DgroupId=com.shiyanlou -DartifactId=microservice-provider-user -DarchetypeArtifactId=maven-archetype-quickstart
~~~
依赖如下:
~~~xml
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.shiyanlou</groupId>
<artifactId>microservice-provider-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microservice-provider-user</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入H2数据库,一种内嵌的数据库,语法类似MySQL -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- 添加spring-boot的maven插件,不能少,打jar包时得用 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
~~~
* 在`com.shiyanlou`下创建实体类`User.java`:
~~~java
package com.shiyanlou;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.math.BigDecimal;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String username;
@Column
private String name;
@Column
private Integer age;
@Column
private BigDecimal balance;
}
~~~
其中使用到了[Lombok](https://projectlombok.org/)插件,不过你可以暂时不用管这个是什么。
* 创建 DAO,在`com.shiyanlou`下创建`UserRepository.java`:
~~~java
package com.shiyanlou;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
}
~~~
* 在`com.shiyanlou`下创建`UserController.java`,提供 RESTful 接口:
~~~java
package com.shiyanlou;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RequestMapping("/users")
@RestController
public class UserController {
@Autowired
UserRepository userRepository;
@GetMapping("/{id}")
public Optional<User> findById(@PathVariable Long id){
return this.userRepository.findById(id);
}
}
~~~
上面代码通过`@GetMapping`注解提供了一个`GET`请求方式的`/users/{id}`。
* 编写启动类`App.java`,该类是程序的启动入口:
~~~java
package com.shiyanlou;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.math.BigDecimal;
import java.util.stream.Stream;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
ApplicationRunner init(UserRepository repository){
return args -> {
User user1 = new User(1L, "account1", "张三", 20, new BigDecimal(100.00));
User user2 = new User(2L, "account2", "李四", 28, new BigDecimal(180.00));
User user3 = new User(3L, "account3", "王五", 32, new BigDecimal(280.00));
Stream.of(user1, user2, user3)
.forEach(repository::save);
};
}
}
~~~
* 编写配置文件`src/main/resources/application.yml`:
~~~yaml
server:
# 指定Tomcat端口
port: 8000
spring:
application:
# 给这个服务取名叫做:microservice-provider-user
name: microservice-provider-user
jpa:
# 让hibernate打印执行的SQL
show-sql: true
logging:
level:
root: INFO
# 配置日志级别,让hibernate打印出执行的SQL参数
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
~~~
* 最终目录结构如下图:

* 通过 maven 构建并运行该程序:
~~~bash
mvn spring-boot:run
~~~
当窗口出现如下信息的时候,你可以请求该应用看看:
~~~
2019-03-12 23:06:45.812 INFO 17362 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8000 (http)
2019-03-12 23:06:45.870 INFO 17362 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-03-12 23:06:45.871 INFO 17362 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35
2019-03-12 23:06:45.919 INFO 17362 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/tanjian/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2019-03-12 23:06:46.013 INFO 17362 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-03-12 23:06:46.013 INFO 17362 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1893 ms
2019-03-12 23:06:46.082 INFO 17362 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]
2019-03-12 23:06:46.086 INFO 17362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2019-03-12 23:06:46.087 INFO 17362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2019-03-12 23:06:46.088 INFO 17362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2019-03-12 23:06:46.089 INFO 17362 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2019-03-12 23:06:46.268 INFO 17362 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-03-12 23:06:46.449 INFO 17362 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-03-12 23:06:46.516 INFO 17362 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2019-03-12 23:06:46.560 INFO 17362 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2019-03-12 23:06:46.882 INFO 17362 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.2.17.Final}
2019-03-12 23:06:46.884 INFO 17362 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2019-03-12 23:06:46.953 INFO 17362 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2019-03-12 23:06:47.109 INFO 17362 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: drop table user if exists
Hibernate: drop sequence if exists hibernate_sequence
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: create table user (id bigint not null, age integer, balance decimal(19,2), name varchar(255), username varchar(255), primary key (id))
2019-03-12 23:06:47.810 INFO 17362 --- [ main] o.h.t.schema.internal.SchemaCreatorImpl : HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@24629999'
2019-03-12 23:06:47.815 INFO 17362 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2019-03-12 23:06:48.171 INFO 17362 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-03-12 23:06:48.387 INFO 17362 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@2e96c6f6: startup date [Tue Mar 12 23:06:44 CST 2019]; root of context hierarchy
2019-03-12 23:06:48.438 WARN 17362 --- [ main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2019-03-12 23:06:48.487 INFO 17362 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/users/{id}],methods=[GET]}" onto public java.util.Optional<com.shiyanlou.labs.spring.cloud.microserviceprovideruser.User> com.shiyanlou.labs.spring.cloud.microserviceprovideruser.UserController.findById(java.lang.Long)
2019-03-12 23:06:48.493 INFO 17362 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
~~~
你可以新打开一个终端,然后输入如下命令来模拟请求:
~~~bash
curl http://localhost:8000/users/1
~~~
不出所料,会出现如下响应,代表着用户微服务就编写好了:
~~~json
{
"id": 1,
"username": "account1",
"name": "张三",
"age": 20,
"balance": 100.0
}
~~~

接下来,让我们开始编写服务消费者【电影微服务】。
- 微服务开发框架 SpringCloud
- 单体应用
- 如何解决单体应用架构中存在的问题
- 如何实现微服务架构以及技术选型
- Spring Cloud 特点
- 开始使用 Spring Cloud 实战微服务
- 快速搭建开发脚手架
- 编写服务提供者-用户微服务
- 编写服务消费者【电影微服务】
- 整合 Spring Boot Actuator
- 开始整合
- 微服务注册与发现
- 编写服务发现服务
- 注册微服务至 Eureka Server
- 更新服务提供者 (用户微服务)
- 更新服务消费者 (电影微服务)
- 查看注册结果
- Ribbon 客户端负载均衡
- Ribbon 简介
- 引入 Ribbon
- Ribbon 入门
- Feign 声明式 REST 调用
- 改造项目
- Hystrix 容错处理
- 实现容错的手段
- Hystrix 简介
- 开始使用
- 测试
- Zuul 网关
- 网关是什么
- Spring Cloud Zuul 介绍
- Zuul 入门使用
- 网关测试
- Spring Cloud Config 配置管理
- 配置中心的作用
- Spring Cloud Config 简介
- Spring Cloud Config 使用
- Sleuth 与 Zipkin 结合图形化展示
- 分布式追踪相关基础概念
- Spring Cloud Sleuth 介绍及使用
- Zipin 简介
- Docker 入门
- 云原生概念
- Docker 容器介绍
- Docker 常用命令
- 微服务运行在 Docker 之上
- Dockerfile 及其常见指令介绍
- 改造 Eureka Server 微服务
- Docker Compose 编排微服务
- 安装 Compose
- Compose 快速入门
- Compose 编排 SpringCloud微服务
- 将 Eureka 等微服务运行在 Docker 容器中
- Docker-Compose 编排文件的编写
- 通过 Docker Compose 启动、停止
- Compose编排Spring Cloud微服务2
- Docker-Compose 来部署一个双节点的 Eureka 集群
