SpringCloud之服务注册(discovery)和服务通信(openfig)基于RESTFUL风格

Spring Cloud的服务注册和服务调用(服务通信)

前提条件:
在编写模块数据调用的java代码之前,需要先把nacos先从git上down下来,并且run起来
安装了docker的前提下执行以下命令:
操作步骤:
- Clone 项目
git clone https://github.com/nacos-group/nacos-docker.git
cd nacos-docker
- 单机模式 Derby
docker-compose -f example/standalone-derby.yaml up
- 单机模式 Mysql
docker-compose -f example/standalone-mysql.yaml up
- 集群模式
docker-compose -f example/cluster-hostname.yaml up

以上三种启动模式根据自己的实际需求选择不同的启动模式,详细请参考
https://nacos.io/zh-cn/docs/quick-start-docker.html

一、导入相关依赖

提供服务(数据)的模块导入discovery依赖、调用服务模块两个依赖均导入

    <properties>
        <java.version>1.8</java.version>
        <discovery.version>0.9.0.RELEASE</discovery.version>
        <openfeign.version>2.1.3.RELEASE</openfeign.version>
    </properties>

    <dependencies>
        <!--==服务注册依赖==-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>${discovery.version}</version>
        </dependency>
        <!--==服务通信依赖(需要去获取其他模块的数据的时候导入)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${openfeign.version}</version>
        </dependency>
    </dependencies>
二、配置application.yml文件

服务提供模块和服务调用模块均只需少量配置即可达到通信功能
application.yml 两个模块均适用(注意使用不同的端口号),因为只需要改端口号,这里就先只写一份yml了,端口号自己去改

server:
  port: 9090
# 服务注册中心
spring:
  # 服务名
  application:
    name: user-center-zsm
  cloud:
    nacos:
      discovery:
        server-addr: ip:8848
三、编写服务提供方和服务调用方两个服务的java代码

这里我就以订单服务和用户服务为例子了:
在这里插入图片描述
user模块调用order模块的数据,我这里因为order模块还调用了其他模块的数据,因此也开启了服务通信(伪数据实现、主要讲用法)
order模块结构:
在这里插入图片描述
首先第一步现在Springboot项目的主程序入口开启服务注册和服务通信

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
//开启服务注册
@EnableDiscoveryClient
//开启服务通信
@EnableFeignClients
public class SpringcloudOrderCenterApplication {

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

Service

import com.springcloud.alibaba.springcloudordercenter.domain.dto.OrderDTO;

public interface OrderService {
      OrderDTO getOrderData(Integer oid);
}

ServiceImpl(这里我组装了其他模块的数据,可以忽略、只需要注意返回的是OrderDTO)

import com.springcloud.alibaba.springcloudordercenter.domain.dto.AliPayDTO;
import com.springcloud.alibaba.springcloudordercenter.domain.dto.OrderDTO;
import com.springcloud.alibaba.springcloudordercenter.domain.dto.PayInfo;
import com.springcloud.alibaba.springcloudordercenter.domain.dto.WeChatPayDTO;
import com.springcloud.alibaba.springcloudordercenter.service.AliPayInfoService;
import com.springcloud.alibaba.springcloudordercenter.service.OrderService;
import com.springcloud.alibaba.springcloudordercenter.service.WeChatPayInfoService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Author zsm
 * @Service 业务逻辑层, 查询订单相关信息,返回OrderDTO伪数据
 *
 */

//spring的service
@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    AliPayInfoService aliPayInfoService;
    @Resource
    WeChatPayInfoService weChatPayInfoService;

    @Override
    public OrderDTO getOrderData(Integer oid) {
        //分别获取Ali支付和微信支付的数据
        AliPayDTO aliPayInfo = aliPayInfoService.getAliPayInfo(1);
        WeChatPayDTO weChatPayInfo = weChatPayInfoService.getWeChatPayInfo(1);
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setOid(1);
        orderDTO.setOrderNo("1234567");
        orderDTO.setPayType(1);
        //如果支付类型是1,那么支付信息就是Ali的,如果支付信息是除了1以外的数字支付信息就是微信的
        if (orderDTO.getPayType()==2){
            PayInfo<AliPayDTO> aliPayDTOPayInfo = new PayInfo<>();
            aliPayDTOPayInfo.setPayInfo(aliPayInfo);
            orderDTO.setPayInfo(aliPayDTOPayInfo);
        }else {
            PayInfo<WeChatPayDTO> weChatPayDTOPayInfo = new PayInfo<>();
            weChatPayDTOPayInfo.setPayInfo(weChatPayInfo);
            orderDTO.setPayInfo(weChatPayDTOPayInfo);
        }
        return orderDTO;
    }
}

Controller

import com.springcloud.alibaba.springcloudordercenter.domain.dto.OrderDTO;
import com.springcloud.alibaba.springcloudordercenter.service.OrderService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * Controller层 对外暴露数据接口
 */
@RestController
@RequestMapping("/orders")
public class OrderController {
    @Resource
    OrderService orderService;

