最近观看某马的视频,视频是使用ssm构建的一个基于dubbo的分布式项目,我将其改造为spring boot基于dubbo的项目
说明:idea+spring boot(2.1.1)+dubbo+mybatis+swagger2
首先:启动zookeeper,和dubbo-admin,具体的操作配置参见我的另外一篇博客
https://blog.csdn.net/qq_42151769/article/details/85238820
下面是项目的构建......
只是构建一个初始的项目,项目截图如下:
模块介绍:
pinyougou_parent: 父工程
pinyougou_manager_web:dubbo服务消费端,后续有很多个类似的模块,提供controller中的api接口给前台
pinyougou_pojo:实体类模块,存放项目所需要的数据库实体类
pinyougou_sellergoods_interface:专门提供对应模块的service接口,接口开发
pinyougou_sellergoods_service:dubbo服务端提供者,发布服务,mybatis的mapper接口连接数据库
pinyougou_mapper:所有的mybatis的通用数据访问层
注意,我将所有的pom.xml中的maven打包插件全部删除了,因为怕在进行jar打包后,一个子模块引入另一个子模块的时候容易出现找不到其中的某些包,这个需要注意下
父工程的pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>pinyougou_parent</name> <packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<!--各个子模块-->
<modules>
<module>pinyougou-common</module>
<module>pinyougou-pojo</module>
<module>pinyougou-sellergoods-interface</module>
<module>pinyougou-sellergoods-service</module>
<module>pinyougou-manager-web</module>
<module>pinyougou_mapper</module>
</modules>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
<!-- Apache工具组件 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>
特别需要注意的是父工程的打包方式必须是<packing>pom</packing>的
pinyougou_manager_web中的pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-manager-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>pinyougou-manager-web</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-sellergoods-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--阿里官方的dubbo依赖,spring boot2.0以上版本使用0.2.0,以下的版本使用0.1.0的,内置有zookeeper的依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<!-- Swagger依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
</project>
需要注意的是,使用的是dubbo官方提供的依赖,当spring boot是2.0.x及其以上的版本的时候,dubbo需要引入的版本是0.2.0的
如果是2.0.x以下的版本就需要引入的dubbo版本是0.1.0的
pinyougou_pojo的pom
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-pojo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>pinyougou-pojo</name>
<description>entity</description>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
</project>
pinyougou_sellergoods_interface的pom
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-sellergoods-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>pinyougou-sellergoods-interface</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.pinyougou</groupId>
<artifactId>pinyougou-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
</project>
pinyougou_sellergoods_service的pom
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-sellergoods-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>pinyougou-sellergoods-service</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-sellergoods-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_mapper</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--阿里官方的dubbo依赖,spring boot2.0以上版本使用0.2.0,以下的版本使用0.1.0的,内置有zookeeper的依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_mapper</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
pinyougou_mapper的pom
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.itcast</groupId>
<artifactId>pinyougou_mapper</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>pinyougou_mapper</name>
<description>通用数据访问层mapper</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.itcast</groupId>
<artifactId>pinyougou-pojo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</project>
下面对配置文件:
manager_web作为dubbo的消费者,appilication.yml
dubbo:
application:
name: pinyougou-sellergoods-service
protocol:
port: 20880
name: dubbo
provider:
timeout: 60000
retries: 0
registry:
address: zookeeper://192.168.25.128:2181
server:
port: 9090
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/pinyougou?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT
username: root
password: root
initialize: true
mybatis:
mapperLocations: classpath*:mapper/*.xml
typeAliasesPackage: com.itcast.pinyougoupojo.model
configuration:
map-underscore-to-camel-case: true
的配置如下:
service作为dubbo的提供者,applicayion.yml配置如下:需要注意的是,数据库配置/mybatis的配置/redis(后续)等等,配置全部是在dubbo提供者来配置的,不会在其依赖的子包mapper模块中配置
dubbo:
application:
name: pinyougou-sellergoods-service
protocol:
port: 20880
name: dubbo
provider:
timeout: 60000
retries: 0
registry:
address: zookeeper://192.168.25.128:2181
server:
port: 9090
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/pinyougou?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT
username: root
password: root
initialize: true
mybatis:
mapperLocations: classpath*:mapper/*.xml
typeAliasesPackage: com.itcast.pinyougoupojo.model
configuration:
map-underscore-to-camel-case: true
其他的配置文件没有了
还有需要注意的是启动类的配置,首先作为dubbo的消费者和提供者模块需要加上注解@Enable,如下
消费端:注意还需要排除掉spring boot自带的数据源,我的是自定义的数据源
package com.itcast.pinyougoumanagerweb;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDubbo
public class PinyougouManagerWebApplication {
public static void main(String[] args) {
SpringApplication.run(PinyougouManagerWebApplication.class, args);
}
}
因为使用了swagger2,同时还需要配置swagger2的配置,如下,注意在有controller的模块中,和启动类同级目录
具体的配置如下:
package com.itcast.pinyougoumanagerweb;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @ProjectName: pinyougou_parent
* @Package: com.itcast.pinyougoumanagerweb
* @ClassName: Swagger2
* @Author: wangming yu
* @Description: ${description}
* @Date: 2019-01-04 23:17
* @Version: 1.0
*/
@Configuration
/**
* 启用swaggerapi
*/
@EnableSwagger2
public class Swagger2 {
/**
* basePackage可以指定生成api的包,指定的包下面的controller类中的requestMapping方法会生成api解释
*
* @return
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.itcast.pinyougoumanagerweb.controller")) //指定controller所在的包路径
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2构建RESTful APIs")
.description("更多Spring Boot相关文章请关注:http://www.baidu.com/")
.termsOfServiceUrl("http://www.baidu.com/")
.contact("程序猿DD")
.version("1.0")
.build();
}
}
提供者端:也需要排除掉自带的数据源,还有一点注意,因为mybatis的配置是在service模块,但是mapper的接口和xml文件在Mapper模块,所以@MapperScan()指定是在Mapper模块的包名,并且在yml中需要使用到classpath*的方式来查找
@Mapper注解可以不要,但是@MapperScan()最好不要省略,我测试了,如果两个主角同时加上的话,起作用的是@MapperScan()注解,至于为什么在单模块中整合mybatis是,可以只需要@Mapper注解,但是在多模块就不行呢,会报找不到mapper的bean,原因是你加上了@Mapper时,但是没有加上@MapperScan(),在多模块中,因为你加入到spring 容器的是在有@Mapper的模块,但是你是在另外一个模块中使用mapper的,两个不是同一个spring容器,当然会报找不到了。。。
package com.itcast.pinyougousellergoodsservice;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDubbo
@MapperScan("com.itcast.pinyougou_mapper.mapper")
public class PinyougouSellergoodsServiceApplication {
public static void main(String[] args) {
SpringApplication.run(PinyougouSellergoodsServiceApplication.class, args);
}
}
自定义数据库的连接也是在service模块的:
package com.itcast.pinyougousellergoodsservice.beans;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import javax.sql.DataSource;
import java.util.Map;
import java.util.Properties;
/**
* @ProjectName: pinyougou_parent
* @Package: com.itcast.pinyougoumapper.beans
* @ClassName: DataSourceConf
* @Author: wangming yu
* @Description: ${description}
* @Date: 2018-12-16 14:29
* @Version: 1.0
*/
@Configuration
public class DataSourceConf {
@Value("${spring.datasource.druid.url}")
String url;
@Value("${spring.datasource.druid.username}")
String username;
@Value("${spring.datasource.druid.password}")
String password;
@Value("${spring.datasource.druid.driver-class-name}")
String driverClassName;
@Bean
public DataSource dataSource(StandardEnvironment env) {
Properties properties = new Properties();
DruidDataSource druidDataSource = new DruidDataSource();
PropertySource<?> appProperties = env.getPropertySources().get("applicationConfig: [classpath:/application.yml]");
Map<String, Object> source = (Map<String, Object>) appProperties.getSource();
properties.putAll(source);
druidDataSource.configFromPropety(properties);
druidDataSource.setUrl(url);
druidDataSource.setPassword(password);
druidDataSource.setUsername(username);
druidDataSource.setDriverClassName(driverClassName);
return druidDataSource;
}
}
服务发布的类:需要注意@Service注解是dubbo的注解
package com.itcast.pinyougousellergoodsservice.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.itcast.pinyougou_mapper.mapper.BrandMapper;
import com.itcast.pinyougoupojo.model.TbBrand;
import com.itcast.pinyougousellergoodsinterface.service.BrandService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* @ProjectName: pinyougou_parent
* @Package: com.itcast.pinyougousellergoodsservice.service.impl
* @ClassName: BrandServiceImpl
* @Author: wangming yu
* @Description: ${description}
* @Date: 2018-12-16 16:22
* @Version: 1.0
*/
/**
* 查询品牌信息
*/
@Service(interfaceClass = BrandService.class) //注意这个注解是dubbo的,并且最好指定接口类
public class BrandServiceImpl implements BrandService {
@Autowired
private BrandMapper brandMapper;
@Override
public List<TbBrand> getAllBrand() {
return brandMapper.getAllBrand();
}
/* @Override
public TbBrand getBrandById(String id) {
Long brandId = Long.valueOf(id);
return brandMapper.getBrandById(Long.valueOf(id));
}*/
}
服务消费者的类:需要注意引用的注解是@Reference ,通用这个注解也是dubbo的
package com.itcast.pinyougoumanagerweb.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.itcast.pinyougoupojo.model.TbBrand;
import com.itcast.pinyougousellergoodsinterface.service.BrandService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* @ProjectName: pinyougou_parent
* @Package: com.itcast.pinyougoumanagerweb.controller
* @ClassName: BrandController
* @Author: wangming yu
* @Description: ${description}
* @Date: 2018-12-16 17:01
* @Version: 1.0
*/
@Controller
@RequestMapping("/brand")
@Slf4j
@Api(value = "BrandController",description = "品牌接口api")
public class BrandController {
@Reference //注意这个注解是dubbo的,因为需要远程调用dubbo注册的服务
private BrandService brandService;
/**
* 查询所有品牌信息
* @return
*/
@ResponseBody
@GetMapping(value = "/list")
@ApiOperation(value = "所有品牌信息",notes = "查询所有品牌信息api")
@ApiImplicitParam(value = "无参")
public List<TbBrand> list(){
List<TbBrand> brands = brandService.getAllBrand();
return brands;
}
/* *//**
* 指定id查询
*//*
@GetMapping("/{id}")
@ResponseBody
public String getBrandById(@PathVariable String id){
TbBrand brand = brandService.getBrandById(id);
ObjectMapper mapper = new ObjectMapper();
String json = null;
try {
json = mapper.writeValueAsString(brand);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return json;
}*/
}
mapper所在的模块也需要排除掉自带的数据源哦