SpringBoot整合Restful架构

文章目录

  • 1.1、使用RestTemplate调用Rest服务
  • 1.2、Swagger集成
  • 1.3、动态修改日志级别

Spring与Restful整合才是微架构的核心,虽然在整个SpringBoot(SpringCloud)之中提供有大量的服务方便整合,但是这些整合都不如Rest重要,因为Rest是整个在微架构之中进行通讯的基础模式。那么对于Rest首先必须对其有一个最为核心的解释:利用JSON实现数据的交互处理。而且Spring里面提供有一个非常强大的RestTemplate操作模板,利用此模板可以非常轻松的实现Rest的Json数据与各种对象间的自动转换。

在默认状态下Spring里面针对Rest的处理使用的都是jackson开发支持包。

1.1、使用RestTemplate调用Rest服务

由于Rest属于分布式的项目开发环境,所以本次进行项目建立的时候一共建立有三个子模块:

  • microboot-restful-api:作为公共的类定义,例如:可以将所有的VO类定义在此项目之中

  • microboot-restful-provider:作为服务提供者,这次的服务提供者提供两个服务(获得对象、增加对象)

  • microboot-restful-consumer:作为服务的消费者,消费者就是利用RestTemplate实现Rest服务的调用以及对象转换

1、【microboot-restful-api】建立一个公共的VO类对象:

package cn.mldn.microboot.vo;

import java.io.Serializable;
import java.util.Date;

public class Member implements Serializable {
    private static final long serialVersionUID = 5879393512553198949L;

    private Long mid;
    private String name;
    private Integer age;
    private Double salary;
    private Date birthday;
   
   ......(省略getset和 toString 方法)...... 
}

2、【microboot-restful-provider】修改pom.xml配置文件,去引用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.mldn.microboot.controller;

import cn.mldn.microboot.vo.Member;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
public class MemberController {

    @RequestMapping(value = "/member/add")
    public Object add(Member member){
        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("mldn -" + mid);
        vo.setBirthday(new Date());
        vo.setSalary(9999.99);
        vo.setAge(16);
        return vo;
    }
}

4、【microboot-restful-provider】定义程序启动类,启动服务,而后测试当前服务是否可用:

  • 获取对象信息:http://localhost:8080/member/get?mid=110

  • 增加对象信息:http://localhost:8080/member/add?mid=110&name=smith&age=12

5、【microboot-restful-consumer】如果要进行Rest操作,那么一定要注意使用一个RestTemplate模板完成处理,所以首先要建立一个程序配置类,进行RestTemplate模板对象创建:

package cn.mldn.microboot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestConfig {
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

6、【microboot-restful-consumer】修改application.yml配置端口:

server:
  port: 80

7、【microboot-restful-consumer】编写测试程序类测试远程Rest服务是否可用:

package cn.mldn.microboot;

import cn.mldn.microboot.vo.Member;
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 javax.annotation.Resource;

@SpringBootTest(classes = MicrobootRestfulConsumerApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestMemberRestful {

    @Resource
    private RestTemplate restTemplate;

    @Test
    public void testAdd(){
        //通过远程的Rest服务中的信息将其自动转换为member对象实例
        Boolean flag = this.restTemplate.getForObject("http://localhost:8080/member/add?mid=110&name=SMITH&age=12", Boolean.class);
        System.out.println("【ConsumerTest.add()】" + flag);
    }

    @Test
    public 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.mldn.microboot.controller;

import cn.mldn.microboot.vo.Member;
import org.springframework.web.bind.annotation.*;

import java.util.Date;

@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("mldn -" + mid);
        vo.setBirthday(new Date());
        vo.setSalary(9999.99);
        vo.setAge(16);
        return vo;
    }
}

9、【microboot-restful-consumer】编写一个调用控制器进行处理:

package cn.mldn.microboot.controller;

import cn.mldn.microboot.util.controller.AbstractBaseController;
import cn.mldn.microboot.vo.Member;
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 javax.annotation.Resource;

@Controller
public class MemberConsumerController extends AbstractBaseController {

    @Resource
    private 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)
    @ResponseBody
    public Object addMember(Member member) {
        Boolean flag = this.restTemplate.postForObject(
                "http://localhost:8080/member/add", member, Boolean.class);
        return flag;
    }
}

10、【microboot-restful-consumer】为了方便进行接受数据的演示,建立一个普通的thymeleaf页面:

<!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>
<p th:text="'用户姓名:'+ ${member.name}" ></p>
<p th:text="'用户年龄:'+ ${member.age}" ></p>
<p th:text="'用户工资:'+ ${member.salary}" ></p>
<p th:text="'用户生日:'+ ${member.birthday}" ></p>
</body>
</html>

