1. 程式人生 > >SpringCloud Rest微服務案例

SpringCloud Rest微服務案例

業務界定:以生產者消費者為例,服務端生產者,客戶端消費者,對外提供的服務

本章以maven聚合工程為例

步驟一:建立parent工程 名為springCloud  依賴注意是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.gcxzflgl.spring</groupId>
  <artifactId>springCloud</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>
		<junit.version>4.12</junit.version>
		<log4j.version>1.2.17</log4j.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.SR1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>1.5.9.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>mysql</groupId>
				<artifactId>mysql-connector-java</artifactId>
				<version>5.0.4</version>
			</dependency>
			<dependency>
				<groupId>com.alibaba</groupId>
				<artifactId>druid</artifactId>
				<version>1.0.31</version>
			</dependency>
			<dependency>
				<groupId>org.mybatis.spring.boot</groupId>
				<artifactId>mybatis-spring-boot-starter</artifactId>
				<version>1.3.0</version>
			</dependency>
			<dependency>
				<groupId>ch.qos.logback</groupId>
				<artifactId>logback-core</artifactId>
				<version>1.2.3</version>
			</dependency>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>${log4j.version}</version>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<finalName>microservicecloud</finalName>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<configuration>
					<delimiters>
						<delimit>$</delimit>
					</delimiters>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<modules>
		<module>springCloud-api</module>
		<module>springCloud-provider-dept</module>
		<module>springCloud-cousumer-dept</module>
	</modules>
</project>

步驟二:建立公共模組,我們把多次呼叫的類或者模組抽象出單獨的模組供其他模組引用,名為springCloud-api,要引入父工程

<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.gcxzflgl.spring</groupId>
    <artifactId>springCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>springCloud-api</artifactId>
  
  <dependencies><!-- 當前Module需要用到的jar包,按自己需求新增,如果父類已經包含了,可以不用寫版本號 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>
	</dependencies>
</project>

並且建立公共類實體Dept,也可以再這個公共類中引入lombok外掛依賴,就不用在麻煩生成對應set/get程式碼,編寫好後mvn打包到本地供其他模組引用,工程->run as->mvn install

步驟三:建立資料庫指令碼

DROP DATABASE IF EXITS db_springcloud;
create database db_springcloud CHARACTER set UTF8;
use db_springcloud;
create table dept(
	deptno BIGINT not null PRIMARY key auto_increment,
	dname varchar(60),
	db_source varchar(60)
);

insert into dept(dname,db_source) values('開發部',DATABASE());
insert into dept(dname,db_source) values('人事部',DATABASE());
insert into dept(dname,db_source) values('財務部',DATABASE());
insert into dept(dname,db_source) values('市場部',DATABASE());
insert into dept(dname,db_source) values('運維部',DATABASE());

步驟四:構建生產者對外提供服務,訪問埠用8001

按照開發流程,約定>配置>編碼

建立工程springCloud-provide-dept,依賴於springCloud-api

<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.gcxzflgl.spring</groupId>
    <artifactId>springCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>springCloud-provider-dept</artifactId>
  
  
	<dependencies>
		<!-- 引入自己定義的api通用包,可以使用Dept部門Entity -->
		<dependency>
			<groupId>com.gcxzflgl.spring</groupId>
			<artifactId>springCloud-api</artifactId>
			<version>${project.version}</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-starter-jetty</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-test</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>

在resources下新增mysql驅動配置檔案application.yml 訪問埠8001

server:
  port: 8001
  
mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml        # mybatis配置檔案所在路徑
  type-aliases-package: com.gcxzflgl.springCloud.entity    # 所有Entity別名類所在包
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml                       # mapper對映檔案
    
spring:
   application:
    name: microservicecloud-dept 
   datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 當前資料來源操作型別
    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驅動包
    url: jdbc:mysql://localhost:3306/db_springCloud              # 資料庫名稱
    username: root
    password: 123456
    dbcp2:
      min-idle: 5                                           # 資料庫連線池的最小維持連線數
      initial-size: 5                                       # 初始化連線數
      max-total: 5                                          # 最大連線數
      max-wait-millis: 200                                  # 等待連接獲取的最大超時時間

並且在resources下建立mybatis資料夾,用於存放mybatis.cfg.xml,mybatis資料夾下建立mapper用於存放對映關係

首先配置mybatis.cfg.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

	<settings>
		<setting name="cacheEnabled" value="true" /><!-- 二級快取開啟 -->
	</settings>

