前言
本萌新从今天开始进入对springcloud的学习阶段了,说实话之前刚学完Java的时候对编程信心十分的匮乏,学的Java基础稀里糊涂,说做网页吧连登陆注册增删改查都写不出来。试图从基础的spring开始学,但是那复杂的配置让我望而却步。于是从简化配置的springboot开始学习了,最开始学习的时候只是零散的学习,没有方向,只能做做简单的登陆啊注册啊(还十分的困难)。在bilibili上看了很多springboot系列的教程,可是自己的技术始终没有进步,原地徘徊三四个月终于决定突破这层阻碍,直接上项目。没错,就是在基础打得稀里糊涂的情况下,直接做项目。我把以前用Python的flask框架写的小程序用springboot重新写了一遍,还在之前的基础上加了几个功能,写完之后,觉得基本的crud能力完全打通,还通过这个项目学到了很多,包括小程序,这也对我学习vue奠定了一丢丢丢的基础。
后来进阶买了松哥(江南一点雨)的springboot+vue写的vhr项目,说实话我跟着他的视频一点点的敲一点点的吸收,现在做基本的前后端开发没什么问题,但是这个项目做完也同样发现了自己好多的知识盲点,所以学无止境嘛,一边扫盲一边拓展。总不能原地踏步是不是?
我也跟很多有点Java基础的兄弟聊过天,他们对自己web端学习的方法不明确,我自己一开始学的时候也走了很多弯路。现在想来我觉得学习编程首要的还是要打好自己的基础,每天的学习最好能写个博客记录下来,这样自己手机端也能查看,时时勤拂拭,莫使惹尘该嘛。学完之后一定要写个不大不小的项目,作为融会贯通。可能你会说,学的时候没问题,一上手项目就脑子一片空白啥也不会了。肯定的呀,写项目就是补你的空白的。写好项目,这样你再回头看,你就会对自己所学出有理解,这个时候想向上进阶,我建议去找网上高级的进阶资料或者买视频看,关于买什么样的视频,当然是那种中大型的前后端分离的项目,最好能带一些自己还没学但是想学的技术,比如我买的就是松哥的微人事项目视频,因为他用了vue来做前端,而vue又是现在最主流的前端开发框架,所以成了我的首选。这样一边学习一边总结,后面的就是看能不能在他的基础上对项目进行改造,不要求你会原创,能在人的基础上进行加功能改造功能,就足以说明自己能力又上升了一个档次。
好了,下面就看现在比较流行的springcloud框架,关于springcloud的介绍我这里就不做介绍了,很多博客都有,我这不赘述。直接看干货吧。
创建聚合工程
添加父工程依赖
<?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.study</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>SpringCloud-API</module>
<module>SpringCloud-Provider</module>
<module>SpringCloud-Consumer</module>
</modules>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
创建API工程
我这里用了lombok插件,你们没有插件的就setget。
然后这里是给其他工程提供实体类的,所以需要实现序列化
package com.study.cloud.bean;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @description:
* 1.实体类必须实现序列化
* @author: Leo
* @createDate: 2020/2/8
* @version: 1.0
*/
@Data
//@Accessors(chain = true)//开启链式写法
public class Book implements Serializable
{
private Integer bookID;
private String bookName;
private Integer bookCounts;
private String detail;
private String db_source;
public Book()
{
}
public Book(String bookName, Integer bookCounts, String detail, String db_source)
{
this.bookName = bookName;
this.bookCounts = bookCounts;
this.detail = detail;
this.db_source = db_source;
}
}
创建服务者工程
添加依赖
<?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>springcloud</artifactId>
<groupId>com.study</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>provider</artifactId>
<dependencies>
<dependency>
<groupId>com.study</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>
</project>
yml配置文件
server:
port: 8001
mybatis:
type-aliases-package: com.study.cloud.bean
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
#服务提供者
spring:
application:
name: springcloud-provider
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/leotemp?useUnicode=true&useSSL=false&characterEncodig=utf-8
username: root
password: 123456
mybatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.cloud.mapper.BookMapper">
<insert id="addBook" parameterType="com.study.cloud.bean.Book">
insert into books(bookName,bookCounts,detail,db_source)
values (#{bookName},
#{bookCounts},
#{detail},
#{db_source})
</insert>
<select id="queryById" parameterType="java.lang.Integer" resultType="com.study.cloud.bean.Book">
select * from books where bookID=#{bookID};
</select>
<select id="queryAll" resultType="com.study.cloud.bean.Book">
select * from books
</select>
</mapper>
mapper层
package com.study.cloud.mapper;
import com.study.cloud.bean.Book;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @description:
* @author: Leo
* @createDate: 2020/2/10
* @version: 1.0
*/
@Mapper
@Repository
public interface BookMapper
{
boolean addBook(Book book);
Book queryById(Integer bookID);
List<Book> queryAll();
}
service层
package com.study.cloud.service;
import com.study.cloud.bean.Book;
import java.util.List;
public interface BookService
{
boolean addBook(Book book);
Book queryById(Integer bookID);
List<Book> queryAll();
}
实现类
package com.study.cloud.service;
import com.study.cloud.bean.Book;
import com.study.cloud.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @description:
* @author: Leo
* @createDate: 2020/2/10
* @version: 1.0
*/
@Service
public class BookServiceImp implements BookService
{
@Autowired
BookMapper bookMapper;
public boolean addBook(Book book)
{
return bookMapper.addBook(book);
}
public Book queryById(Integer bookID)
{
return bookMapper.queryById(bookID);
}
public List<Book> queryAll()
{
return bookMapper.queryAll();
}
}
控制层
package com.study.cloud.controller;
import com.study.cloud.bean.Book;
import com.study.cloud.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @description:
* @author: Leo
* @createDate: 2020/2/10
* @version: 1.0
*/
@RestController
@RequestMapping("/book/provide")
public class BookController
{
@Autowired
BookService bookService;
@PostMapping("/")
public boolean addBook(@RequestBody Book book)
{
return bookService.addBook(book);
}
@GetMapping("/{bookID}")
public Book queryById(@PathVariable("bookID") Integer bookID)
{
return bookService.queryById(bookID);
}
@GetMapping("/")
public List<Book> queryAll()
{
return bookService.queryAll();
}
}
最后定义启动类
上面就是最基本的数据的添加和查询。但是现在我们又要创建一个工程,这个工程是我们的消费者。
创建消费者模块
添加依赖
<?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>springcloud</artifactId>
<groupId>com.study</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>consumer</artifactId>
<!--需要实体类和web-->
<dependencies>
<dependency>
<groupId>com.study</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
二 修改端口,不要和之前那个工程一样 建议80
三、springcloud调用远程服务的话可以通过RestTemplate方法
第一步,要把RestTemplate注册到bean里
首先解释以下@configuration,它的主要作用就是在spring容器启动的时候,初始化IOC,使用了这个注解,那么该类就会在spring启动的时候,把@Bean注解标识的类进行依赖注入。@Bean理解的话,就好比在配置文件中配置.接下来就是在restTemplate的构造方法中添加httpRequest的工厂,使用连接池来优化http通信,默认使用长连接时间为30秒,再设置路由让http连接定向到指定的IP,然后设置并发数。再就是设置请求配置的超时时间,为了防止请求时间过长而引起资源的过渡浪费。如果在超过设置的timeout还没有数据返回,就直接断开连接。headers是添加默认的请求头,这里设置了传送的格式为json,语言为中-英等等属性。HttpClientBuilder.create设置请求头到HttpClient,然后在设置保持的时间,重试的次数,注入给httpClient进行封装。
package com.study.cloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @description:
* @author: Leo
* @createDate: 2020/2/10
* @version: 1.0
*/
@Configuration //这是springboot中的注解,他的作用相当于spring中的applicationContext.xml
public class ConfigBean
{
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
RestTemplate
说明:
现在restful接口越来越广泛,而如今很多接口摒弃了传统的配置复杂的webService开发模式,在java领域只需要很简单的springMvc就可以声明为一个控制器,再加上service层,就可以直接操作数据库成为一个灵活的接口。而我们请求接口的次数也会越来越多(最近我在和一个工具对接的时候,对方公司提供的接口全部由我们主动去调用),一般我们请求接口,都采用Apache Httpclient工具,这个工具稳定,既可以建立长连接,保持不错的性能,而它唯一的不足就是使用起来麻烦多变,并且要很多层判断处理,今天我要谈的就是spring对httpClient的再封装工具类,restTemplate,采用模板模式抽象出来的高效工具。有点类似于jdbcTemplate,今天我们就来一步步揭开它的使用方法
内置方法
客户端调用服务端
package com.study.cloud.controller;
import com.study.cloud.bean.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @description: 这里我是消费者,我在消费的时候需要自己有service层吗?我觉得显然是否定,那么问题来了,如果
* controller没有service他该如何去调用service呢?
* 通过RestTemplate
* @author: Leo
* @createDate: 2020/2/10
* @version: 1.0
*/
@RestController
public class BookConSumController
{
@Autowired
RestTemplate restTemplate;//提供多种便捷访问远程http服务的方法,是一个简单的restful服务模板
private static final String REST_URL_PREFIX="http://localhost:8001/book/provide";
//public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
// throws RestClientException
@RequestMapping("/book/consumer/post")
public boolean addBook(Book book){
return restTemplate.postForObject(REST_URL_PREFIX+"/",book,Boolean.class);
}
@RequestMapping("/book/consumer/get/{bookID}")
public Book getBookById(@PathVariable("bookID") Integer bookID){
return restTemplate.getForObject(REST_URL_PREFIX+"/"+bookID,Book.class);
}
@RequestMapping("/book/consumer/get")
public List<Book> getAllBook(){
return restTemplate.getForObject(REST_URL_PREFIX+"/",List.class);
}
}
这里调用的是**ForObject,他需要的参数是服务端的请求路径、参数、当前对象的类型
测试效果
服务端本地测试
http://localhost:8001/book/provide/
请求完全没毛病!
再看消费者端的调用
http://localhost/book/consumer/get
返回结果完全一致。