Loading

微服务的实现

实体类:

在shop_service_common中创建 com.yyj.entity.Product实体类,并配置
package com.yyj.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;

@Entity
@Table(name="tb_product")
@Data
public class Product {
    @Id
    private Long id;
    private String productName;
    private Integer status;
    private BigDecimal price;
    private String productDesc;
    private String caption;
    private Integer inventory;
}
View Code
这里使用了lombok简化实体类的开发,Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率

dao层接口:

在shop_service_product中创建 com.yyj.product.dao.ProductDao 接口
package com.yyj.product.dao;

import com.yyj.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface ProductDao extends JpaRepository<Product,Long>, JpaSpecificationExecutor<Product> {
}

service层:

在shop_service_product中创建 com.yyj.product.service.ProductService
package com.yyj.product.service;

import com.yyj.entity.Product;

import java.util.List;

public interface ProductService {
    //根据id查询
    Product findById(Long id);

    //查询全部
    List findAll();

    //保存
    void save(Product product);

    //更新
    void update(Product product);

    //删除
    void delete(Long id);
}
View Code
在shop_service_product中创建 com.yyj.product.service.impl.ProductServiceImpl 实现类
package com.yyj.product.service.impl;

import com.yyj.entity.Product;
import com.yyj.product.dao.ProductDao;
import com.yyj.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductDao productDao;

    @Override
    public Product findById(Long id) {
        return productDao.findById(id).get();
    }

    @Override
    public List findAll() {
        return productDao.findAll();
    }

    @Override
    public void save(Product product) {
        productDao.save(product);
    }

    @Override
    public void update(Product product) {
        productDao.save(product);
    }

    @Override
    public void delete(Long id) {
        productDao.deleteById(id);
    }
}
View Code

controller层:

在shop_service_product中创建 com.yyj.product.controller.ProductController
package com.yyj.product.controller;

import com.yyj.entity.Product;
import com.yyj.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @GetMapping
    public List findAll() {
        return productService.findAll();
    }

    @GetMapping("/{id}")
    public Product findById(@PathVariable Long id) {
        return productService.findById(id);
    }

    @PostMapping
    public String save(@RequestBody Product product) {
        productService.save(product);
        return "保存成功";
    }

    @PutMapping("/{id}")
    public String update(@RequestBody Product product) {
        productService.update(product);
        return "修改成功";
    }

    @DeleteMapping("/{id}")
    public String delete(Long id) {
        productService.delete(id);
        return "删除成功";
    }
}
View Code
controller中使用的@GetMapping是一个组合注解,相当与@RequestMapping(method="get")。
类似的注解还有@PostMapping,@PutMapping,@DeleteMapping

配置启动类

在shop_service_product中创建 com.yyj.product.ProductApplication 启动类
package com.yyj.product;

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

@SpringBootApplication(scanBasePackages = {"com.yyj.product"})
@EntityScan("com.yyj.entity")
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class,args);
    }
}

配置application.yml文件

server:
  port: 9002
spring:
  application:
    name: shop-service-product
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    username: root
    password: 123
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
View Code

用户和订单微服务与上述微服务类似,根据商品微服务进行编写

服务调用

前文已经编写了三个基础的微服务,在用户下单时需要调用商品微服务获取商品数据。那应该怎么做呢?显然,商品微服务提供了供人调用的HTTP接口。所以可以再下定单的时候使用http请求的相关工具类完成,如常见的HttpClient,OkHttp,当然也可以使用Spring提供的RestTemplate 

RestTemplate介绍

Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。 
在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring 模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。考虑到RestTemplate类是为调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。 

RestTemplate方法介绍

通过RestTemplate调用微服务

(1) 在 shop_service_order工程中ProductApplication启动类 中配置RestTemplate
    //配置RestTemplate交给spring管理
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
(2) 编写下订单方法
@PostMapping("/{id}")
 public String order(Integer num) {
 //通过restTemplate调用商品微服务
 Product object =
restTemplate.getForObject("http://127.0.0.1:9002/product/1", Product.class);
 System.out.println(object);
 return "操作成功";
 }

硬编码存在的问题

至此已经可以通过RestTemplate调用商品微服务的RESTFul API接口。但是我们把提供者的网络地址(ip,端口)等硬编码到了代码中,这种做法存在许多问题:
  应用场景有局限
  无法动态调整
那么应该怎么解决呢,就需要通过注册中心动态的对服务注册和服务发现 
posted @ 2021-07-27 11:01  1640808365  阅读(252)  评论(0编辑  收藏  举报