</configuration>

其次是我們很熟悉很傳統的 dao,Service,controller

Dao層介面,注意@Mapper註解別丟掉

package com.gcxzflgl.springCloud.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import com.gcxzflgl.springCloud.entity.Dept;

@Mapper
public interface DeptDao {

	public boolean addDept(Dept dept);

	public Dept findById(Long id);

	public List<Dept> findAll();
}

對映檔案xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.gcxzflgl.springCloud.dao.DeptDao">

	<select id="findById" resultType="Dept" parameterType="Long">
		select deptno,dname,db_source from dept where deptno=#{deptno};
	</select>
	<select id="findAll" resultType="Dept">
		select deptno,dname,db_source from dept;
	</select>
	<insert id="addDept" parameterType="Dept">
		INSERT INTO dept(dname,db_source) VALUES(#{dname},DATABASE());
	</insert>

</mapper>
 

Service層

package com.gcxzflgl.springCloud.service;

import java.util.List;

import com.gcxzflgl.springCloud.entity.Dept;

public interface DeptService{
	
	public boolean add(Dept dept);

	public Dept get(Long id);

	public List<Dept> list();
}
package com.gcxzflgl.springCloud.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gcxzflgl.springCloud.dao.DeptDao;
import com.gcxzflgl.springCloud.entity.Dept;
import com.gcxzflgl.springCloud.service.DeptService;

@Service
public class DeptServiceImpl implements DeptService{
	@Autowired
	private DeptDao dao;
	
	@Override
	public boolean add(Dept dept)
	{
		return dao.addDept(dept);
	}

	@Override
	public Dept get(Long id)
	{
		return dao.findById(id);
	}

	@Override
	public List<Dept> list()
	{
		return dao.findAll();
	}

}

Controller層,採用Rest方式對外提供服務

package com.gcxzflgl.springCloud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
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.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.gcxzflgl.springCloud.entity.Dept;
import com.gcxzflgl.springCloud.service.DeptService;

@RestController
public class DeptController{
	
	@Autowired
	private DeptService service;

	@RequestMapping(value = "/dept/add", method = RequestMethod.POST)
	public boolean add(@RequestBody Dept dept){
		return service.add(dept);
	}

	@RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
	public Dept get(@PathVariable("id") Long id){
		return service.get(id);
	}

	@RequestMapping(value = "/dept/list", method = RequestMethod.GET)
	public List<Dept> list(){
		return service.list();
	}

}

編寫主類執行測試:

package com.gcxzflgl.springCloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

出現以上結果代表提供者服務正常

步驟五:編寫消費者 名稱 springCloud-consumer-dept

<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.gcxzflgl.spring</groupId>
    <artifactId>springCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>springCloud-cousumer-dept</artifactId>
  
  <dependencies>
		<dependency><!-- 自己定義的api -->
			<groupId>com.gcxzflgl.spring</groupId>
			<artifactId>springCloud-api</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>

在resources下新增application.yml配置檔案

server:
  port: 80
  

Springcloud中的服務消費,就需要我們服務之前相互發請求了。之前我們都是想著用http請求相關的互動,用的比較多的是 apache httpcomponents ,現在springboot提供了RestTemplate更高級別的方法來滿足我們的功能.

建立一個配置類

package com.gcxzflgl.springCloud.confBean;

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


@Configuration
public class ConfigBean { 
	@Bean
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}
}

編寫Controller層,直接用restTemplate進行互動

package com.gcxzflgl.springCloud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.gcxzflgl.springCloud.entity.Dept;

@RestController
public class DeptController_Consumer
{

	private static final String REST_URL_PREFIX = "http://localhost:8001";
	
	@Autowired
	private RestTemplate restTemplate;

	@RequestMapping(value = "/consumer/dept/add")
	public boolean add(Dept dept){
		return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
	}

	@RequestMapping(value = "/consumer/dept/get/{id}")
	public Dept get(@PathVariable("id") Long id)
	{
		return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
	}

	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/consumer/dept/list")
	public List<Dept> list()
	{
		return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
	}


}

編寫主類測試最終結果:

package com.gcxzflgl.springCloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

我們看到最終結果,消費者進行消費,暴露給消費者的80,實際起作用的8001,從而達到對外提供服務,微服務代表服務大小,只提供對應的功能,一個服務是一個執行緒。我們看到有兩個執行緒在執行中