Spring Cloud工程完善
目录
完善订单服务
启动类
配置文件
实体类
Controller
Service
Mapper
测试运行
完成商品服务
启动类
配置文件
实体类
Controller
Service
Mapper
测试运行
远程调用
需求
实现
1.定义RestTemplate
2.修改order-service中的OrderService
测试运行
RestTemplate
什么是REST?
什么是RESTful?
RESTful API 缺点:
完善订单服务
启动类
package order; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
配置文件
server: port: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/cloud_order?characterEncoding=utf8&useSSL=false username: root password: #密码 driver-class-name: com.mysql.cj.jdbc.Driver # 设置 Mybatis 的 xml 保存路径 mybatis: configuration: # 配置打印 MyBatis 执行的 SQL log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true #自动驼峰转换
实体类
package order.model; import lombok.Data; import java.util.Date; @Data public class OrderInfo { private Integer id; private Integer userId; private Integer productId; private Integer num; private Integer price; private Integer deleteFlag; private Date createTime; private Date updateTime; }
Controller
package order.controller; import order.model.OrderInfo; import order.service.OrderService; 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; @RequestMapping("/order") @RestController public class OrderController { @Autowired private OrderService orderService; @RequestMapping("/{orderId}") public OrderInfo getOrderById(@PathVariable("orderId") Integer orderId){ return orderService.selectOrderById(orderId); } }
Service
package order.service; import order.mapper.OrderMapper; import order.model.OrderInfo; import order.model.ProductInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class OrderService { @Autowired private OrderMapper orderMapper; public OrderInfo selectOrderById(Integer orderId) { OrderInfo orderInfo = orderMapper.selectOrderById(orderId); return orderInfo; } }
Mapper
package order.mapper; import order.model.OrderInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; @Mapper public interface OrderMapper { @Select("select * from order_detail where id=#{orderId}") OrderInfo selectOrderById(Integer orderId); }
测试运行
完成商品服务
启动类
package product; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ProductServiceApplication { public static void main(String[] args) { SpringApplication.run(ProductServiceApplication.class, args); } }
配置文件
server: port: 9090 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/cloud_product?characterEncoding=utf8&useSSL=false username: root password: #密码 driver-class-name: com.mysql.cj.jdbc.Driver # 设置 Mybatis 的 xml 保存路径 mybatis: configuration: # 配置打印 MyBatis 执行的 SQL log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true #自动驼峰转换
实体类
package product.model; import lombok.Data; import java.util.Date; @Data public class ProductInfo { private Integer id; private String productName; private Integer productPrice; private Integer state; private Date createTime; private Date updateTime; }
Controller
package product.controller; import lombok.extern.slf4j.Slf4j; 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 product.model.ProductInfo; import product.service.ProductService; @Slf4j @RequestMapping("/product") @RestController public class ProductController { @Autowired private ProductService productService; @RequestMapping("/{productId}") public ProductInfo getProductById(@PathVariable("productId") Integer productId){ log.info("接收到参数"+productId); return productService.selectProductById(productId); } }
Service
package product.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import product.mapper.ProductMapper; import product.model.ProductInfo; @Service public class ProductService { @Autowired private ProductMapper productMapper; public ProductInfo selectProductById(Integer id){ return productMapper.selectProductById(id); } }
Mapper
package product.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import product.model.ProductInfo; @Mapper public interface ProductMapper { @Select("select * from product_detail where id = #{id}") ProductInfo selectProductById(Integer id); }
测试运行
远程调用
需求
根据订单查询订单信息时, 根据订单⾥产品ID, 获取产品的详细信息.
实现
实现思路: order-service服务向product-service服务发送⼀个http请求, 把得到的返回结果, 和订单结果融合在⼀起, 返回给调⽤⽅。
实现⽅式: 采⽤Spring 提供的RestTemplate。
1.定义RestTemplate
package order.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class BeanConfig { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
2.修改order-service中的OrderService
package order.service; import order.mapper.OrderMapper; import order.model.OrderInfo; import order.model.ProductInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private RestTemplate restTemplate; public OrderInfo selectOrderById(Integer orderId){ OrderInfo orderInfo = orderMapper.selectOrderById(orderId); String url = "http://127.0.0.1:9090/product/"+orderInfo.getProductId(); ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class); orderInfo.setProductInfo(productInfo); return orderInfo; } }
测试运行
RestTemplate
RestTemplate 是从 Spring3.0 开始⽀持的⼀个 HTTP 请求⼯具, 它是⼀个同步的 REST API 客⼾端, 提供了常⻅的REST请求⽅案的模版。
什么是REST?
REST(Representational State Transfer), 表现层资源状态转移.
REST是由HTTP的主要设计者Roy Fielding博⼠在2000年他的博⼠论⽂中提出来的⼀种软件架构⻛格.
这⾥⾯主要有三个概念:
1. 资源: ⽹络上的所有事物都可以抽象为资源, 每个资源都有⼀个唯⼀的资源标识符(URI)
2. 表现层: 资源的表现形式, ⽐如⽂本作为资源, 可以⽤txt格式表现, 也可以通过HTML, XML, JSON等格式来表现, 甚⾄以⼆进制的格式表现.
3. 状态转移: 访问URI, 也就是客⼾端和服务器的交互过程. 客⼾端⽤到的⼿段,只能是HTTP协议. 这个过程中, 可能会涉及到数据状态的变化. ⽐如对数据的增删改查, 都是状态的转移.
REST 是⼀种设计⻛格, 指资源在⽹络中以某种表现形式进⾏状态转移.
简单来说: REST描述的是在⽹络中Client和Server的⼀种交互形式, REST本⾝不实⽤,实⽤的是如何设计 RESTful API(REST⻛格的⽹络接⼝).
什么是RESTful?
REST 是⼀种设计⻛格, 并没有⼀个明确的标准. 满⾜这种设计⻛格的程序或接⼝我们称之为RESTful(从单词字⾯来看就是⼀个形容词). 所以RESTful API 就是满⾜REST架构⻛格的接⼝.
RESTful ⻛格⼤致有以下⼏个主要特征:
1. 资源: 资源可以是⼀个图⽚, ⾳频, 视频或者JSON格式等⽹络上的⼀个实体, 除了⼀些⼆进制的资源外普通的⽂本资源更多以JSON为载体、⾯向⽤⼾的⼀组数据(通常从数据库中查询⽽得到) .
2. 统⼀接⼝: 对资源的操作. ⽐如获取, 创建, 修改和删除. 这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE⽅法. 换⾔⽽知,如果使⽤RESTful⻛格的接⼝, 从接⼝上你可能只能定位其资源,但是⽆法知晓它具体进⾏了什么操作,需要具体了解其发⽣了什么操作动作要从其HTTP请求⽅法类型上进⾏判断。
RestTemplate 是Spring提供, 封装HTTP调⽤, 并强制使⽤RESTful⻛格. 它会处理HTTP连接和关闭,只需要使⽤者提供资源的地址和参数即可.
RESTful实践
RESTful⻛格的API 固然很好很规范, 但⼤多数互联⽹公司并没有按照其规则来设计, 因为REST是⼀种风格,⽽不是⼀种约束或规则, 过于理想的RESTful API 会付出太多的成本.
RESTful API 缺点:
1. 操作⽅式繁琐, RESTful API通常根据GET, POST, PUT, DELETE 来区分对资源的操作动作. 但是HTTP Method 并不可直接⻅到, 需要通过抓包等⼯具才能观察. 如果把动作放在URL上反⽽更加直观, 更利于团队的理解和交流.
2. ⼀些浏览器对GET, POST之外的请求⽀持不太友好, 需要额外处理.
3. 过分强调资源. ⽽实际业务需求可能⽐较复杂, 并不能单纯使⽤增删改查就能满⾜需求, 强⾏使⽤RESTful API会增加开发难度和成本。
所以, 在实际开发中, 如果业务需求和RESTful API不太匹配或者很⿇烦时, 也可以不⽤RESTful API. 如果使⽤场景和REST⻛格⽐较匹配, 就可以采⽤RESTful API.
总之: ⽆论哪种⻛格的API, 都是为了⽅便团队开发, 协商以及管理, 不能墨守成规. 尽信书不如⽆书, 尽信规范不如⽆规范。
欢迎大家访问我的主页---》链接