11、【microboot-restful-consumer】访问消费端服务:

  • 测试信息获得操作:http://localhost/consumer/get?mid=120

  • 测试信息追加操作:http://localhost/consumer/add?mid=120&name=ALLEN&age=10&salary=9.9&birthday=2000-10-10

12、现在在整个的项目处理之中会发现以下的几个特点:

  • Rest服务的生产者只是按照自己返回的内容进行JSON数据的输出

  • 消费者利用RestTemplate进行JSON数据的获得以及自动向指定类型的对象进行转换

  • 为了达到这种转换的操作标准,特意准备了一个api项目保存公共的VO类型


而对于Rest服务的更多考虑,应该包含如下几点:

  • 既然服务端的提供者只能够被消费者所访问,证明其不能被所有用户操作,一定需要安全认证;

  • 服务端一定要进行指定业务层和数据层的编写,也就是说每一个服务端都应该具备有一个自己的服务器信息

  • 在服务器访问非常繁忙的时候,消费端执行时有可能需要进行短期的熔断处理

  • 服务端既然时一个独立的组件,那么就必须考虑负载均衡问题

  • 消费端进行服务端的调用操作,如果所有的调用都写上明确的调用地址,太麻烦了

  • 消费端进行处理的时候如果都是自己来采用RestTemplate做处理,代码结构太差了,因为毕竟服务端是远程业务端,远程业务端最好的调用应该就用接口完成。

1.2、Swagger集成

当你现在建立一些公共的Rest服务的时候就可以利用Swagger进行所有Rest服务的描述了。也就是说它提供的只是一个说明工具的概念。

1、 如果要想去使用Swagger说明操作,则必须引入相应的依赖支持包:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

2、定义一个进行Swagger2的配置程序类:

package cn.mldn.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 {
    @Bean
    public Docket getDocket() { //此类主要是整个Swagger配置项,利用这个类需要来指派扫描包
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(this.getApiInfo()).select()
                .apis(RequestHandlerSelectors.basePackage("cn.mldn.microboot.controller"))
                .paths(PathSelectors.any()).build();
    }

    private ApiInfo getApiInfo() {
        return new ApiInfoBuilder().title("SpringBoot中使用Swagger构建项目说明信息")
                .description("更多选择请关注www.mldn.cn")
                .termsOfServiceUrl("http://www.mldn.cn")
                .contact("小明同学")
                .license("李小明")
                .version("1.0").build();
    }
}

3、修改MemberController程序类,追加相关注解信息:

package cn.mldn.microboot.controller;

import java.util.Date;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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.mldn.microboot.vo.Member;

@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("mldnjava - " + mid);
		vo.setBirthday(new Date());
		vo.setSalary(99999.99);
		vo.setAge(16);
		return vo;
	}
}

4、正常进行程序的启动配置处理,而后打开浏览器进入到界面:http://localhost:8080/swagger-ui.html
SpringBoot整合Restful架构_第1张图片

1.3、动态修改日志级别

在项目开发之中日志可以使用info()、error()里面提供一个比较有意思的功能,就是说用户可以通过远程的控制追加日志显示级别的操作。

1、定义一个简单的控制器程序:

package cn.mldn.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(){
        this.log.info("【*** INFO ***】日志输出");
        this.log.error("【*** ERROR ***】日志输出");
        return true;
    }
}

2、如果现在希望只进行error级别的日志输出,则修改application.yml配置文件:

logging:
  level:
    cn.mldn.microboot.controller: ERROR

3、现在希望在以后程序运行的时候这个日志的输出级别可以动态的做一个扩充,所以这个时候要想达到这个目的就可以必须进行安全的关闭操作,修改application.yml配置文件:

<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management:
  security:
    enabled: false

4、随后在一个客户端上进行修改,直接利用测试类完成。

package cn.mldn.microboot.vo;

public class LoginInfo {
    
    private String level;

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }
}

5、随后在【microboot-restful-consumer】编写一个测试类修改日志级别:

package cn.mldn.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.mldn.microboot.vo.LogInfo;

@SpringBootTest(classes = StartSpringBootMain.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestLogger {
	@Resource
	private RestTemplate restTemplate;
	@Test
	public void testLevel() {
		LogInfo log = new LogInfo();
		log.setLevel("INFO"); // 新的日志级别
		this.restTemplate.postForLocation(
				"http://localhost:8080/loggers/cn.mldn.microboot.controller",
				log);
	}
}

你可能感兴趣的:(Restful)