SpringCloud父子模块项目microservice建立

SpringCloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运行环境简单,可以在开发人员的电脑上跑。

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

微服务架构的应用场景:

1、系统拆分,多个子系统

2、每个子系统可部署多个应用,应用之间负载均衡实现

3、需要一个服务注册中心,所有的服务都在注册中心注册,负载均衡也是通过在注册中心注册的服务来使用一定策略来实现。

4、所有的客户端都通过同一个网关地址访问后台的服务,通过路由配置,网关来判断一个URL请求由哪个服务处理。请求转发到服务上的时候也使用负载均衡。

5、服务之间有时候也需要相互访问。例如有一个用户模块,其他服务在处理一些业务的时候,要获取用户服务的用户数据。

6、需要一个断路器,及时处理服务调用时的超时和错误,防止由于其中一个服务的问题而导致整体系统的瘫痪。

7、还需要一个监控功能,监控每个服务调用花费的时间等。

Spring Cloud的优势

  • 产出于spring大家族,spring在企业级开发框架中无人能敌,来头很大,可以保证后续的更新、完善。比如dubbo现在就差不多死了
  • 有spring Boot 这个独立干将可以省很多事,大大小小的活spring boot都搞的挺不错。
  • 作为一个微服务治理的大家伙,考虑的很全面,几乎服务治理的方方面面都考虑到了,方便开发开箱即用。
  • Spring Cloud 活跃度很高,教程很丰富,遇到问题很容易找到解决方案
  • 轻轻松松几行代码就完成了熔断、均衡负责、服务中心的各种平台功能

二、服务提供者与消费关系

服务提供者:提供服务被人调用
消费者:调用被人服务

https://projects.spring.io/spring-cloud/    springcloud项目官方主页

https://springcloud.cc/  springcloud中文网 有很详细的翻译文档 

http://springcloud.cn/  springcloud中文论坛 

新建一个working set

定义抽象的父类

我们开发项目,现在基本都用到maven,以及用父子项目,以及公共模块依赖,来构建方便扩展的项目体系;

首先我们建立父项目 microservice ,主要是一个pom,管理module,以及管理依赖,规范所有jar包版本等;

父模块

定义编码和编译版本compiler,druid阿里巴巴连接池

dependencyManagement 依赖管理,父项目加了依赖管理,子项目可以直接加groupId和artifactId用,不需要加版本

scope import直接引入了公共的pom

<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.springcloud</groupId>
  <artifactId>microservice</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  
  <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>
        <druid.version>1.1.10</druid.version>
  </properties>
  
  <dependencyManagement>
       <dependencies>
          <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Edgware.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.5.13.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>
      </dependencies>
  </dependencyManagement>
  
  
  <modules>
  	<module>microservice-common</module>
  	<module>microservice-student-provider-1001</module>
  	<module>microservice-student-consumer-80</module>
  </modules>
</project>

公共模块的搭建,分布式该抽象的都抽象出来

我们新建module公共模块项目 microservice-common,主要是放一些其他项目公用的东西,比如实体类,工具类等等;

新建module模块

作为一个module了

不用指定版本,父模块已经指定了版本

<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>
  <parent>
    <groupId>com.springcloud</groupId>
    <artifactId>microservice</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>microservice-common</artifactId>
  
  <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
  </dependencies>
</project>

建立实体类序列化,进行对象服务调用必须序列化才能传输。当然我们数据库里也提前建一个db_springcloud数据库;

import java.io.Serializable;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
 
/**
 * 学生信息实体
 * @author Administrator
 *
 */
@Entity
@Table(name="t_student")
public class Student implements Serializable{
 
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
 
    @Id
    @GeneratedValue
    private Integer id; // 编号
     
    @Column(length=50)
    private String name; // 姓名
     
    @Column(length=50)
    private String grade; // 年级
     
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGrade() {
        return grade;
    }
    public void setGrade(String grade) {
        this.grade = grade;
    }
     
     
     
}

其他的子项目还要引入依赖,要maven install一下,相当于打个jar包发布到本地仓库

分布式就是消费者调用提供者实现解耦

microservice-student-provider-1001服务提供者项目建立

我们新建一个服务器提供者module子模块,类似前面建的common公共模块,名称是 microservice-student-provider-1001

项目-某个模块-提供者-端口(服务集群和负载均衡要分多个端口)

加common项目依赖,以及 springboot的 web jpa  驱动包 tomcat 连接池 配置 包括自动热部署配置,要依赖公共的模块,需要common里面的entity。都不需要版本,都依赖父类

<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>
  <parent>
    <groupId>com.springcloud</groupId>
    <artifactId>microservice</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>microservice-student-provider-1001</artifactId>
  
  <dependencies>
      <dependency>
          <groupId>com.java.springcloud</groupId>
          <artifactId>microservice-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-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
    </dependency>
    <!-- 修改后立即生效,热部署 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>springloaded</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
  </dependencies>
</project>

application.yml

server:
  port: 1001
  context-path: /
 
# 数据源配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_springcloud
    username: root
    password: 123456
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

接口

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import com.entity.Student;
 
/**
 * 学生Repository接口
 * @author Administrator
 *
 */
public interface StudentRepository extends JpaRepository<Student, Integer>,JpaSpecificationExecutor<Student>{
 
}
import java.util.List;
import com.entity.Student;
 
public interface StudentService {
 
