在这个数据量越来越大、客户需求越来越高的时代,作为一个写java web后端代码的程序员,不会写微服务确实是有点说不过去,现在最常见的微服务框架一个是dubbo,另一个就是springcloud了。两者有很多的不同,比较显著的一个是dubbo符合CAP中的CP原则,符合高一致性,而springcloud符合AP原则,符合高可用性;另外从社区来说的话,.......就不说了,总之现如今不会springcloud就显得很捞。。好了,不说废话了,进入正题。
首先我们想用springcloud,就首先需要搭建一个微服务框架(这么说也不合适,实际上我们今天做的第一步就是用maven构建多个微服务,其实就是多个module)。
一:创建父工程
首先我们创建一个名为microservicecloud的父工程,eclipse里file->new maven project...就不多说了,唯一需要注意的是,创建的时候Packaging要选择pom,如下:
对父工程的pom文件做如下修改,里边的dependency是为了让子工程都和父工程有同样的依赖版本(在子工程里引用的时候不用再加version了),但实际上在父工程里是不会直接引用这些jar包的(只有子工程里有该依赖时才会被引用):
<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.sunsy.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<description>parent module</description>
<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>
<lombok.version>1.16.18</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR3</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>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>
<delimiter>$</delimiter>
</delimiters>
</configuration>
</plugin>
</plugins>
</build>
<modules>
</modules>
</project>
二:创建microservicecloud-api子工程
接下来创建子工程,首先是microservicecloud-api(瞎起了个名),里边有部门实体类,创建方法如下:
选择other之后选择创建maven module,如下
之后创建microservicecloud-api,如下:
next之后选jar,如下:
点完成就创建成功了。。。(创建其他的子工程就不重复了,都一样,截图截的我恶心。。。)
我们在这个工程下创建一个com.sunsy.springcloud.entity包,这个包下创建一个最简单的Dept.java实体类,类如下:
package com.sunsy.springcloud.entity;
import java.io.Serializable;
public class Dept implements Serializable {
private static final long serialVersionUID = 1L;
private Long deptno;
private String dname;
private String db_source;
public Dept() {
super();
}
public Dept(Long deptno, String dname, String db_source) {
super();
this.deptno = deptno;
this.dname = dname;
this.db_source = db_source;
}
public Dept(String dname) {
super();
this.dname = dname;
}
public Long getDeptno() {
return deptno;
}
public void setDeptno(Long deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getDb_source() {
return db_source;
}
public void setDb_source(String db_source) {
this.db_source = db_source;
}
}
三:创建microservicecloud-provider-dept子工程
在创建这个子工程之前,我们要先在mysql里创建一个名为clouddb01的数据库,之后运行如下sql(就是创建了个名叫dept的表,然后插了几个测试数据):
/*
Navicat MySQL Data Transfer
Source Server : 127.0.0.1Mysql
Source Server Version : 50718
Source Host : localhost:3306
Source Database : clouddb01
Target Server Type : MYSQL
Target Server Version : 50718
File Encoding : 65001
Date: 2019-01-08 17:26:17
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for dept
-- ----------------------------
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`deptno` bigint(20) NOT NULL AUTO_INCREMENT,
`dname` varchar(60) DEFAULT NULL,
`db_source` varchar(60) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES ('1', '开发部', 'clouddb01');
INSERT INTO `dept` VALUES ('2', '人事部', 'clouddb01');
INSERT INTO `dept` VALUES ('3', '财务部', 'clouddb01');
INSERT INTO `dept` VALUES ('4', '市场部', 'clouddb01');
INSERT INTO `dept` VALUES ('5', '运维部', 'clouddb01');
INSERT INTO `dept` VALUES ('6', 'testt', 'clouddb01');
之后创建一个子工程,命名为microservicecloud-provider-dept,这个子工程整合了mybatis,实现对dept实体的查询,以及实现controller以供他人调用。该工程目录结构如下:
首先还是pom配一下,各种依赖填进去,注意,在这个工程里依赖了上一个子工程microservicecloud-api,所以我们就不需要再写一遍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.sunsy.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservicecloud-provider-dept</artifactId>
<dependencies>
<dependency>
<groupId>com.sunsy.springcloud</groupId>
<artifactId>microservicecloud-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.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</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,如下(注意配置文件里的mybatis.cfg.xml以及mapper文件的位置,以及配置的value之前冒号之后要有一个空格,必须要有,我最开始用yml的时候被这个空格坑惨了....):
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml
type-aliases-package: com.sunsy.springcloud.entity
mapper-locations: classpath:mybatis/mapper/**/*.xml
spring:
application:
name: microservicecloud-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/cloudDb01
username: root
password: 123456
mybatis.cfg.xml文件如下(在application.yml里完全可以不配这个,为了显得专业一点全面一点,我还是配了。。。):
<?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>
DeptMapper.xml文件,因为比较简单,所以我没用mybatis逆向工程自动生成,自己手写了一下:
<?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.sunsy.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>
至此,boot整合Mybatis的配置文件就OK了,之后是dao层和service层以及controller。
DeptDao.java如下:
package com.sunsy.springcloud.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.sunsy.springcloud.entity.Dept;
@Mapper
public interface DeptDao {
public boolean addDept(Dept dept);
public Dept findById(Long id);
public List<Dept> findAll();
}
DeptService.java如下:
package com.sunsy.springcloud.service;
import java.util.List;
import com.sunsy.springcloud.entity.Dept;
public interface DeptService {
public boolean add(Dept dept);
public Dept get(Long id);
public List<Dept> list();
}
DeptServiceImpl.java如下:
package com.sunsy.springcloud.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.sunsy.springcloud.dao.DeptDao;
import com.sunsy.springcloud.entity.Dept;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptDao deptDao;
@Override
public boolean add(Dept dept) {
return deptDao.addDept(dept);
}
@Override
public Dept get(Long id) {
return deptDao.findById(id);
}
@Override
public List<Dept> list() {
return deptDao.findAll();
}
}
DeptController.java如下:
package com.sunsy.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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.sunsy.springcloud.entity.Dept;
import com.sunsy.springcloud.service.DeptServiceImpl;
@RestController
public class DeptController {
@Autowired
private DeptServiceImpl 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();
}
}
最后是主启动类,DeptProviderApp.java如下:
package com.sunsy.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class DeptProviderApp {
public static void main(String[] args) {
SpringApplication.run(DeptProviderApp.class, args);
}
}
OK,至此第二个子工程就完成了,我们可以启动之后访问http://localhost:8001/dept/list可以看到结果:
四:创建microservicecloud-consumer-dept子工程
子工程目录结构如下:
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>
<parent>
<groupId>com.sunsy.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservicecloud-consumer-dept</artifactId>
<dependencies>
<dependency>
<groupId>com.sunsy.springcloud</groupId>
<artifactId>microservicecloud-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>
application.yml如下:
server:
port: 80
创建一个ConfigBean类,把RestTemplate注入到容器中,ConfigBean.java如下:
package com.sunsy.springcloud.configuration;
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();
}
}
DeptConsumerController.java如下(该controller里的方法没用service层实现,而是调用了上一个子工程中controller层的rest接口去实现的,即getForObject方法):
package com.sunsy.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.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.sunsy.springcloud.entity.Dept;
@RestController
public class DeptConsumerController {
private static final String REST_URL_PREFFIX="http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value="/consumer/dept/add")
public boolean add(Dept dept) {
return restTemplate.postForObject(REST_URL_PREFFIX+"/dept/add", dept, Boolean.class);
}
@RequestMapping(value="/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return restTemplate.getForObject(REST_URL_PREFFIX+"/dept/get/"+id, Dept.class);
}
@SuppressWarnings("unchecked")
@RequestMapping(value="/consumer/dept/list")
public List<Dept> list() {
return restTemplate.getForObject(REST_URL_PREFFIX+"/dept/list", List.class);
}
}
最后是主启动类,SpringCloudConsumerApp.java如下:
package com.sunsy.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringCloudConsumerApp {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumerApp.class, args);
}
}
启动这个子工程,我们可以调用http://localhost:80/consumer/dept/list路径获得和调用上一个子工程的http://localhost:8001/dept/list路径相同的结果,当然,其实调用第一个url时本质就是再去调第二个url(getForObject方法)。
至此,这次博客的内容就结束了,写了这么多不过都是最基础的东西(所以没写啥注释....为自己偷懒找个理由),还没有开始涉及springcloud(如果在pom里加了cloud的依赖也算是涉及了cloud的话,那我服...)。不过我们想要接下来去深入eureka、zuul这些玩意,今天这个最基础的架子是必须要有的。下次会基于这个架子写一下eureka的小示例。拜里个拜...