实战:基于Spring Boot实现微服务
在Java开发领域,Spring Boot算得上是一个颗耀眼的“明星”了。自Spring Boot诞生以来,秉着简化Java企业级应用的宗旨,受到广大Java开发者的好评。特别是微服务架构的兴起,Spring Boot被称为构建Spring应用中微服务的最有力的工具之一。Spring Boot中众多的开箱即用的Starter,为广大开发者尝试开启一个新服务提供了最快捷的方式。
本节将介绍如何基于Spring Boot来实现微服务。
配置环境
为了演示本例子,需要依赖于Spring Boot Web Starter。
Spring Boot Web Starter集成了Spring MVC,可以方便地构建RESTful Web应用,并使用Tomcat作为默认内嵌Servlet容器。
本节例子spring-boot-rest的pom.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:
http:
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.waylau</groupId>
<artifactId>spring-boot-rest</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>spring-boot-rest</name>
<properties>
<java.version>1.8</java.version>
</properties>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
REST API设计
在本节,我们将实现一个简单版本的“用户管理”RESTful服务。通过“用户管理”的API,就能方便地进行用户的增、删、改、查等操作。
用户管理的整体API设计如下。
·GET/users:获取用户列表。
·POST/users:保存用户。
·GET/users/{id}:获取用户信息。
·PUT/users/{id}:修改用户。
·DELETE/users/{id}:删除用户。
这样,相应的控制器可以定义如下。
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping
public List<User> getUsers() {
return null;
}
@GetMapping("/{id}")
public User getUser(@PathVariable("id") Long id) {
return null;
}
@PostMapping
public User createUser(@RequestBody User user) {
return null;
}
@PutMapping("/{id}")
public void updateUser(@PathVariable("id") Long id, @RequestBody User user) {
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable("id") Long id) {
}
}
编写程序代码
下面进行后台编码实现,编码涉及实体类、仓库接口、仓库实现类及控制器类。
1.实体类
com.waylau.spring.boot.domain包,用于放置实体类。我们定义一个保存用户信息的实体User。
public class User {
private Long id;
private String name;
private String E-mail;
public User() {
}
public User(String name, String E-mail) {
this.name = name;
this.E-mail = E-mail;
}
@Override
public String toString() {
return String.format("User[id=%d, name='%s', E-mail='%s']", id, name, E-mail);
}
}
2.仓库接口及实现类
com.waylau.spring.boot.repository包,用于放置仓库接口及仓库实现类,也就是我们的数据存储。
用户仓库接口UserRepository如下。
public interface UserRepository {
User saveOrUpateUser(User user);
void deleteUser(Long id);
User getUserById(Long id);
List<User> listUser();
}UserRepository的实现类如下。
@Repository
public class UserRepositoryImpl implements UserRepository {
private static AtomicLong counter = new AtomicLong();
private final ConcurrentMap<Long, User> userMap = new ConcurrentHashMap<Long,
User>();
@Override
public User saveOrUpateUser(User user) {
Long id = user.getId();
if (id == null || id <= 0) {
id = counter.incrementAndGet();
user.setId(id);
}
this.userMap.put(id, user);
return user;
}
@Override
public void deleteUser(Long id) {
this.userMap.remove(id);
}
@Override
public User getUserById(Long id) {
return this.userMap.get(id);
}
@Override
public List<User> listUser() {
return new ArrayList<User>(this.userMap.values());
}
}
其中,我们用ConcurrentMapuserMap来模拟数据的存储,AtomicLong counter用来生成一个递增的id,作为用户的唯一编号。
@Repository注解用于标识UserRepositoryImpl类是一个可注入的Bean。
3.控制器类
com.waylau.spring.boot.controller包,用于放置控制器类,也就是我们需要实现的API。
UserController实现如下。
@RestController
@RequestMapping("/users")
public class UserController {
@Autowiredprivate UserRepository userRepository;
@GetMapping
public List<User> getUsers() {
return userRepository.listUser();
}
@GetMapping("/{id}")
public User getUser(@PathVariable("id") Long id) {
return userRepository.getUserById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userRepository.saveOrUpateUser(user);
}
@PutMapping("/{id}")
public void updateUser(@PathVariable("id") Long id, @RequestBody User user) {
User oldUser = this.getUser(id);
if (oldUser != null) {
user.setId(id);
userRepository.saveOrUpateUser(user);
}
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable("id") Long id) {
userRepository.deleteUser(id);
}
}
安装REST客户端
为了测试REST接口,我们需要一款REST客户端。
有非常多的REST客户端可供选择,比如,Chrome浏览器的Postman插件,或者Firefox浏览器的RESTClient以及HttpRequester插件,都能方便用于REST API的调试。
这里,笔者就RESTClient以及HttpRequester插件的安装,做一下简单的介绍。
1.Firefox安装REST客户端插件
为了方便测试REST API,我们需要一款REST客户端来协助我们。
由于这里用Firefox浏览器居多,所以推荐安装RESTClient或者HttpRequester插件。当然,你可以根据个人喜好来安装其他软件。
在Firefox安装插件的界面,输入关键字“restclient”就能看到这两款插件的信息。单击“安装”即可,如图所示。
![精通学习微服务架构实战:基于SpringBoot实现微服务_第3张图片](http://img.e-com-net.com/image/info8/f27291989dfc428bb9905a25a192a1d4.jpg)
2.用HttpRequester来测试
在我们运行程序后,我们可以对
http://localhost:8080/users/1接口进行测试。
我们在HttpRequester中的请求URL中输入接口地址,而后单击“Submit”来提交测试请求。在右侧响应界面,能看到返回的JSON数据。下图展示了HttpRequester的使用过程。
![精通学习微服务架构实战:基于SpringBoot实现微服务_第4张图片](http://img.e-com-net.com/image/info8/bbbac796e5ae4dd1a6efa74dcb14a93d.jpg)
运行、测试程序
运行程序,项目在8080端口启动。
首先,我们发送GET请求到
http://localhost:8080/users,可以看到,响应返回的是一个空的列表[]。
我们发送POST请求到
http://localhost:8080/users,用来创建一个用户。请求内容如下。
{
"name":"waylau","E-mail":"[email protected]"}发送成功,我们能看到响应的状态是200,响应的数据如下。
{
"id": 1,
"name": "waylau",
"E-mail": "[email protected]"
}
我们通过该接口,再创建几条测试数据,并发送GET请求到
http://localhost:8080/users,可以看到,响应返回的是一个有数据的列表。
[
{
"id": 1,
"name": "waylau",
"E-mail": "[email protected]"
},
{
"id": 2,
"name": "老卫",
"E-mail": "[email protected]"
}
]
我们发送PUT方法到
http://localhost:8080/users/2,来修改id为2的用户信息,修改为以下内容。
{
"name":"柳伟卫","E-mail":"[email protected]"}
发送成功,我们能看到响应的状态是200。我们通过发送GET请求
到http:
{
"id": 2,
"name": "柳伟卫",
"E-mail": "[email protected]"
}
可以看到,用户数据已经被变更了。自此,这个简单的“用户管理”的RESTful服务已经全部调试完毕。
本节示例,可以在spring-boot-rest项目下找到。
最后
给大家分享一篇一线开发大牛整理的java高并发核心编程神仙文档,里面主要包含的知识点有:多线程、线程池、内置锁、JMM、CAS、JUC、高并发设计模式、Java异步回调、CompletableFuture类等。
文档地址:一篇神文就把java多线程,锁,JMM,JUC和高并发设计模式讲明白了
码字不易,如果觉得本篇文章对你有用的话,请给我一键三连!关注作者,后续会有更多的干货分享,请持续关注!