0%

SpringCloud(三)Rest微服务案例

案例介绍

使用 springmvcmybaitsmysql,以部门模块(Dept)做一个微服务通用案例:Consumer(Client)通过REST调用Provider(Server)提供的服务。

项目结构

  • clouddemo
    • clouddemo-common:封装的实体、接口、公共配置
    • clouddemo-provider(8001端口):微服务落地的服务提供者
    • clouddemo-consumer(80端口):服务调用者

技术版本

  • Spring Cloud :Dalston.SR1
  • Spring Boot : 1.5.9.RELEASE

实战

父工程

  • pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<groupId>top.zhenganwen</groupId>
<artifactId>clouddemo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<finalName>clouddemo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
</plugins>
</build>

common工程

  • pom.xml
1
2
3
4
5
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
  • 实体类 Dept
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package top.zhenganwen.clouddemo.entity;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
* 部门实体类
*/
@Data
@Accessors(chain = true)//链式调用setters
public class Dept implements Serializable {


private Long deptno;//主键
private String dname;//部门名称
private String db_source;//数据来自哪个数据库

}

运行 mvn clean packge安装到本地仓库

provider

  • pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<parent>
<groupId>top.zhenganwen</groupId>
<artifactId>clouddemo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>

<dependency>
<groupId>top.zhenganwen</groupId>
<artifactId>clouddemo-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
  • application.yml,一下几点需注意
    • mybatis核心配置文件
    • mapper映射文件
    • 实体类所在包
    • 数据库连接url和用户名密码
    • application.name,这个在微服务中至关重要,服务注册和发现的标识
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server:
port: 8001

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: top.zhenganwen.clouddemo.entity # 所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件

spring:
application:
name: clouddemo-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/test # 数据库名称
username: root
password: root
dbcp2: #连接池配置
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化连接数
max-total: 5 # 最大连接数
max-wait-millis: 200 # 等待连接获取的最大超时时间
  • mybatis.cfg.xml
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

<settings>
<setting name="cacheEnabled" value="true" /><!-- 二级缓存开启 -->
</settings>

</configuration>
  • DeptMapper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
package top.zhenganwen.clouddemoprovider.mapper;

import org.apache.ibatis.annotations.Mapper;
import top.zhenganwen.clouddemo.entity.Dept;

import java.util.List;

@Mapper //必须加此注解才能被springboot识别是mybatis中的mapper接口,从而根据配置文件创建代理对象
public interface DeptMapper {
boolean addDept(Dept dept);
Dept findById(Long id);
List<Dept> findAll();
}
  • DeptMapper.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="top.zhenganwen.clouddemoprovider.mapper.DeptMapper">

<select id="findById" resultType="Dept" parameterType="Long">
select deptno,dname,db_source from dept where deptno=#{deptno};
</select>
<select id="findAll" resultType="Dept">
select deptno,dname,db_source from dept;
</select>
<insert id="addDept" parameterType="Dept">
INSERT INTO dept(dname,db_source) VALUES(#{dname},DATABASE());
</insert>

</mapper>
  • DeptService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package top.zhenganwen.clouddemoprovider.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.zhenganwen.clouddemo.entity.Dept;
import top.zhenganwen.clouddemoprovider.mapper.DeptMapper;
import top.zhenganwen.clouddemoprovider.service.DeptService;

import java.util.List;

@Service
public class DeptServiceImpl implements DeptService {

@Autowired
private DeptMapper deptMapper;

@Override
public boolean add(Dept dept) {
try {
deptMapper.addDept(dept);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

@Override
public Dept get(Long id) {
return deptMapper.findById(id);
}

@Override
public List<Dept> list() {
return deptMapper.findAll();
}

}
  • DeptController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package top.zhenganwen.clouddemoprovider.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import top.zhenganwen.clouddemo.entity.Dept;
import top.zhenganwen.clouddemoprovider.service.DeptService;

import java.util.List;

@RestController
@RequestMapping("dept")
public class DeptController {
@Autowired
private DeptService service;

@PostMapping("add")
public boolean add(@RequestBody Dept dept) {
return service.add(dept);
}

@GetMapping("get/{id}")
public Dept get(@PathVariable("id") Long id) {
return service.get(id);
}

@GetMapping("list")
public List<Dept> list() {
return service.list();
}

}
  • 启动类
1
2
3
4
5
6
7
8
9
10
11
12
package top.zhenganwen.clouddemoprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ClouddemoProviderApplication {

public static void main(String[] args) {
SpringApplication.run(ClouddemoProviderApplication.class, args);
}
}

consumer

  • pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<parent>
<groupId>top.zhenganwen</groupId>
<artifactId>clouddemo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>

<dependency>
<groupId>top.zhenganwen</groupId>
<artifactId>clouddemo-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</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>
  • application.properties
1
server.port=80
  • 引入REST API调用工具 RestTemplate,其中高度封装了 HTTP操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package top.zhenganwen.clouddemoconsumer.cfg;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration //此类相当于一个applicationContext.xml:被@Configuration标注的任意类
public class BeanConfiguration {

@Bean //此注解相当于一个<bean>元素:被@Bean标注的返回一个对象的任意方法
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
  • Controller,远程调用 provider提供的 HTTP接口,实现轻量级通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package top.zhenganwen.clouddemoconsumer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import top.zhenganwen.clouddemo.entity.Dept;

import java.util.List;

@RestController
@RequestMapping("dept")
public class DeptConsumerController {

private static final String URL_PREFIX= "http://localhost:8001";

@Autowired
private RestTemplate restTemplate;

@PostMapping("add")
public Boolean add(Dept dept) {
return restTemplate.postForObject(URL_PREFIX + "/dept/add", dept, Boolean.class);
}
@GetMapping("list")
public List<Dept> list() {
return restTemplate.getForObject(URL_PREFIX + "/dept/list", List.class);
}

@GetMapping("get/{id}")
public Dept get(@PathVariable Long id) {
return restTemplate.getForObject(URL_PREFIX + "/dept/get/" + id, Dept.class);
}
}

测试

provider工程并不对外提供访问,而是对内提供对部门模块的操作的一套 REST API,例如 consumer工程通过provider工程对部门模块进行增删改查

鼓励一下~