维基上对其定义为:一种软件开发技术- 面向服务的体系结构(SOA)架构样式的一种变体,将应用程序构造为一组**松散耦合**的服务。在微服务体系结构中,服务是细粒度的,协议是轻量级的。
微服务(或微服务架构)是一种云原生架构方法,其中单个应用程序由许多松散耦合且可独立部署的较小组件或服务组成。这些服务通常具有以下特征:
尽管有关微服务的许多讨论都围绕体系结构定义和特征展开,但它们的价值可以通过相当简单的业务和组织收益更普遍地理解:
微服务是一种用于构建应用的架构方案。微服务架构有别于更为传统的单体式方案,可将应用拆分成多个核心功能。每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作(和出现故障)时不会相互影响。
提起微服务,绝大多数都是前后端分离的项目,前端要么是Vue,要么是小程序或者APP啥的,前后端通过http协议来传递数据。而在SpringBoot项目中,只许通过两个注解,就可以实现最简单的微服务:
@RestController 注解和 @Controller 类似,都是放到controller的类上,用来标识接口的返回值类型。那么两者的区别是什么呢?
如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容,在SpringBoot项目中,会把返回值自动转换为json字符串。
如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。
示例代码:
package com.shenmazong.demohello.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
@Controller
public class IndexController {
@GetMapping(value = "/")
public String index() {
return "index";
}
@GetMapping(value = "/user")
@ResponseBody
public Object getUser() {
HashMap<String, Object> userMap = new HashMap<>();
userMap.put("name", "武松");
userMap.put("age", 35);
return userMap;
}
}
当controller类上,已经使用@Controller注解,但你写的接口还需要返回json或者xml数据怎么办?这是就需要在方法上加@ResponseBody注解。
示例代码:
package com.shenmazong.demohello.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
public class UserController {
@GetMapping(value = "/user")
public Object getUser() {
HashMap<String, Object> userMap = new HashMap<>();
userMap.put("name", "武松");
userMap.put("age", 35);
return userMap;
}
}
SpringBoot实现的微服务默认都是json格式,而且默认序列化的json库是jackson库。但有时候,客户需要xml格式的数据,那么该怎么实现呢?
<!--xml格式-->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
package com.shenmazong.demohello.controller;
import com.shenmazong.demohello.pojo.TbUser;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
public class UserController {
@GetMapping(value = "/json",produces = MediaType.APPLICATION_JSON_VALUE)
public Object getUserJson() {
TbUser tbUser = new TbUser();
tbUser.setUserName("武松");
tbUser.setUserAge(35);
return tbUser;
}
@GetMapping(value = "/xml",produces = MediaType.APPLICATION_XML_VALUE)
public Object getUserXml() {
TbUser tbUser = new TbUser();
tbUser.setUserName("武松");
tbUser.setUserAge(35);
return tbUser;
}
}
package com.shenmazong.demohello.pojo;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;
@Data
@JacksonXmlRootElement(localName = "user")
public class TbUser {
private String userName;
private Integer userAge;
@JacksonXmlCData
@JacksonXmlProperty(localName = "Content")
private String content;
}
@JacksonXmlRootElement注解中有localName属性,该属性如果不设置,那么生成的XML最外面就是
,而不是@JacksonXmlCData注解是为了生成
<![CDATA[text]]>
这样的数据,如果你不需要,可以去掉@JacksonXmlProperty注解通常可以不需要,但是如果你想要你的xml节点名字,首字母大写。比如例子中的Content,那么必须加这个注解,并且注解的localName填上你想要的节点名字。最重要的是!实体类原来的属性content必须首字母小写!否则会被识别成两个不同的属性。
有了上面的配置,在Controller返回实体类的时候,就会像转换Json一样,将实体类转换为xml对象了。有时候你的浏览器并不能识别xml,是因为你返回的content-type不是xml,可以通过修改@RequestMapping注解的produces属性来修改:
运行后的效果如下:
@RequestMapping(value = "/postxml", method = RequestMethod.POST, consumes = { "text/xml" }, produces = {
"application/xml" })
@ResponseBody
public TbUser post(@RequestBody TbUser user) {
return user;
}
测试代码:
package com.shenmazong.demohello;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoHelloApplicationTests {
@Test
void contextLoads() {
}
@Test
public void testPost() throws Exception {
// 直接字符串拼接
StringBuilder builder = new StringBuilder();
// xml数据存储
builder.append("<user>\n" +
"<userName>武松</userName>\n" +
"<userAge>35</userAge>\n" +
"<Content>\n" +
"<![CDATA[ 武松醉打蒋门神 ]]>\n" +
"</Content>\n" +
"</user>");
String data = builder.toString();
System.out.println(data);
String url = "http://localhost:8080/postxml";
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(data, "text/xml", "utf-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity);
System.out.println("content:" + content);
}
}
上面的测试函数需要在pom文件中添加下面的依赖:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
package com.shenmazong.demohello.controller;
import com.shenmazong.demohello.pojo.TbUser;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
@RestController
public class UserController {
@GetMapping(value = "/json",produces = MediaType.APPLICATION_JSON_VALUE)
public Object getUserJson() {
TbUser tbUser = new TbUser();
tbUser.setUserName("武松");
tbUser.setUserAge(35);
tbUser.setContent("武松醉打蒋门神");
return tbUser;
}
@GetMapping(value = "/xml",produces = MediaType.APPLICATION_XML_VALUE)
public Object getUserXml() {
TbUser tbUser = new TbUser();
tbUser.setUserName("武松");
tbUser.setUserAge(35);
tbUser.setContent("武松醉打蒋门神");
return tbUser;
}
@RequestMapping(value = "/postxml", method = RequestMethod.POST, consumes = { "text/xml" }, produces = {
"application/xml" })
@ResponseBody
public TbUser post(@RequestBody TbUser user) {
return user;
}
}