Python 官方文档:入门教程 => 点击学习
目录前言核心组件服务注册中心服务调用方式服务网关断路器数据库设计1 项目搭建1.1添加依赖2 开发房源查询模块:2.1 house-list 模块 2
这个项目的功能很简单只涉及了查询功能,这个项目的的目的是熟悉SpringCloud框架,明白服务与服务之间的调用是通过Http请求完成的使用微服务的架构而Feign可以使其像调用本地方法一样,学会在其他模块调用另一模块的服务和内容,完成负载均衡,学会将不同端口注册到eureka ,了解网关并会配置网关和使用断路器。
spring cloud Netflix Eureka
REST api、Feign、 Ribbon
spring Cloud Netflix Zuul
Spring Cloud Netflix Hystrix
由于本项目只是为了完整的实现SprinGCloud项目并明白框架功能故只设计查询功能,所以只设计两张表
表1 house
表2
本项目是一个多模块项目,创建一个 Spring Initializr 项目 不自动添加依赖项,完成创建后删除自带的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>house-server</module>
<module>eureak-server</module>
<module>house-zuul</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xatu</groupId>
<artifactId>spring-cloud-house-test1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-house-test1</name>
<description>spring-cloud-house-test1</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
端口号 8081 url接口 /house
参数名称 :null
参数类型 : null
说明 : 找到上线房源 打印list
创建application.properties
server.port=8081
spring.datasource.driver-class-name=com.Mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/house_test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.passWord=123456
logging.pattern.console=%clr(%d{${LOG_DATEFORMAT_PATTERN:HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}
mybatis.configuration.map-underscore-to-camel-case=true
spring.application.name=house-list
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
<?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>house-server</artifactId>
<groupId>com.xatu</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>houser-list</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-WEB</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@SpringBootApplication
@EnableEurekaClient
public class HouseListApplication {
public static void main(String[] args) {
SpringApplication.run(HouseListApplication.class, args);
}
@RestController//将返结果是JSON对象
public class HouseListController {
@Autowired
HouseListService houseListService;
@GetMapping("/house")
public List<House> houseList() {
return houseListService.getCourseList();
}
}
public class House implements Serializable {
Integer id;
Integer houseId;
String houseName;
Integer valid;
@Override
public String toString() {
return "Course{" +
"id=" + id +
", courseId=" + houseId +
", courseName='" + houseName + '\'' +
", valid=" + valid +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getHouseId() {
return houseId;
}
public void setHouseId(Integer houseId) {
this.houseId = houseId;
}
public String getHouseName() {
return houseName;
}
public void setHouseName(String houseName) {
this.houseName = houseName;
}
public Integer getValid() {
return valid;
}
public void setValid(Integer valid) {
this.valid = valid;
}
}
public interface HouseListService {
List<House> getCourseList();
}
impl 实现类
@Service
public class HouseListServiceImpl implements HouseListService {
@Autowired
HouseMapper houseMapper;
@Override
public List<House> getCourseList() {
return houseMapper.findValidCourses();
}
}
mapper
@Mapper
@Repository
public interface HouseMapper {
@Select("SELECT * FROM house WHERE valid = 1")
List<House> findValidCourses();
}
这里实现的是查询已上线的房源。
端口号 8083
url接口 /price
参数名称 :houseId
参数类型 : int
说明 : 获取到对应房源id的价格
url接口 /HouseInPrice
参数名称 :null
参数类型 : null
说明 : 作用与/list/house类似只是为了测试引入功能
url接口 /houseAndPrice
参数名称 :null
参数类型 : null
说明 : 获取到房子id 价格 id 名字
server.port=8082
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/house_test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
logging.pattern.console=%clr(%d{${LOG_DATEFORMAT_PATTERN:HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}
#tuo feng ming ming zhuan huan
mybatis.configuration.map-underscore-to-camel-case=true
spring.application.name=house-price
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
house-list.ribbon.NFLoadBanlancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
feign.hystrix.enabled=true
<?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>house-server</artifactId>
<groupId>com.xatu</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>house-price</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>com.xatu</groupId>
<artifactId>houser-list</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableCircuitBreaker
public class HousePriceApplication {
public static void main(String[] args) {
SpringApplication.run(HousePriceApplication.class, args);
}
}
//当远端服务出现问题会进入这个类
@FeignClient(value = "house-list" ,fallback = HouseListClientHystrix.class)
//有多个实例时,带有注解的人就是注入的
@Primary
public interface HouseListClient {
@GetMapping("/house")
public List<House> houseList();
}
如果不用feign 不同服务是不能进行调用的,我们在需要使用整合服务的模块中引入依赖 ,我加了注释了,再在启动类中加入注解,并创建一个类来作为我们引入模块的feign客户端,直接从我们想要引入的服务的controller中复制即可,引入后会有提示,要引入对另一个模块的依赖,就能数显服务的整合了。
@Component
public class HouseListClientHystrix implements HouseListClient {
@Override
public List<House> houseList() {
List<House> defaultCourses = new ArrayList<>();
House House = new House();
House.setId(1);
House.setHouseId(1);
House.setHouseName("默认房源");
House.setValid(1);
defaultCourses.add(House);
return defaultCourses;
}
}
发生错误时调用的类,给服务的返回是默认的返回值 @Component 注解使它成为一个组件
@RestController
public class HousePriceController {
@Autowired
HousePriceService housePriceService;
@Autowired
HouseListClient houseListClient;
@GetMapping("/price")
public Integer getCoursePrice(Integer houseId) {
HousePrice housePrice = housePriceService.getHousePrice(houseId);
return housePrice.getPrice();
}
@GetMapping("/HouseInPrice")
public List<House> getHouseListInPrice(Integer houseId) {
List<House> houses = houseListClient.houseList();
return houses;
}
@GetMapping("/houseAndPrice")
public List<HouseAndPrice> getCoursesAndPrice() {
List<HouseAndPrice> houseAndPrice = housePriceService.getHousesAndPrice();
return houseAndPrice;
}
}
public interface HousePriceService {
HousePrice getHousePrice(Integer houseId);
List<HouseAndPrice> getHousesAndPrice();
List<HousePrice> getHousePriceList();
}
impl
@Service
public class HousePriceServiceImpl implements HousePriceService {
@Autowired
HousePriceMapper housePriceMapper;
@Autowired
HouseListClient houseListClient;
@Override
public HousePrice getHousePrice(Integer houseId) {
return housePriceMapper.findCoursePrice(houseId);
}
@Override
public List<HouseAndPrice> getHousesAndPrice() {
List<HouseAndPrice> houseAndPricesList = new ArrayList<>();
List<House> houses = houseListClient.houseList();
for(int i = 0;i < houses.size();i++){
House house = houses.get(i);
if(house != null){
HousePrice housePrice = getHousePrice(house.getHouseId());
HouseAndPrice houseAndPrice = new HouseAndPrice();
houseAndPrice.setPrice(housePrice.getPrice());
houseAndPrice.setName(house.getHouseName());
houseAndPrice.setId(house.getId());
houseAndPrice.setHouseId(house.getHouseId());
houseAndPricesList.add(houseAndPrice);
}
}
return houseAndPricesList;
}
@Override
public List<HousePrice> getHousePriceList() {
return housePriceMapper.getAll();
}
}
第二个方法就体现除了服务的整合,我们并不用去进行多表查询,只需要调用其他服务就能快捷完成。
public class HouseAndPrice {
Integer id;
Integer houseId;
String name;
Integer price;
@Override
public String toString() {
return "HouseAndPrice{" +
"id=" + id +
", houseId=" + houseId +
", name='" + name + '\'' +
", price=" + price +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getHouseId() {
return houseId;
}
public void setHouseId(Integer houseId) {
this.houseId = houseId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
}
public class HousePrice implements Serializable {
Integer id;
Integer houseId;
Integer price;
@Override
public String toString() {
return "HousePrice{" +
"id=" + id +
", houseId=" + houseId +
", price=" + price +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getHouseId() {
return houseId;
}
public void setHouseId(Integer houseId) {
this.houseId = houseId;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
}
@Mapper
@Repository
public interface HousePriceMapper {
@Select("SELECT * FROM house_price WHERE house_id = #{houseId}")
HousePrice findCoursePrice(Integer courseId);
@Select("SELECT * FROM house_price" )
List<HousePrice> getAll();
}
Eureka server服务注册与管理的中心 生产者,提供者
调用方:
提供者把自己的信息注册到上面,server就能掌握最新的动态,调用方去调用服务是,会先去获取最新的地址,获取地址之后再去进行实际的调用。
Eureka 开发多了获取地址这一步是对ip服务进行解耦 。
Eureka client改写
我们把强两个模块进行Eureka Client改写也很简单,只用在启动类上加注解
@EnableEurekaClient
在配置文件上进行配置
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
我们eureka端口号多少8000那项就是多少
spring.application.name=eureka-server
server.port=8000
eureka.instance.hostname=localhost
#?????
eureka.client.fetch-reGIStry=false
#?????????
eureka.client.register-with-eureka=false
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
第一个注释是获取注册表。不需要同步其他节点数据
第二个注释是是否发自己也注册上去
<?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>spring-cloud-house-test1</artifactId>
<groupId>com.xatu</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureak-server</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<name>course-eureka-server</name>
<description>Spring Cloud Eureka</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
//eurekaserver启动
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
这样就证明我们的服务已经注册上去了
RandomRule表示随机策略
RoundRobinRule 表示轮询策略
Response TimeWeightedRule加权,根据每一个Server的平均响应时间动态加权
其实就是在配置文件中加一行
house-list.ribbon.NFLoadBanlancerRuleClassName=com.netflix.loadbalancer.RoundRobinRuley意思就是对house-list服务调用的时候采取的负载均衡的策略。
起到一个兜底的作用,有些时候一个服务出现问题,我们不希望整个系统都崩溃掉,那我们可以采取降级的手段,虽然不能返回正常的数据却可以保证系统正常运行。运用断路器我们不仅要配置配置文件,加依赖,还要书写一个短路类(参见price模块下client 下的断路器实现类)
<?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>spring-cloud-house-test1</artifactId>
<groupId>com.xatu</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>house-zuul</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 网关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
spring.application.name=house-gateway
server.port=9000
logging.pattern.console=%clr(%d{${LOG_DATEFORMAT_PATTERN:HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}
mybatis.configuration.map-underscore-to-camel-case=true
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
#???????
zuul.prefix=/xatu
zuul.routes.house-list.path=/list
//网关注解
@EnableZuulProxy
@SpringCloudApplication
public class ZuulGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulGatewayApplication.class, args);
}
}
pre 过滤器在路由请求之前运行
route 过滤器可以处理请求的实际路由
post 路由请求后运行过滤器
error如果在处理请求的过程中发生错误,则过滤器将运行
这里写一个前置一个后置
@Component
public class PreRequestFilter extends ZuulFilter {
//指定过滤器类别
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
//顺序
@Override
public int filterOrder() {
return 5;
}
//是不是走过滤器可以添加判断
@Override
public boolean shouldFilter() {
return true;
}
//通过过滤器将要实现的逻辑----打印出请求url
@Override
public Object run() throws ZuulException {
RequestContext currentContext = RequestContext.getCurrentContext();
//获取当前请求uri
System.out.println("URI:" + currentContext.getRequest().getRequestURI());
return null;
}
}
@Component
public class PostRequestFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
//打印返回状态码
@Override
public Object run() throws ZuulException {
RequestContext currentContext = RequestContext.getCurrentContext();
int status = currentContext.getResponse().getStatus();
System.out.println("response status:" + status);
return null;
}
}
浏览器输入http://127.0.0.1:9000/xatu/house-list/house
可以看书过滤器也实现了
1 通过这个项目我们了解了SpringCloud的几个重要组件
2 数据流向
3 完成两个模块开发后进行了服务注册与发现Eureka
4 为了使服务间调用更加简便使用了Feign组件
5 使用到了负载均衡
6 使用到了熔断器
7 使用网关,并进行了过滤器的编写
到此这篇关于Spring cloud 实现房源查询功能的文章就介绍到这了,更多相关Spring cloud 房源查询内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Spring cloud 实现房源查询功能的实例代码
本文链接: https://lsjlt.com/news/168556.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0