Spring Boot 和 Spring Cloud 版本选择
Spring Cloud 官网:https://spring.io/projects/spring-cloud#learn
Spring Boot 官网:https://spring.io/projects/spring-boot#learn
Spring Boot 官方强烈建议你升级到2.X以上版本
Spring Boot 和 Spring Cloud 版本对应查看方法
访问网站:https://start.spring.io/actuator/info
查看JSON串返回结果
在线格式化JSON
列出了SpringCloud 和 SpringBoot 版本对应关系。
父工程Project空间创建
父工程pom文件
<?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.kernel.springcloud</groupId>
<artifactId>cloud-kernel</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging> <!-- 这里添加pom,注意不是jar或war -->
<!-- 统一管理jar包版本 -->
<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>
<spring.boot.version>2.3.2.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR7</spring.cloud.version>
<lombok.version>1.16.18</lombok.version>
<mysql-connector-java.version>8.0.23</mysql-connector-java.version>
<druid.version>1.1.14</druid.version>
<swagger.version>2.9.2</swagger.version>
<mybatis.start.version>1.3.0</mybatis.start.version>
<hutool.version>4.1.19</hutool.version>
</properties>
<!-- 依赖管理 子模块继承之后,提供作用:锁定版本 + 子module 不用写groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.3.12.RELEASE-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR12-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
</dependency>
<!--阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.start.version}</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- 工具类大全糊涂 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
DependencyManagement 和 Dependencies
Maven使用DependencyManagement元素来提供了一种管理依赖版本号的方式。
通常会在一个组织或者项目的最顶层的父POM中看到DependencyManagement元素。
使用pom.xml中的DependencyManagement元素能让所有在子项目中引用个依赖而不用显式的列出版本量。
Maven会沿着父子层次向上走,直到找到一个拥有DependencyManagement元素的项目,然后它就会使用这个DependencyManagement元素中指定的版本号。
这样做的好处就是:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改;另外如果某个子项目需要另外的一个版本,只需要声明version就可。
DependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。
如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom。
如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
公共模块创建
cloud-api-common
公共模块:用来存放工具类等各模块通用的代码。
pom文件
<?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">
<parent>
<artifactId>cloud-kernel</artifactId>
<groupId>com.kernel.springcloud</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-api-common</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
</dependencies>
</project>
如接口统一返回封装
package com.kernel.web;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(description = "接口返回数据")
@Data
public class RestResult<T> {
@ApiModelProperty(value = "返回状态码")
private int code;
@ApiModelProperty(value = "描述信息")
private String msg;
@ApiModelProperty(value = "返回数据")
private T data;
// 成功,不返回具体数据
public static <T> RestResult<T> successNoData(ResultCode code) {
RestResult<T> result = new RestResult<T>();
result.setCode(code.getCode());
result.setMsg(code.getMsg());
return result;
}
// 成功,返回数据
public static <T> RestResult<T> success(T t, ResultCode code) {
RestResult<T> result = new RestResult<T>();
result.setCode(code.getCode());
result.setMsg(code.getMsg());
result.setData(t);
return result;
}
// 失败,返回失败信息
public static <T> RestResult<T> fail(ResultCode code) {
RestResult<T> result = new RestResult<T>();
result.setCode(code.getCode());
result.setMsg(code.getMsg());
return result;
}
}
public enum ResultCode {
/* 成功状态码 */
SUCCESS(0, "Success"), //成功
DATA_ACCESS_ERROR(50004, " Data_access_error"), //数据库访问错误
/* 参数错误:10001-19999 */
PARAM_IS_INVALID(10001, "Param_invalid"), // 参数无效
PARAM_IS_BLANK(10002, "Param_null"), // 参数为空
PARAM_NOT_COMPLETE(10003, "Param_missing"); //参数缺失
private Integer code;
private String msg;
ResultCode(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
服务提供者模块创建
创建微服务模块套路:
- 新建Module
- 修改pom文件
- 编写配置文件yml
- 编写主启动类
- 编写业务代码
创建cloud-provider-8001微服务提供者模块:
1.新建名为 cloud-provider-8001 的Module的Maven工程
父pom变化,多了modules 元素
<modules>
<module>cloud-api-common</module>
<module>cloud-provider-8001</module>
</modules>
2.修改POM文件
<?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">
<parent>
<artifactId>cloud-kernel</artifactId>
<groupId>com.kernel.springcloud</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-8001</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- 我们自己的公共模块 -->
<dependency>
<groupId>com.kernel.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
</project>
3.编写配置文件yml
server:
port: 8001
spring:
application:
name: cloud-provider-service # 服务名称
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.jdbc.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/idata_baiir?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username: ******
password: ******
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.kernel.entity # 所有Entity别名类所在包
4.主启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @ClassName ProviderApplication
* @author: shouanzh
* @Description ProviderApplication
* @date 2022/4/16 17:18
*/
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
5. 编写业务代码
简单的三层架构 controller -> service -> DAO
一个简单数据库表
user_test表:id、name、age 三个字段
entity
UserTest实体类(实体类放在了公共模块下)
/**
* UserTest PO实体类
*/
@Data
@ApiModel(description = "用户信息")
public class UserTest {
@ApiModelProperty(name = "id", value = "id")
private Long id;
@ApiModelProperty(name = "name", value = "名字")
private String name;
@ApiModelProperty(name = "age", value = "年龄")
private Integer age;
}
DAO
UserTestMapper.java
/**
* UserTest Dao层接口
*/
@Mapper
public interface UserTestMapper {
/**
* 插入对象
*/
int insert(UserTest userTest);
/**
* 更新对象
*/
int update(UserTest userTest);
/**
* 删除对象
*/
int delete(Long id);
/**
* 获取单个对象
*/
UserTest selectOne(Long id);
/**
* 获取列表
*/
List<UserTest> selectList(UserTest userTest);
}
UserTest.xml 路径:resources/mapper/UserTest.xml
<?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.da.springcloud.mapper.UserTestMapper">
<resultMap id="UserTest" type="com.kernel.entity.po.UserTest">
<result property="id" column="ID"/>
<result property="name" column="NAME"/>
<result property="age" column="AGE"/>
</resultMap>
<insert id="insert" parameterType="com.kernel.entity.po.UserTest" useGeneratedKeys="true"
keyProperty="id">
INSERT INTO USER_TEST (
<trim prefixOverrides=",">
<if test="id != null">,ID</if>
<if test="name != null">,NAME</if>
<if test="age != null">,AGE</if>
</trim>
) VALUES (
<trim prefixOverrides=",">
<if test="id != null">,#{id}</if>
<if test="name != null">,#{name}</if>
<if test="age != null">,#{age}</if>
</trim>
)
</insert>
<update id="update" parameterType="com.kernel.entity.po.UserTest">
UPDATE USER_TEST
<set>
<if test="name != null">NAME = #{name},</if>
<if test="age != null">AGE = #{age},</if>
</set>
WHERE ID = #{id}
</update>
<select id="selectOne" parameterType="java.lang.Long" resultMap="UserTest">
SELECT ID,
NAME,
AGE
FROM USER_TEST
WHERE ID = #{id} LIMIT 1
</select>
<select id="selectList" parameterType="com.kernel.entity.po.UserTest" resultMap="UserTest">
SELECT
ID,
NAME,
AGE
FROM USER_TEST
<where>
<if test="id != null">AND ID = #{id}</if>
<if test="name != null">AND NAME = #{name}</if>
<if test="age != null">AND AGE = #{age}</if>
</where>
</select>
<delete id="delete" parameterType="java.lang.Long">
DELETE
FROM USER_TEST
WHERE ID = #{id}
</delete>
</mapper>
Service:
/**
* UserTest Service层接口
*/
public interface IUserTestService {
/**
* 删除
* @param id
* @return
*/
int delete(Long id);// 删除
/**
* 新增
* @param userTest
* @return
*/
int insert(UserTest userTest);
/**
* 更新
* @param userTest
* @return
*/
int update(UserTest userTest);
/**
* 根据主键查找
* @param id
* @return
*/
UserTest selectOne(Long id);
/**
* 根据条件查询
* @param userTest
* @return
*/
List<UserTest> selectList(UserTest userTest);
}
/**
* UserTest Service层实现
*/
@Service
public class UserTestServiceImpl implements IUserTestService {
@Autowired
private UserTestMapper userTestMapper;
/**
* 删除
*
* @param id
* @return
*/
@Override
public int delete(Long id) {
return userTestMapper.delete(id);
}
/**
* 新增
*
* @param userTest
* @return
*/
@Override
public int insert(UserTest userTest) {
return userTestMapper.insert(userTest);
}
/**
* 更新
*
* @param userTest
* @return
*/
@Override
public int update(UserTest userTest) {
return userTestMapper.update(userTest);
}
/**
* 根据主键查找
*
* @param id
* @return
*/
@Override
public UserTest selectOne(Long id) {
return userTestMapper.selectOne(id);
}
/**
* 根据条件查询
*
* @param userTest
* @return
*/
@Override
public List<UserTest> selectList(UserTest userTest) {
return userTestMapper.selectList(userTest);
}
}
controller
@Api(tags = "用户管理接口")
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserTestService userTestService;
@ApiOperation(value="查询用户")
@PostMapping(value = "/search/v1")
public RestResult<List<UserTest>> search(@RequestBody UserTest userTest) {
try {
List<UserTest> userTests = userTestService.selectList(userTest);
return RestResult.success(userTests, ResultCode.SUCCESS);
} catch (Exception e) {
return RestResult.fail(ResultCode.DATA_ACCESS_ERROR);
}
}
@ApiOperation(value="删除用户")
@PostMapping(value = "/delete/v1")
@ApiImplicitParam(name = "id", value = "用户ID", required = true)
public RestResult delete(Long id) {
try {
userTestService.delete(id);
return RestResult.successNoData(ResultCode.SUCCESS);
} catch (Exception e) {
return RestResult.fail(ResultCode.DATA_ACCESS_ERROR);
}
}
}
整合Swagger配置
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.pathMapping("/")
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.securitySchemes(securitySchemes());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("spring cloud 接口测试文档")
.description("spring cloud 接口测试文档")
.version("3.0")
.contact(new Contact("shouanzh","","1432680552@qq.com"))
.license("")
.licenseUrl("")
.build();
}
/**
* SecurityScheme 子类 BasicAuth OAuth ApiKey
*
* @return
*/
private List<SecurityScheme> securitySchemes() {
List<SecurityScheme> list = new ArrayList<>();
// basicAuth SwaggerBootstrapUI支持的不好,使用swagger原生UI
// list.add(new BasicAuth("basicAuth"));
// name 为参数名 keyname是页面传值显示的 keyname, name在swagger鉴权中使用
list.add(new ApiKey("authorization", "authorization",
"header"));
return list;
}
}
测试
swagger 访问地址:http://localhost:8001/swagger-ui.html
总体结构
至此 服务提供者模块搭建完毕
消费者模块创建
1.新建Module
创建名为cloud-consumer-80的maven工程。
2.修改pom文件
<?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">
<parent>
<artifactId>cloud-kernel</artifactId>
<groupId>com.kernel.springcloud</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-80</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- 我们自己的公共模块 -->
<dependency>
<groupId>com.kernel.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
3.编写yml配置文件
application.yml
server:
port: 80
spring:
application:
name: cloud-consumer-service
4.主启动类
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
使用RestTemplate调用服务提供模块
RestTemplate配置
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
controller
@RestController
@Api(tags = "消费端")
public class ConsumerController {
public static final String PROVIDER_URL = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@ApiOperation(value="查询用户")
@PostMapping(value = "/search/v1")
public RestResult search(@RequestBody UserTest userTest) {
try {
return restTemplate.postForObject(PROVIDER_URL + "/user/search/v1", userTest, RestResult.class);
} catch (Exception e) {
return RestResult.fail(ResultCode.DATA_ACCESS_ERROR);
}
}
}
总体结构
测试
启动俩个服务
消费端swagger地址:http://localhost/swagger-ui.html
到此 服务提供者 和 服务消费者 搭建完毕,并使用RestTemplate调用服务提供者。接下来将进行spring cloud 组件的融合。