Spring 与 Restful 整合才是微架构的核心,虽然在整个 SpringBoot(SpringCloud)之中提供有大量的
服务方便整合,但是这些 整合都不如 Rest 重要,因为 Rest 是整个在微架构之中进行通讯的基础模式。
那么对于 Rest 首先必须对其有一个最为核心的解释: 利用 JSON 实现数据的交互处理。而且 Spring 里面
提供有一个非常强大的 RestTemplate 操作模版,利用此模版可以非常轻松的实现 Rest 的 JSON 数据与
各种对象间的自动转换。
2.1、使用 RestTemplate 模版实现 Rest 服务调用由于 Rest 属于分布式的项目开发环境,所以本次进行项目建立的时候一共建立有三个子模块:· microboot-restful-api:作为公共的类定义,例如:可以将所有的 VO 类定义在此项目之中;· microboot-restful-provider:作为服务提供者,这次的服务提供者提供两个服务
(获得对象、增加对象);· micorboot-restful-consumer:作为服务的消费者,消费者就是利用 RestTemplate 实现 Rest 服务的
调用以及对象转换
1、 【microboot-restful-api】建立一个公共的 VO 类对象:package cn.study.microboot.vo;import java.io.Serializable;
import java.util.Date;@SuppressWarnings("serial")
public class Member implements Serializable {private Long mid ;private String name ;private Integer age ;private Double salary ;private Date birthday ;public Long getMid() {return mid;}public void setMid(Long mid) {this.mid = mid;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Double getSalary() {return salary;}public void setSalary(Double salary) {this.salary = salary;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "Member [mid=" + mid + ", name=" + name + ", age=" + age+ ", salary=" + salary + ", birthday=" + birthday + "]";}
}
2、 【microboot-restful-provider】修改 pom.xml 配置文件,去引用 microboot-restful-api模块:<dependency><groupId>cn.mldn</groupId><artifactId>microboot-restful-api</artifactId><version>0.0.1-SNAPSHOT</version></dependency>
3、 【microboot-restful-provider】建立一个控制器实现 Rest 服务的处理:package cn.study.microboot.controller;import java.util.Date;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import cn.study.microboot.vo.Member;@RestController
public class MemberController {@RequestMapping(value = "/member/add")public Object add(Member member) {    // 表示当前的配置可以直接将参数变为VO对象System.err.println("【MemberController.add()接收对象】" + member);return true;}@RequestMapping(value = "/member/get")public Member get(long mid) {Member vo = new Member();vo.setMid(mid);vo.setName("studyjava - " + mid);vo.setBirthday(new Date());vo.setSalary(99999.99);vo.setAge(16);return vo;}
}
4、 【microboot-restful-provider】定义程序启动类,启动服务,而后测试当前服务是否可用:package cn.study.microboot;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;@SpringBootApplication
public class RestfulProviderStartSpringBootMain extends SpringBootServletInitializer {
// 必须继承指定的父类@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(RestfulProviderStartSpringBootMain.class) ;}public static void main(String[] args) throws Exception {SpringApplication.run(RestfulProviderStartSpringBootMain.class, args);}
}· 获取对象信息:http://localhost:8080/member/get?mid=110{"mid":110,"name":"studyjava - 110","age":16,"salary":99999.99,"birthday":1551841349990}· 增加对象信息:http://localhost:8080/member/add?mid=110&name=smith&age=12true
5、 【microboot-restful-consumer】如果要进行 Rest 操作,那么一定要注意使用一个 RestTemplate
模版完成处理,所以首先要建立一个程序配置类,进行 RestTemplate 模版对象创建:package cn.study.microboot.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class RestConfig {@Beanpublic RestTemplate getRestTemplate() { return new RestTemplate() ;}
}
6、 【microboot-restful-consumer】修改 application.yml 配置端口:server.port = 80
package cn.study.microboot;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ConsumerStartSpringBootMain{ // 必须继承指定的父类public static void main(String[] args) throws Exception {SpringApplication.run(ConsumerStartSpringBootMain.class, args);}
}package cn.study.microboot;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate;import cn.study.microboot.vo.Member;@SpringBootTest(classes = ConsumerStartSpringBootMain.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestMemberRestful {@Resourceprivate RestTemplate restTemplate; @Testpublic void testAdd() {Boolean flag = this.restTemplate.getForObject("http://localhost:8080/member/add?mid=110&name=SMITH&age=10",Boolean.class);System.out.println("【ConsumerTest.add()】" + flag);}@Testpublic void testGet() {// 通过远程的Rest服务中的信息将其自动转换为Member对象实例Member member = this.restTemplate.getForObject("http://localhost:8080/member/get?mid=110", Member.class);System.out.println("【ConsumerTest.get()】" + member);}
}
8、 【microboot-restful-provider】为了更方便的进行内容的传输,此时 Rest 服务的提供方一定要做出
一点点修改:package cn.study.microboot.controller;import java.util.Date;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 cn.study.microboot.vo.Member;@RestController
public class MemberController {@RequestMapping(value = "/member/add",method=RequestMethod.POST)public Object add(@RequestBody Member member) {    // 表示当前的配置可以直接将参数变为VO对象System.err.println("【MemberController.add()接收对象】" + member);return true;}@RequestMapping(value = "/member/get/{mid}",method=RequestMethod.GET)public Member get(@PathVariable("mid") long mid) {Member vo = new Member();vo.setMid(mid);vo.setName("studyjava - " + mid);vo.setBirthday(new Date());vo.setSalary(99999.99);vo.setAge(16);return vo;}
}
9、 【microboot-restful-consumer】编写一个调用控制器进行处理;package cn.study.microboot.controller;import javax.annotation.Resource;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;import cn.study.microboot.vo.Member;@Controller
public class MemberConsumerController extends AbstractBaseController{@Resourceprivate RestTemplate restTemplate;@RequestMapping(value = "/consumer/get", method = RequestMethod.GET)@ResponseBodypublic Member getMember(long mid,Model model) {Member member = this.restTemplate.getForObject("http://localhost:8080/member/get/" + mid, Member.class);model.addAttribute("member", member) ;return member;}@RequestMapping(value = "/consumer/add", method = RequestMethod.GET)@ResponseBodypublic Object addMember(Member member) {Boolean flag = this.restTemplate.postForObject("http://localhost:8080/member/add", member, Boolean.class);return flag;}
}package cn.study.microboot.controller;import java.text.SimpleDateFormat;
import java.util.Locale;import javax.annotation.Resource;import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.MessageSource;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;public abstract class AbstractBaseController {// 自动注入此资源的对象@Resourceprivate MessageSource messageSource;public String getMessage(String key, String ...args) {return this.messageSource.getMessage(key, args,Locale.getDefault());}@InitBinderpublic void initBinder(WebDataBinder binder) {    // 在本程序里面需要针对于日期格式进行处理// 首先建立一个可以将字符串转换为日期的工具程序类SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;// 明确的描述此时需要注册一个日期格式的转化处理程序类binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));}}
11、 【microboot-restful-consumer】访问消费端服务:· 测试信息追加操作:
http://localhost/consumer/add?mid=120&name=ALLEN&age=10&salary=9.9&birthday=2000-10-10true测试信息获得操作:http://localhost/consumer/get?mid=120{"mid":120,"name":"studyjava - 120","age":16,"salary":99999.99,"birthday":1551844293999}
· Rest 服务的生产者只是按照自己返回的内容进行 JSON 数据的输出;· 消费者利用 RestTemplate 进行 JSON 数据的获得以及自动向指定类型的对象进行转换;· 为了达到这种转换的操作标准,特意准备了一个 api 项目保存公共的 VO 类型。
package cn.study.microboot.controller;import javax.annotation.Resource;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;import cn.study.microboot.vo.Member;@Controller
public class MemberConsumerController extends AbstractBaseController{@Resourceprivate RestTemplate restTemplate;@RequestMapping(value = "/consumer/get", method = RequestMethod.GET)public String getMember(long mid,Model model) {Member member = this.restTemplate.getForObject("http://localhost:8080/member/get/" + mid, Member.class);model.addAttribute("member", member) ;return "member_show";}@RequestMapping(value = "/consumer/add", method = RequestMethod.GET)@ResponseBodypublic Object addMember(Member member) {Boolean flag = this.restTemplate.postForObject("http://localhost:8080/member/add", member, Boolean.class);return flag;}
}<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>microboot-restful-consumer</groupId><artifactId>microboot-restful-consumer</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><thymeleaf.version>3.0.9.RELEASE</thymeleaf.version><thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version><!-- 布局功能的支持程序 thymeleaf3主程序 layout2以上版本 --><!-- thymeleaf2 layout1 --><thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version></properties>    <dependencies><dependency><!-- 引入web模块 --><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>microboot-restful-api</groupId><artifactId>microboot-restful-api</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency></dependencies></project>member_show.html<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>SpringBoot模版渲染</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
</head>
<body><p th:text="'用户编号:' + ${member.mid}"/><p th:text="'用户姓名:' + ${member.name}"/><p th:text="'用户年龄:' + ${member.age}"/><p th:text="'用户工资:' + ${member.salary}"/><p th:text="'用户生日:' + ${member.birthday}"/>
</body>
</html>http://localhost/consumer/get?mid=120用户编号:120用户姓名:studyjava - 120用户年龄:16用户工资:99999.99用户生日:Wed Mar 06 12:01:14 CST 2019

而对于 Rest 服务的更多考虑,应该包含如下几点:· 既然服务的提供者只能够被消费者所访问,证明其不可能被所有用户操作,一定需要安全认证;· 服务端一定要进行指定业务层和数据层的编写,也就是说每一个服务端都应该具备有一个自己的服务器信息;· 在服务端访问非常繁忙的时候,消费端执行时有可能需要进行短期的熔断处理;· 服务端既然是一个独立的组件,那么就必须考虑负载均衡问题;· 消费端进行服务端的调用操作,如果所有的调用都写上明确的调用地址,太麻烦了;· 消费端进行处理的时候如果都是自己来直接采用 RestTemplate 做处理,代码结构太差了,因为毕竟服务端
是远程业务端,远程业务端最好的调用应该就用接口完成。
 当你现在建立一些公共的 Rest 服务的时候就可以利用 Swagger 进行所有 Rest 服务的描述了。也就是说它提供的只是一个说明 工具的概念。1、 如果要想去使用 swagger 说明操作,则必须引入相应的依赖支持包:<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.7.0</version></dependency>
2、 定义一个进行 Swagger2 的配置程序类:package cn.study.microboot.config;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;@Configuration
@EnableSwagger2
public class Swagger2Config {@Beanpublic Docket getDocket() { // 此类主要是整个的Swagger配置项,利用这个类需要来指派扫描包return new Docket(DocumentationType.SWAGGER_2).apiInfo(this.getApiInfo()).select().apis(RequestHandlerSelectors.basePackage("cn.study.microboot.controller")).paths(PathSelectors.any()).build(); // 设置文档的显示类型}private ApiInfo getApiInfo() {return new ApiInfoBuilder().title("SpringBoot中使用Swagger构建项目说明信息").description("接口描述信息").termsOfServiceUrl("http://www.study.cn").contact("study——springbooot").license("small lee").version("1.0").build();}
}
3、 修改 MemberController 程序类,追加相关注解信息:package cn.study.microboot.controller;import java.util.Date;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 cn.study.microboot.vo.Member;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;@RestController
public class MemberController {@ApiOperation(value = "实现人员信息的添加处理", notes = "添加")@ApiImplicitParams({@ApiImplicitParam(name = "member", value = "用户描述的详细实体信息",
required = true, dataType = "MemberClass")})@RequestMapping(value = "/member/add", method = RequestMethod.POST)public Object add(@RequestBody Member member) {
// 表示当前的配置可以直接将参数变为VO对象System.err.println("【MemberController.add()接收对象】" + member);return true;}@ApiOperation(value = "获取指定编号的人员信息",
notes = "只需要设置mid的信息就可以获取Member的完整内容")@ApiImplicitParams({@ApiImplicitParam(name = "mid", value = "用户编号",
required = true, dataType = "String")})@RequestMapping(value = "/member/get/{mid}", method = RequestMethod.GET)public Member get(@PathVariable("mid") long mid) {Member vo = new Member();vo.setMid(mid);vo.setName("studyjava - " + mid);vo.setBirthday(new Date());vo.setSalary(99999.99);vo.setAge(16);return vo;}
}
4、 正常进行程序的启动配置处理,而后打开浏览器进入到界面:http://localhost:8080/swagger-ui.html
2.3、动态修改日志级别在项目开发之中日志可以使用 info()、error()进行输出在 SpringBoot 里面提供有一个比较有意思的
功能,就是说用户可以通过 远程的控制追加日志的显示级别的操作。package cn.study.microboot.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class MessageController {private Logger log = LoggerFactory.getLogger(MessageController.class);@RequestMapping(value = "/test")public Object add() { // 表示当前的配置可以直接将参数变为VO对象this.log.info("【*** INFO ***】 日志输出");this.log.info("【*** ERROR ***】 日志输出");return true;}
}http://localhost:8080/testtrue
2、 如果现在希望只进行 error 级别的日志输出,则修改 application.yml 配置文件:application.propertieslogging:level:cn.study.microboot.controller: ERROR
3、 现在希望在以后程序运行的时候这个日志的输出级别可以动态的做一个扩充,所以这个时候要想达到这样的
目的就可以必须 进行安全的关闭操作,修改 pom.xml和application.properties 配置文件:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>management.security.enabled
4、 随后在一个客户端上进行修改,直接利用测试类完成。package cn.study.microboot.vo;public class LogInfo {private String level;public String getLevel() {return level;}public void setLevel(String level) {this.level = level;}@Overridepublic String toString() {return "LogInfo [level=" + level + "]";}}
5、 随后编写一个测试类修改日志级别:package cn.study.microboot.test;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate;import cn.study.microboot.ProviderStartSpringBootMain;
import cn.study.microboot.vo.LogInfo;@SpringBootTest(classes = ProviderStartSpringBootMain.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestLogger {@Resourceprivate RestTemplate restTemplate;@Testpublic void testLevel() {LogInfo log = new LogInfo();log.setLevel("INFO"); // 新的日志级别this.restTemplate.postForLocation(
"http://localhost:8080/loggers/cn.study.microboot.controller",log);}
}动态修改日志级别是 actuator 给出的一个简单支持,但是在实际之中日志的处理更多的情况下不会取消
安全配置,所以这种日 志的配置也不是全部可以使用。

使用RestTemplate模版实现 Rest 服务调用、Swagger 集成、动态修改日志级别相关推荐

  1. NRF51822蓝牙服务(9)——动态修改设备的名称

    前言 很多时候我们希望能够通过手机动态修改设备的MAC地址.配对密码或者蓝牙设备信息等,其实原理上都是可以实现的.大概思路其实就是把我们需要修改的内容发送到FLASH中保存,然后再用FLASH中的内容 ...

  2. vue调用百度地图动态修改中心点

    初始化地图 initialApi () {       var map = new BMap.Map("allmap") //初始化地图时中心点的位置为深圳       var p ...

  3. Spring Cloud —— Feign 实现服务调用

    引言 本篇博客简单介绍 Feign 的基础知识和基本应用,以前一篇博客<Spring Cloud Alibaba--Nacos实现服务治理>为代码基础,实现更简单的微服务调用方式. 一.什 ...

  4. 利用java实现简单的RPC服务调用

    一.前言 RPC(Remote Procedure Call Protocol)--远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输 ...

  5. 调用链路_全链路日志分析解决方案介绍

    为何需要链路分析? 您是否了解运维环境的网络架构和业务系统架构?当业务升级或变更时,是否对已有的架构图及时作出更新?当发生故障时,是否能够快速判断哪个业务系统模块或接口出现了问题,是否能够快速判断故障 ...

  6. SpringCloud微服务架构,Spring Cloud 服务治理(Eureka,Consul,Nacos),Ribbon 客户端负载均衡,RestTemplate与OpenFeign实现远程调用

    什么是SpringCloud 微服务架构 • "微服务"一词源于 Martin Fowler的名为 Microservices的博文,可以在他的官方博客上找到 http://mar ...

  7. ribbon, restTemplate 负载均衡服务调用

    ribbon ribbon concept ribbon核心组件IRule 模仿源码重写轮询 ribbon concept spring cloud ribbon 是基于Netflix ribbon实 ...

  8. Spring Cloud之(四)基于RestTemplate的微服务调用

    四.基于RestTemplate的微服务调用 前面我们已经成功的把第一个小案例跑起来了,其中消费者使用了RestTemplate来调用提供者提供的微服务,下面就来详细的说明一下RestTemplate ...

  9. 两个子集pom互相调用_声明式服务调用组件Feign

    什么是Feign?    Feign是SpringCloud组件中的一个轻量级RESTful的HTTP服务客户端.Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务. 什么是 ...

最新文章

  1. 【django轻量级框架】View与Model交互(模块的交互关系)
  2. 计算机基本组成: 触发器
  3. 基于ISE的设计实现基础
  4. liferay namespace用法
  5. js encodeurl java接收_在JS中encodeURI(url)怎样才能不出现乱码?
  6. linux下C调用lua的第一个程序
  7. javascript 键值keyCode
  8. vue 获取id元素,vue.js怎么获取dom元素?
  9. 【bzoj2834】回家的路 分层图最短路
  10. 作业5(《构建之法》心得体会)
  11. ant java任务_Ant War任务
  12. 计算机使用快捷键大全
  13. 只需 1 分钟,这个网站用 AI 分离歌曲的人声、伴奏和乐器声
  14. 关于ccs软件的简单使用
  15. 2376. 统计特殊整数--(每日一难phase2--day4)
  16. matlab数控加工,关于MATLAB复杂型面数控加工编程.pdf
  17. ThinkPad SL400使用手札
  18. make menuconfig快速查找
  19. 如何解压war后缀的文件:
  20. [LibreOJ 3124]【CTS2019】氪金手游【容斥原理】【概率】【树形DP】

热门文章

  1. PHP如何添加变量 $_SERVER
  2. 设计模式笔记(19)---观察者模式(行为型)
  3. t2 初识Tornado
  4. 2019《去哪儿》春季校招第一站(含笔试题)
  5. Javascrip—拷贝对象(13)
  6. golang协程进行同步方法
  7. zookeeper+kafka配置
  8. 登陆时不显示上一次登陆的用户名
  9. keepalived配置文件详解   ​
  10. freemarker 概述