    @RequestMapping("/getOrderData/{oid}")
    public OrderDTO getOrderData(@PathVariable Integer oid) {
        OrderDTO orderData = orderService.getOrderData(oid);
        return orderData;
    }
}

以上就是服务提供方模块提供order相关的数据。

==================================================================
user模块结构
在这里插入图片描述
第一步也是在主程序入口开启服务注册和服务通信

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
//开启服务注册
@EnableDiscoveryClient
//开启服务发现
@EnableFeignClients
public class SpringcloudUserCenterApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringcloudUserCenterApplication.class, args);
    }
}

OrderDTO(order模块Controller层返回的数据类型)

import lombok.Data;

/**
 *  Order 数据传输对象
 */
@Data
public class OrderDTO {
    //Order 主键
    Integer oid;
    //订单号
    String orderNo;
    //支付方式
    Integer payType;
    //支付信息
    PayInfo payInfo;
}

UserVO(user模块传递给前端需要展示的数据)

import com.springcloud.alibaba.springcloudusercenter.domain.dto.OrderDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 *  返回给前端界面展示的数据
 *
 */

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserVO {
    //User 主键id
    Integer uid;
    //User 用户名
    String username;
    //组装OrderDTO
    OrderDTO orderDTO;

    //2个参数的构造
    public UserVO(Integer uid,String username){
        this.uid = uid;
        this.username = username;
    }
}

OrderServie: 获取order模块数据

import com.springcloud.alibaba.springcloudusercenter.domain.dto.OrderDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 *  获取Order层的数据
 *
 * @FeignClient http协议通信 value的值是order模块yml文件中配置的服务名
 * @Service dubbo  gRPC通信
 */
@FeignClient(value = "order-center-zsm")
public interface OrderService {
    //order模块Controller层暴露出来的urlMapping地址
    @RequestMapping("/orders/getOrderData/{oid}")
    OrderDTO getOrderData(@PathVariable Integer oid);
}

UserService:

import com.springcloud.alibaba.springcloudusercenter.domain.vo.UserVO;

public interface UserService {

    UserVO getUserData(Integer uid);
}

UserServiceImpl(这一层组装数据)

import com.springcloud.alibaba.springcloudusercenter.domain.dto.OrderDTO;
import com.springcloud.alibaba.springcloudusercenter.domain.vo.UserVO;
import com.springcloud.alibaba.springcloudusercenter.service.OrderService;
import com.springcloud.alibaba.springcloudusercenter.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Author zsm
 * @Service 业务逻辑层,返回UserVO给前端
 * 业务层组装数据
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    OrderService orderService;

    @Override
    public UserVO getUserData(Integer uid) {
        //传个伪数据
        OrderDTO orderData = orderService.getOrderData(1);
        //new UserVO
        UserVO userInfo = new UserVO(1, "张顺民");
        userInfo.setOrderDTO(orderData);

        return userInfo;
    }
}

UserController:

import com.springcloud.alibaba.springcloudusercenter.domain.vo.UserVO;
import com.springcloud.alibaba.springcloudusercenter.service.UserService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * Controller层,暴露数据接口给其他模块或前端调用
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    UserService userService;

    @RequestMapping("/getUserData/{uid}")
    public UserVO getUserData(@PathVariable Integer uid) {
        UserVO userData = userService.getUserData(uid);
        return userData;
    }
}
common包下全局结果集处理等

ResponseResult(全局返回结果集类型)

/**
 * 返回数据的全局类型
 * @param <T>
 */
//启用构建者模式
@Data
@Builder
public class ResponseResult<T> {
    //响应状态码
    private Integer statusCode;
    //响应提示信息
    private String tipMsg;
    //全局返回数据类型
    private T data;

    public static <T> ResponseResult success(T data){

      return  ResponseResult.builder().statusCode(ResponseStatus.SUCCESS.getStatusCode())
                .tipMsg(ResponseStatus.SUCCESS.getTipsMsg())
                .data(data).build();
    }
    public static <T> ResponseResult fail(){

        return  ResponseResult.builder().statusCode(ResponseStatus.FAIL_404.getStatusCode())
                .tipMsg(ResponseStatus.FAIL_404.getTipsMsg())
                .build();
    }
}

全局结果集处理类ResponseAdvice

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 *  全局结果集处理
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    // 是否执行第二个方法
    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    //Object为Controller层返回的对象类型
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        ResponseResult result = ResponseResult.success(o);
        return result;
    }
}

ResponseSatus状态码、提示信息等常量值的枚举类

/**
 *  全局影响信息枚举类
 */
public enum ResponseStatus {
    SUCCESS(20000,"获取数据成功"),
    FAIL_404(40004,"网络不给力,请稍后重试");

    private Integer statusCode;
    private String tipsMsg;

    ResponseStatus(Integer statusCode, String tipsMsg) {
        this.statusCode = statusCode;
        this.tipsMsg = tipsMsg;
    }

    public Integer getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(Integer statusCode) {
        this.statusCode = statusCode;
    }

    public String getTipsMsg() {
        return tipsMsg;
    }

    public void setTipsMsg(String tipsMsg) {
        this.tipsMsg = tipsMsg;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值