springcloud-学习环境搭建(一)
springCloud流程图
SpringCloud版本
大版本说明
SpringBoot | SpringCloud | 关系 |
---|---|---|
1.2.x | Angel版本(天使) | 兼容SpringBoot1.2x |
1.3.x | Brixton版本(布里克斯顿) | 兼容SpringBoot1.3x,也兼容SpringBoot1.4x |
1.4.x | Camden版本(卡姆登) | 兼容SpringBoot1.4x,也兼容SpringBoot1.5x |
1.5.x | Dalston版本(多尔斯顿) | 兼容SpringBoot1.5x,不兼容SpringBoot2.0x |
1.5.x | Edgware版本(埃奇韦尔) | 兼容SpringBoot1.5x,不兼容SpringBoot2.0x |
2.0.x | Finchley版本(芬奇利) | 兼容SpringBoot2.0x,不兼容SpringBoot1.5x |
2.1.x | Greenwich版本(格林威治) |
实际开发版本关系
spring-boot-starter-parent | pring-cloud-dependencles | ||
---|---|---|---|
版本号 | 发布日期 | 版本号 | 发布日期 |
1.5.2.RELEASE | 2017-03 | Dalston.RC1 | 2017-x |
1.5.9.RELEASE | 2017-11 | Edgware.RELEASE | 2017-11 |
1.5.16.RELEASE | 2018-04 | Edgware.SR5 | 2018-10 |
1.5.20.RELEASE | 2018-09 | Edgware.SR5 | 2018-10 |
2.0.2.RELEASE | 2018-05 | Fomchiey.BULD-SNAPSHOT | 2018-x |
2.0.6.RELEASE | 2018-10 | Fomchiey-SR2 | 2018-10 |
2.1.4.RELEASE | 2019-04 | Greenwich.SR1 | 2019-03 |
推荐使用最后两个版本
创建springcloud项目父工程
- 新建一个普通的maven项目,新建成功后需要删除src目录。
- maven
<?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>
<groupId>com.dongjixue</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<!--1.打包方式-->
<packaging>pom</packaging>
<!--3.版本管理:我们可以统一的管理一些依赖的版本version-->
<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>
<mysql.version>8.0.17</mysql.version>
</properties>
<!--2.依赖管理-->
<dependencyManagement>
<dependencies>
<!--2.1 springCloud依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--2.2 SpringBoot springCloud是依赖于springboot的-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--2.3 数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--2.4 数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--2.5 SpringBoot 启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--2.6 单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--2.7 lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!--2.8 日志测试~-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
- 数据库
CREATE TABLE `dept` (
`deptno` BIGINT NOT NULL AUTO_INCREMENT COMMENT '部门编号',
`dname` VARCHAR(60) NOT NULL COMMENT '部门名字',
`db_source` VARCHAR(60) NOT NULL COMMENT '数据库名字',
PRIMARY KEY (`deptno`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
insert into dept (dname,db_source) values ('开发部',DATABASE());
insert into dept (dname,db_source) values ('人事部',DATABASE());
insert into dept (dname,db_source) values ('财务部',DATABASE());
insert into dept (dname,db_source) values ('市场部',DATABASE());
insert into dept (dname,db_source) values ('运维部',DATABASE());
子工程 springcloud-common
该子工程可以用于写一些公用的实体类和工具类等
- 在父工程中 new module一个maven项目 。parent是springcloud
- pom.xml文件 。
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.dong</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-common</artifactId>
<!--当前的Module自己需要的依赖,如果父依赖中已经配置了,这里就不用写了-->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
- 实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true) //链式写法
//所有的实体类务必实现序列化,通讯需求
public class Dept implements Serializable {
private Long deptno; //部门编号
private String dname;
//看下这个数据存在哪个数据库的字段~ 微服务 ,一个服务对应一个数据库
//同一个信息可能存在不同的数据库
private String dbSource;
/**
* 链式写法 Dept d=new Dept();
* 以前 d.setDeptno(""); d.setDname("");
* 链式写法:d.setDeptno("").etDname("");
*/
}
新建子工程 springcloud-provider-8001 作为服务提供者
- pom.xml
<dependencies>
<!--我们需要拿到实体类,所以要配置api module-->
<dependency>
<groupId>com.dong</groupId>
<artifactId>springcloud-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--日志门面-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--jetty:尝试着用这个当应用服务器,与Tomcat没什么区别-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!--热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
- application.yml
server:
port: 8001
#mybatis配置
mybatis:
configuration:
#开启驼峰命名
map-underscore-to-camel-case: true
type-aliases-package: com.dong.common.pojo
mapper-locations: classpath:mapper/*.xml
#spring的配置
spring:
application:
name: springcloud-provider-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource #数据源
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&allowMultiQueries=true
username: root
password: 123456
logging:
level:
com.dong.provider.dao: debug
- dao层
package com.dong.provider.dao;
import com.dong.common.pojo.Dept;
@Mapper
@Repository
public interface DeptMapper {
//添加部门
boolean addDept(Dept dept);
//根据ID查询部门
Dept queryById(@Param("deptno") long id);
//查询全部部门
List<Dept> queryAll();
}
- mapper
<?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="com.dong.provider.dao.DeptMapper">
<insert id="addDept" parameterType="Dept">
insert into dept(dname,db_source)
values (#{dname},DATABASE());
</insert>
<select id="queryById" resultType="Dept" parameterType="Long">
select * from dept where deptno = #{deptno};
</select>
<select id="queryAll" resultType="Dept">
select * from dept;
</select>
</mapper>
- service
package com.dong.provider.service;
import com.dong.common.pojo.Dept;
public interface DeptService {
boolean addDept(Dept dept);
Dept queryById(long id);
List<Dept> queryAll();
}
package com.dong.provider.service.impl;
import com.dong.common.pojo.Dept;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public boolean addDept(Dept dept) {
return deptMapper.addDept(dept);
}
@Override
public Dept queryById(long id) {
return deptMapper.queryById(id);
}
@Override
public List<Dept> queryAll() {
return deptMapper.queryAll();
}
}
- controller
package com.dong.provider.controller;
import com.dong.common.pojo.Dept;
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/dept/add")
public boolean addDept(@RequestBody Dept dept) {
return deptService.addDept(dept);
}
@GetMapping("/dept/get/{id}")
public Dept getDept(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
if (dept == null) {
throw new RuntimeException("Fail");
}
return dept;
}
@GetMapping("/dept/list")
public List<Dept> queryAll() {
return deptService.queryAll();
}
}
- 主启动类
package com.dong.provider;
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
- 测试:略
新建子工程 springcloud-consumer-80 作为消费者
- pom.xml
<dependency>
<groupId>com.dong</groupId>
<artifactId>springcloud-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>
</dependency>
- application.yml
server:
#80端口在浏览器访问的时候可以不加端口号,因为是默认的
port: 80
- controller
package com.dong.consumer.controller;
@RestController
public class DeptConsumerController {
/**
* 消费者 : 不因该有service层,因为我们访问的是服务提供者的资源
* RestTemplate有很多方法给我们直接调用!
* RestTemplate中没有Bean所以要我们自己把它注册到Bean中
* 提供多种便捷访问远程http服务的方法,简单的restful服务模板
* 我们通过RestTemplate可以实现从consumer调用provider模块的服务
* 参数(url, 实体或Map(参数类型), Class<T> responseType(返回类型))
*/
@Autowired
private RestTemplate restTemplate;
private static final String REST_URL_PREFIX = "http://localhost:8001";
@RequestMapping("/consumer/dept/get/{id}")
public Dept getDept(@PathVariable("id") Long id) {
//service不在本项目中,所以要去远程项目获取
//远程只能用 get 方式请求,那么这里也只能通过 get 方式获取
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
}
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept) {
//远程只能用 post 方式请求,那么这里也只能通过 post 方式获取
return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> queryAll() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
}
}
- config
package com.dong.consumer.config;
@Configuration
//@Configuration ... 相当于spring中的配置文件 applicationContext.xml文件
public class ConfigBean {
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
- 主启动类
package com.dong.consumer;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
- 启动ConsumerApplication和ProviderApplication进行测试
测试一:
访问:http://localhost//consumer/dept/get/1
结果:{"deptno":1,"dname":"开发部","db_source":null}
测试二:
访问: http://localhost//consumer/dept/add?dname=销售部
结果:true
测试三:
访问:http://localhost//consumer/dept/list
结果:
[
{"deptno":1,"dname":"开发部","db_source":null},
{"deptno":2,"dname":"人事部","db_source":null},
{"deptno":3,"dname":"财务部","db_source":null},
{"deptno":4,"dname":"市场部","db_source":null},
{"deptno":5,"dname":"运维部","db_source":null},
{"deptno":6,"dname":"销售部","db_source":null}
]
- 注意
在上面的测试二中:(最初服务提供方的controller中addDept方法没有加@RequestBody,就出现了如下错误
浏览器:org.springframework.web.client.HttpServerErrorException$InternalServerError:500
idea中控制台报的是sql中dname为null的错误
解决访问就是: public boolean addDept(@RequestBody Dept dept)
还有一点就是消费方add不能加@RequestBody,否则会报以下错误
There was an unexpected error (type=Bad Request, status=400).
Required request body is missing: public boolean com.dong.consumer.controller.DeptConsumerController.add(com.dong.common.pojo.Dept)
具体原因不详,求指教。