概述
前端和后端的交互
前文说过,大部分情况下前端可以看作是 数据 的需求方,后端可以看作是 数据 的提供方。比如我就是后端,你问我要A的信息,我返回你下面一串东西:
dGhpcyBpcyBhIGV4YW1wbGU=
你能看懂这是什么吗?
同理,如果前后端不以统一的格式来交互的话,也无法正常解析对方的内容。
目前,前后端通信的"运输工具"就是HTTP,它由三部分组成,如下图:
这三部分表示我们可以将数据放置的地方,当前端去向后端通信的时候,它可以在这三个空间中挑选放置数据的地方。URL一般来说是放置需要使用后端哪个功能,以及使用该功能时后端所需的一些必要参数;而header一般来说是放置一些和通信本身有关的信息;body 空间最大,可以放置的数据最多,一般用来放置我们的业务数据。
前端-后端的通信是 请求-响应 式的通信方式,后端收到前端响应后,只能利用HTTP的 Header 和 body 部分进行传参,因为 URL 是标识后端功能项的。
又因为HTTP这个协议也就是这个运输工具内部的仓储构造,导致这三个部分不能随意放置,要遵循一定的规范。
URL的放置规范如下:
后端功能地址 ? 参数名=参数值 & 参数名=参数值
通过 ?
来标识后面的就是要携带的数据,数据与数据之间以 &
隔开,每个数据都是一个键值对,键名就是参数名,键值就是 =
后面的数值。
Header的放置规范如下:
参数名:参数值
也是键值对的形式。
那么 body 的呢?body由于主要放是业务数据,甚至是网站代码,body里面的数据格式很灵活。
所以首先要在 Header 中放置一个键值对:
Content-Type: 格式名称
Content-Type
表示 body 里面的格式是什么格式的,比如文本格式,比如图片格式,比如json格式等等。
目前,由于JSON格式的易读性和比较简洁,综合下来是大部分情况下的最佳选项,所以前端后端的交互,在 body 层面就是 以JSON格式 进行交互。
后端的对象是如何转换成JSON格式字符串的
先来看个例子:
@RestController
@RequestMapping("/web")
public class TestController {
@GetMapping("/jsonstr")
public Home getHome() {
return new Home("家庭", "湖边");
}
}
这段代码的请求结果是:
我们的后端对象返回给前端的实际上就是一段文本信息,格式是JSON格式。那你奇怪吗?为什么 Home
对象就能变成JSON格式的字符串输出,这是谁处理的呢?
答案是 springMVC
,这个框架帮助我们处理了将对象装换成JSON格式字符串的工作。在真正调用我们的 getHome()
方法时,我们的整个框架栈进行了许多的其他处理;在我们的 getHome()
方法返回时,我们的框架栈同样做了很多其他的处理。
又由于后端返回给前端信息,基本上都是从 HTTP的 body 中以 JSON字符串的形式返回的。所以 JSON 格式的理解非常重要,同样的,对象如何转成JSON字符串也要大致理解下。
后端对象转JSON字符串简要例程
为了有一个直观的转换感受,这里给出一个简要的历程
/**
* 将对象转换成JSON字符串的处理类
*/
public class JsonMapper {
public static void main(String[] args) {
JsonMapper mapper = new JsonMapper();
Home home = new Home("thing", "hangzhou");
String jsonStr = mapper.parseJson(home);
System.out.println(jsonStr);
People people = new People("男", "周");
String jsonStr2 = mapper.parseJson(people);
System.out.println(jsonStr2);
}
/**
* 将传入的对象中的具有 getter方法的属性及其值转变为 JSON 字符串进行输出
* 简单处理,默认所有成员都具有 getter方法。
* @param obj 传入的对象
* @return JSON字符串
*/
public String parseJson(Object obj) {
StringBuilder builder = new StringBuilder("{");
BeanProperty[] properties = getBeanProperty(obj);
// 构造JSON字符串
for (BeanProperty property : properties) {
builder.append(""").append(property.getName()).append("":"");
try {
builder.append(property.getGetter().invoke(obj).toString()).append("",");
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
builder = builder.replace(builder.length() - 1, builder.length(), "}");
return builder.toString();
}
/**
* 将对象转换成 BeanProperty 数组
* 每个 BeanProperty 都包含了对象中的一个属性的名字和其对应的getter方法
* @param obj 对象
* @return BeanProperty[] 数组
*/
private BeanProperty[] getBeanProperty(Object obj) {
Class c = obj.getClass();
// 获取对象中的成员属性
Field[] fields = c.getDeclaredFields();
BeanProperty[] beanProperties = new BeanProperty[fields.length];
// 获取对象本身包含的方法
Method[] methods = c.getDeclaredMethods();
// 遍历成员,根据成员信息获取对应的getter方法;
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
for (Method method : methods) {
if (method.getName().toLowerCase().equals("get" + field.getName().toLowerCase())) {
BeanProperty beanProperty = new BeanProperty(field.getName(), method);
beanProperties[i] = beanProperty;
break;
}
}
}
return beanProperties;
}
/**
* 对象中的属性类
* 包含每个属性的名称,每个属性对应的 getter 方法
*/
private class BeanProperty {
private String name;
private Method getter;
BeanProperty(String name, Method getter) {
this.name = name;
this.getter = getter;
}
String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
Method getGetter() {
return getter;
}
void setGetter(Method getter) {
this.getter = getter;
}
}
}
运行结果为:
{“name”:“thing”,“address”:“hangzhou”}
{“sex”:“男”,“name”:“周”}
其中,Home 类为:
public class Home {
private String name;
private String address;
public Home() {
}
public Home(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
可以看出,转换的规则其实很简单:
将成员变量名当成 JSON 的 键名,将getter方法获取到的值当作 键 对应的数值。
springMVC的转换,也就是最上面第一段程序的例子,其有几个特殊点。感兴趣的话可以试试将 Home 改成如下的代码,再看看 /web/jsonstr 的返回值是什么样子的。也可以简单理解,不尝试。
public class Home {
private String name;
private String address;
private String lon;
public String ele = "0.01";
private static String staticStr = "static";
public Home() {
}
public Home(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getLat() {
return "lat";
}
public String getStaticStr() {
return staticStr;
}
public static String getStaticString() {
return "static1";
}
public static String getStatics() {
return "ssss";
}
}
后端接收前端数据的三个空间
三个空间分别是文章开头说的 url, header, body。
这里我们使用 postman 来作为HTTP客户端,去请求我们的程序API。(关于postman的使用可以自行搜索)。
程序如下:
@RestController
@RequestMapping("/web")
public class TestController {
@GetMapping("/jsonstr")
public Home getHome() {
return new Home("家庭", "湖边");
}
@PostMapping("/param")
public void url(String u, @RequestHeader String h, @RequestBody Home home) {
System.out.println(u);
System.out.println(h);
System.out.println(home.getName() + "..." + home.getAddress());
}
}
其中, u 表示 参数携带在 url 里面(url 中的 ?
后边的参数);加了 @RequestHeader
字段的参数是请求头传参;加了 @RequestBody
的参数是 body 传参;
其中,Body传参相当于把 JSON字符串转换成 java 对象,其实原理也类似。
postman请求如下:(Header 参数没截出来)
程序运行结果是:
this is url
this is header
this is home name...this is home address
现在,前后端如何交互已经说清楚了,但是前端还有一个额外的地方可以传递参数:
我们的后端URL组成可以是 /web/param/{id}
,这个括号括住的 id 就是第四个可以携带参数的地方,那么代码具体怎么体现呢?
可以自行搜索 路径传参 或者 @PathVariable
注解来试试看。
理解了前后端如何交互后,下一节需要了解前后端交互的常见规范,也就是 restful
规范。接着就可以开始学习如何操作数据库,如何编写和数据库交互的后端应用了。
最后
以上就是感动小鸭子为你收集整理的java后端开发(五):前端如何理解后端的对象信息的全部内容,希望文章能够帮你解决java后端开发(五):前端如何理解后端的对象信息所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复