    /**
     * 添加或者修改学生信息
     * @param student
     */
    public void save(Student student);
     
    /**
     * 根据id查找学生信息
     * @param id
     * @return
     */
    public Student findById(Integer id);
     
    /**
     * 查询学生信息
     * @return
     */
    public List<Student> list();
     
    /**
     * 根据id删除学生信息
     * @param id
     */
    public void delete(Integer id);
     
     
}

实现层

@Service("studentService")为bean的注解

save方法有id修改,无id为添加

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.entity.Student;
import com.repository.StudentRepository;
import com.service.StudentService;
 
@Service("studentService")
public class StudentServiceImpl implements StudentService{
 
    @Resource
    private StudentRepository studentRepository;
     
    @Override
    public void save(Student student) {
        studentRepository.save(student);
    }
 
    @Override
    public Student findById(Integer id) {
        return studentRepository.findOne(id);
    }
 
    @Override
    public List<Student> list() {
        return studentRepository.findAll();
    }
 
    @Override
    public void delete(Integer id) {
        studentRepository.delete(id);
    }
 
}

controller

import java.util.List;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.entity.Student;
import com.service.StudentService;
 
/**
 * 服务提供者-学生信息控制器
 * @author Administrator
 *
 */
@RestController
@RequestMapping("/student")
public class StudentProviderController {
 
    @Resource
    private StudentService studentService;
     
    /**
     * 添加或者修改学生信息
     * @param student
     * @return
     */
    @PostMapping(value="/save")
    public boolean save(Student student){
        try{
            studentService.save(student);  
            return true;
        }catch(Exception e){
            return false;
        }
    }
     
    /**
     * 查询学生信息
     * @return
     */
    @GetMapping(value="/list")
    public List<Student> list(){
        return studentService.list();
    }
     
    /**
     * 根据id查询学生信息
     * @return
     */
    @GetMapping(value="/get/{id}")
    public Student get(@PathVariable("id") Integer id){
        return studentService.findById(id);
    }
     
    /**
     * 根据id删除学生信息
     * @return
     */
    @GetMapping(value="/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id){
        try{
            studentService.delete(id);
            return true;
        }catch(Exception e){
            return false;
        }
    }
}

启动类,我们运行启动类,自动生成t_student表;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class StudentProviderApplication_1001 {
 
    public static void main(String[] args) {
        SpringApplication.run(StudentProviderApplication_1001.class, args);
    }
}

http://localhost:1001/student/get/1

服务消费者

我们新建一个服务器提供者module子模块,类似前面建的common公共模块,名称是 microservice-student-consumer-80.

80端口对外的端口

消费者要调用提供者,底层是http rest风格调用

<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>
  <parent>
    <groupId>com.springcloud</groupId>
    <artifactId>microservice</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>microservice-student-consumer-80</artifactId>
  
  <dependencies>
      <dependency>
          <groupId>com.java.springcloud</groupId>
          <artifactId>microservice-common</artifactId>
         <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
      <!-- 修改后立即生效,热部署 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>springloaded</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
  </dependencies>
</project>

application.yml配置文件:

server:
  port: 80
  context-path: /

定义config类,相当于定义一个bean

@Configuration 相当于定义了一个bean,相当于spring或xml配置文件,加了注解其他类都会扫描到。

 @Bean controller层要进行注入,直接调用。直接@resource然后@Autowired自动装配

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * SpringCloud相关配置
 * @author Administrator
 *
 */
@Configuration
public class SpringCloudConfig {

	/**
	 * 调用服务模版对象
	 * @return
	 */
	@Bean
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}
	
}

save 远程调用服务提供者的save方法

postForObject post方式 地址,请求对象,返回类型

getForObject get方式没有参数 

import java.util.List;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


/**
 * 服务消费者-学生信息控制器
 * @author Administrator
 *
 */
@RestController
@RequestMapping("/student")
public class StudentConsumerController {

	@Resource
	private RestTemplate restTemplate;
	
	private final static String PRE_HOST="http://localhost:1001";
	
	/**
     * 添加或者修改学生信息
     * @param student
     * @return
     */
    @PostMapping(value="/save")
    public boolean save(Student student){
    	return restTemplate.postForObject(PRE_HOST+"/student/save", student, Boolean.class);
    }
     
    /**
     * 查询学生信息
     * @return
     */
    @SuppressWarnings("unchecked")
	@GetMapping(value="/list")
    public List<Student> list(){
        return restTemplate.getForObject(PRE_HOST+"/student/list", List.class);
    }
     
    /**
     * 根据id查询学生信息
     * @return
     */
    @GetMapping(value="/get/{id}")
    public Student get(@PathVariable("id") Integer id){
        return restTemplate.getForObject(PRE_HOST+"/student/get/"+id, Student.class);
    }
     
    /**
     * 根据id删除学生信息
     * @return
     */
    @GetMapping(value="/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id){
        return restTemplate.getForObject(PRE_HOST+"/student/delete/"+id, Boolean.class);
    }
	
}

定义启动类

exclude 不会注入数据源和数据库驱动

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
public class StudentConsumerApplication_80 {

	public static void main(String[] args) {
		SpringApplication.run(StudentConsumerApplication_80.class, args);
	}
}

配置文件

server:
  port: 80
  context-path: /
 

猜你喜欢

转载自blog.csdn.net/qq_35029061/article/details/81971548
今日推荐