一、项目总体介绍
1.1、项目背景
在上一个系列二中我们用Ribbon封装好的RestTemplate实现了客户端服务端的http调用,但我们发现RestTemplate提供的方法很单一、有时无法满足我们的实际场景需求.我们需要一个更灵活的客户端调用方式。
1.2、项目实现功能
这节我们将用一个更强大的封装了http的客户端调用方式Feign实现用户客户端调用用户服务端进行数据库操作。
1.3、项目构建环境
jdk 1.8 、spring cloud 1.58
1.4、项目总体结构介绍(依旧是四个模块)
eureka-registry:eureka服务注册中心
user-service-api:定义用户服务接口(接口实体类的定义)
user-service-provider:用户服务生产者
user-service-feign:用户服务客户端
二、代码展示及开发心得
2.1、项目注册中心(eureka-registry)
2.1.1 、功能说明
除注册中心外、所有服务都将想注册中心进行注册,也是服务注册与发现的核心所在
2.1.2、项目目录结构
2.1.3、项目环境依赖(当前我们只需要引入spring-cloud-eureka-server 服务端即可)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
2.1.4、项目核心源码
---------------------项目配置文件application.properties--------------------------------
#HTTP访问端口
server.port=7000
#是否将服务注册到注册中心,这是服务注册中心,禁止自我注册
eureka.client.register-with-eureka=false
#是否从Eureka server 获取注册信息,注册中心的服务器,没有必要再去检索服务
eureka.client.fetch-registry=false
#设置服务的默认注册地址
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
#设为false,关闭自我保护
eureka.server.enable-self-preservation=false
#清理间隔(单位毫秒,默认是60*1000)
eureka.server.eviction-interval-timer-in-ms=10000
---------------------项目启动入口Applicatin-------------------------------
package com.gpdi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2.2、用户api服务
2.2.1、服务功能介绍
所有用户服务接口(增删查改接口以及客户端服务端共用的东西)
2.2.2、项目目录结构
2.2.3、项目环境依赖( 这里可以根据实际情况进行添加依赖(比如说hystrix依赖等))
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
2.2.4、项目核心代码
--------------------------------用户服务-------------------------------------
package com.gpdi.user.service;
import com.gpdi.user.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
/**
* @description: 提供用户服务
*
*/
@FeignClient(value = "user-service")
public interface UserService {
/**
* 添加用户
*/
@PostMapping(value = "/user/save")
public boolean saveUser(User user);
/**
* 查询用户信息
*/
@GetMapping(value = "/user/getAllUser")
public List<User> getAllUser();
}
---------------------------用户实体类---------------------------------
package com.gpdi.user.entity;
public class User {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.3、user-service-provider
2.3.1、系统功能介绍
用户服务的提供者,实现服务最终调用数据库功能
2.3.2、系统结构图
2.3.3、系统环境依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2.3.4、项目核心代码
--------------------------Controller层----------------------------------
package com.gpdi.user.controller;
import com.gpdi.user.entity.User;
import com.gpdi.user.service.UserService;
import com.gpdi.user.service.UserServiceProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@PostMapping(value = "savaUser")
public boolean saveUser(User user) {
return userServiceProxy.saveUser(user);
}
@GetMapping(value = "user/getAllUser")
public List<User> getAllUser() {
return userServiceProxy.getAllUser();
}
@Autowired
private UserServiceProxy userServiceProxy;
}
-------------------------Service层---------------------------
package com.gpdi.user.service;
import com.gpdi.user.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceProxy implements UserService {
@Override
public boolean saveUser(User user) {
String sql = "insert into user values(null,#{" + user.getName() + "})";
if (jdbcTemplate.update(sql) == 1) {
return true;
} else {
return false;
}
}
@Override
public List<User> getAllUser() {
return jdbcTemplate.query("select * from user", new
BeanPropertyRowMapper(User.class));
}
@Autowired
private JdbcTemplate jdbcTemplate;
}
---------------------------------启动文件------------------------
package com.gpdi.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
-----------------------------系统配置文件----------------------
#配置Eureka服务
#系统应用名称
spring.application.name = user-service
# Eureka注册中心服务器端口
eureka.server.port = 7000
## 服务提供方端口
server.port = 7071
## Eureka Server 服务 URL,用于客户端注册
eureka.client.serviceUrl.defaultZone=\
http://localhost:${eureka.server.port}/eureka
## Management 安全失效
management.security.enabled = false
#MySql本地数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/eureka-user?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
2.4、user-service-feign
2.4.1、系统功能说明
提供系统客户端的调用,调用服务端的程序进行功能的实现
2.4.2、系统结构图
2.4.3、项目环境依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
2.4.4、项目核心代码
-------------------系统配置文件---------------------------------
spring.application.name = user-service-client
server.port = 8081
## Eureka Server 服务 URL,用于客户端注册
eureka.client.serviceUrl.defaultZone=\
http://localhost:7000/eureka
management.security.enabled = false
## Ribbon 不使用 Eureka
ribbon.eureka.enabled = true
## 配置 "person-service" 的负载均衡服务器列表
# person-service.ribbon.listOfServers = \
#http://localhost:9090,http://localhost:9090,http://localhost:9090
------------------------Controller层(调用父类实现)-----------------------------------
package com.gpdi.user.controller;
import com.gpdi.user.entity.User;
import com.gpdi.user.hystrix.UserServiceFallBack;
import com.gpdi.user.service.UserService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController implements UserService {
@Override
public boolean saveUser(User user) {
return userService.saveUser(user);
}
@HystrixCommand(fallbackMethod = "getAllUserFall")
@Override
public List<User> getAllUser() {
return userService.getAllUser();
}
public List<User> getAllUserFall() {
System.out.println("查询用户熔断");
return null;
}
private final UserService userService;
@Autowired
public UserController(UserService personService) {
this.userService = personService;
}
}
------------------------自定义负载均衡---------------------------------------
package com.gupao.spring.cloud.feign.client.ribbon;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;
import java.util.List;
/**
*/
public class FirstServerForeverRule extends AbstractLoadBalancerRule {
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
@Override
public Server choose(Object key) {
ILoadBalancer loadBalancer = getLoadBalancer();
List<Server> allServers = loadBalancer.getAllServers();
return allServers.get(0);
}
}
----------------------------系统启动文件-------------------------
package com.gpdi.user;
import com.gpdi.user.ribbon.FirstServerForeverRule;
import com.gpdi.user.service.UserService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(clients = UserService.class)
@EnableHystrix
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public FirstServerForeverRule firstServerForeverRule() {
return new FirstServerForeverRule();
}
}