目录
SpringCloud 入门
文章以尚硅谷2020年发布的Springcloud+Spring Alibab为基础,记录下在学习中遇到的问题和学习心得.
1. 版本选择
官网查看SpringCloud和SpringBoot之间版本的对应关系
https://spring.io/projects/spring-cloud#overview
2.SpringCloud升级导致的“升级危机”
一、初始环境搭建
本人的环境使用:
JDK 1.8.251(使用1.8版本即可)
mysql:8.0.18
maven:3.8.3
使用idea创建maven 项目,命名为cloud2020 组名为com.atguigu.springcloud,不要使用idea自带的maven
父工程的pom依赖配置:
<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>
<lombok.version>1.18.10</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>8.0.18</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>2.1.0</mybatis.spring.boot.version>
</properties>
<!--子模块继承之后,提供作用:锁定版本+子module不用再写groupId和version-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- mybatis-springboot整合 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
补充:
1.dependencyManagement
dependencyManagement 只是声明依赖,并不实现引入,子项目如果不声明依赖,则不会从父项目中继承下来,如果声明但未设置version,则会从父工程的pom中继承版本(类似于java中的子类继承父类)
2.跳过单元测试
点击闪电按钮会跳过单元测试
3.mvn:install
也可点击父工程maven中的install将父类发布到仓库中
二、创建支付模块(子模块)
建module 改pom 写yml 主启动 业务类
1.修改pom
在父工程名字处右键创建新的modlue命名为 cloud-provider-payment8001
在子模块cloud-provider-payment8001中修改pom文件,引入在父类中声明的依赖,
<dependencies>
<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>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
若在子模块的maven刷新后出现 couldn`t reslove druid.version 或者${mabatis.spring.boot.version},只需要在父pom下删除对应的dependcy下的version重新输入${druid.version}或${mabatis.spring.boot.version}即可
2.配置application.yml
Springboot配置项可以为properties,但官方推荐使用applicaiton.yml,两者都可以使Springboot成功启动
在子模块的src/main/resource下创建application.yml,若没有resource文件夹则需要自己创建
application.yml代码包括
server:
port: 8001 #配置服务端口号
spring:
application:
name: cloud-payment-service #服务名
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作
driver-class-name: com.mysql.cj.jdbc.Driver #JDBC
url: jdbc:mysql://localhost:3306/cloud2020?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities
3.支付业务具体实现
1.创建数据库名为cloud2020,在其下创建表名为payment 字段为id(bigint 主键自增) 和serial(varchar(255))
2. 在子模块的main/java下创建包com.atguigu.springcloud在包下创建PaymentMain8001.java文件(启动类)
@SpringBootApplication
public class PaymentMain8001 {
/**
* @date 2022/8/13 16:01
* @author ahang
* @return void
*/
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
3.在com.atguigu.springcloud包下创建dao、controller、entities、service文件夹
在entities下创建实体类Payment和返回结果类CommentResult
@Data
@AllArgsConstructor//构造函数
@NoArgsConstructor
public class Payment implements Serializable {
private long id;
private String serial;
}
@Data
@AllArgsConstructor//构造函数
@NoArgsConstructor
public class CommentResult<T> {
private Integer code;
private String message;
private T data;
public CommentResult(Integer code,String message){
this(code,message,null);
}
}
在dao下创建PaymentDao
@Mapper
public interface PaymentDao {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id );
}
在service下创建PaymentService和impl.PaymentServiceImpl
public interface PaymentService {
public int create(Payment payment);
public Payment getPaymentById(@Param("id")Long id );
}
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
public int create(Payment payment) {
return paymentDao.create(payment);
}
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
在controller下创建PaymentController
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommentResult create(Payment payment){
int result=paymentService.create(payment);
log.info("*********插入成功"+result);
if (result>0){
return new CommentResult(200,"插入数据成功",result);
}else{
return new CommentResult(444,"插入数据失败",null);
}
}
@GetMapping(value = "/payment/get/{id}")
public CommentResult getPaymentById(@PathVariable("id")Long id){
Payment payment=paymentService.getPaymentById(id);
if (payment!=null){
log.info("*********查询结果"+payment);
return new CommentResult(200,"查询成功",payment);
}else{
return new CommentResult(444,"没有对应记录id:"+id,null);
}
}
}
4.测试所写业务
启动PaymentMain8001,在数据库中插入测试数据后,在浏览器输入localhost:8001/payment/get/1
若出现如下情况:
1.启动报错:java无效源问题,这是jdk环境不搭配照成,本地JDK为1.8.xx后在idea中点击file->setting->Build,Execution,Deployment->Compiler->Java Complier下将父和子工程全设置为8
并且在file->ProjectStructure->Project->ProjectSdk设置为本地环境的1.8.xx project language level设置为8-Lanvdas,type annotations etc. 在file->ProjectStructure->Project->Modules下将父子项目的Sources同样设置为8-Lanvdas,type annotations etc.
2.若成功启动SpringBoot但在网页输入网址后网页结果为Whitelabel Error Page
一般为启动类位置不对 ,PaymentMain8001(启动类)应放在与 dao、service等同级目录下。若启动类位置没问题,则是在Controller类中的注解@RestController出现问题
3.因为浏览器通常不支持post请求,所以在浏览器中调用controller下的localhost:8001/payment/create?serial=ahang,会返回报错,若想测试可使用Postman工具Download Postman | Get Started for Free
三、创建消费者模块
1.创建cloud-consumer-order80子模块
2.创建启动类
3.在application.yml中写入
server:
port:80
4.复制payment8001下的entities包
5.在容器中注册restTemplate
在com.atguigu.springcloud下创建config.ApplicationContextConfig类
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
6.编写controller.OrderController类
@RestController
@Slf4j
public class OrderController {
public static final String PAYMENT_URL="http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@GetMapping(value = "consumer/payment/create")
public CommentResult<Payment> creat(Payment payment){
//restTemplate (url(请求地址),requestMap(请求参数),ResponseBean.class(HTTP响应转换被装换成的对象类型))
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommentResult.class);
}
@GetMapping(value = "consumer/payment/get/{id}")
public CommentResult<Payment> getPayment(@PathVariable("id")Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommentResult.class);
}
}
7.测试所写业务
在同时打开payment8001和order80启动类后再浏览器输入localhost/consumer/payment/get/1和localhost/consumer/payment/create?serial=ahang 注意再测试后者时需要在PaymentController中的create方法添加@RequestBody,不然会导致在浏览器中显示插入成功,在数据库中插入为空的情况
四、代码重构
为了使后续代码减少冗余,将公共复用强的代码提取到一个新的子模块下命名为cloud-api-commons
修改新的子模块的pom
<dependencies>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
将payment8001或者order80下的entities包复制到commons子模块的com.atguigu.springcloud下并删除payment8001和order80下的entities下的实体类
选中commons子模块使用maven的clean和install命令将commons打包发布到本地厂库,
再在payment8001和order80的pom文件中添加
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
刷新maven厂库并且导包后爆红消失,启动两个子模块的启动类进行测试查询和插入(同上节)