IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 响应处理-前后端数据交互、内容协商 -> 正文阅读

[Java知识库]响应处理-前后端数据交互、内容协商

目录

数据交互浅析:

内容协商:


数据交互浅析:

众所周知,前后端分离项目的前端我们是利用Jquery实现ajax异步请求与后端进行数据交互:意思就是从前端页面中取出数据,请求到对应的controller层方法上,然后后端对前端请求的数据进行业务逻辑处理,最后将对应的状态返回给前端;

HTTPMessageConverter原理:

将你项目中的实体类数据转为JSON数据或者倒转,利用读写方法;

设计restful风格的API,通过json数据进行前后端交互:数据如何解析的?SpringMVC中启动时会自动配置一些HttpMessageConverter,那么什么作用呢?能够支持json数据类型,当后端接收到请求时会判断是否能读,能读则读,返回结果时判断是否能写,能写则写;

public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> var1, @Nullable MediaType var2);

    boolean canWrite(Class<?> var1, @Nullable MediaType var2);

    List<MediaType> getSupportedMediaTypes();

    T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;

    void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}

1、那么问题来了读归读写归写,但是你的数据得转换,那么转换数据是不是得需要Converter,那么在WebMvcConfigurationSupport类中,里面有一个非常关键的方法:addDefaultHttpMessageConverters();

protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
		StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
		stringConverter.setWriteAcceptCharset(false);

		messageConverters.add(new ByteArrayHttpMessageConverter());
		messageConverters.add(stringConverter);
		messageConverters.add(new ResourceHttpMessageConverter());
		messageConverters.add(new SourceHttpMessageConverter<Source>());
		messageConverters.add(new AllEncompassingFormHttpMessageConverter());

		if (romePresent) {
			messageConverters.add(new AtomFeedHttpMessageConverter());
			messageConverters.add(new RssChannelHttpMessageConverter());
		}

		if (jackson2XmlPresent) {
			ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.xml().applicationContext(this.applicationContext).build();
			messageConverters.add(new MappingJackson2XmlHttpMessageConverter(objectMapper));
		}
		else if (jaxb2Present) {
			messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
		}

		if (jackson2Present) {
			ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().applicationContext(this.applicationContext).build();
			messageConverters.add(new MappingJackson2HttpMessageConverter(objectMapper));
		}
		else if (gsonPresent) {
			messageConverters.add(new GsonHttpMessageConverter());
		}
	}

由上述可以知道这是用来判断的,找到数据需要的Converter转换器,如果需要的话,就添加到messageConverter中;这里需要注意当我们配置了自己的MessageConverter时(专门储存Converter的地方),addDefaultHttpMessageConverters()方法就不会被SpringMVC调用;

2、getMessageConverter():用来判断converters转换器是用自定义的还是springMVC默认配置的(这里有点迷,isEmpty是判断转换器中的内容吗?):我的理解是:如果转换器为空(意思就是没东西取了),我们就new一个集合(转换器的),然后配置当前的转换器,(这里应该是我们某个数据需要某个转换器时,如果这个转换器没有,就new一个转换器集合,并配置一个对应这种数据的转换器,将数据转换)——也就是自己的转换器;然后后面判断转换器中内容是否为空,若为空,springMVC就会加载addDefaultHttpMessageConverters(),去获取属性对应的转换器;

protected final List<HttpMessageConverter<?>> getMessageConverters() {
		if (this.messageConverters == null) {
			this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
			configureMessageConverters(this.messageConverters);
			if (this.messageConverters.isEmpty()) {
				addDefaultHttpMessageConverters(this.messageConverters);
			}
			extendMessageConverters(this.messageConverters);
		}
		return this.messageConverters;
	}

3、对于MessageConverters的处理:

遍历的每一个converter去比较,直至找到Jackson的处理类型;

// 遍历 messageConverters
for (HttpMessageConverter<?> converter : this.messageConverters) {
    Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
        // 上文类关系图处要重点记住的地方,主要判断 MappingJackson2HttpMessageConverter 是否是 GenericHttpMessageConverter 类型
    if (converter instanceof GenericHttpMessageConverter) {
        GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
        if (genericConverter.canRead(targetType, contextClass, contentType)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
            }
            if (inputMessage.getBody() != null) {
                inputMessage = getAdvice().beforeBodyRead(inputMessage, parameter, targetType, converterType);
                body = genericConverter.read(targetType, contextClass, inputMessage);
                body = getAdvice().afterBodyRead(body, inputMessage, parameter, targetType, converterType);
            }
            else {
                body = getAdvice().handleEmptyBody(null, inputMessage, parameter, targetType, converterType);
            }
            break;
        }
    }
    else if (targetClass != null) {
        if (converter.canRead(targetClass, contentType)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
            }
            if (inputMessage.getBody() != null) {
                inputMessage = getAdvice().beforeBodyRead(inputMessage, parameter, targetType, converterType);
                body = ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage);
                body = getAdvice().afterBodyRead(body, inputMessage, parameter, targetType, converterType);
            }
            else {
                body = getAdvice().handleEmptyBody(null, inputMessage, parameter, targetType, converterType);
            }
            break;
        }
    }
}

4、然后判断读取操作:能读就读,

protected Object _readMapAndClose(JsonParser p0, JavaType valueType)
        throws IOException
    {
        try (JsonParser p = p0) {
            Object result;
            JsonToken t = _initForReading(p);
            if (t == JsonToken.VALUE_NULL) {
                // Ask JsonDeserializer what 'null value' to use:
                DeserializationContext ctxt = createDeserializationContext(p,
                        getDeserializationConfig());
                result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt);
            } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
                result = null;
            } else {
                DeserializationConfig cfg = getDeserializationConfig();
                DeserializationContext ctxt = createDeserializationContext(p, cfg);
                JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
                if (cfg.useRootWrapping()) {
                    result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
                } else {
                    result = deser.deserialize(p, ctxt);
                }
                ctxt.checkUnresolvedObjectId();
            }
            // Need to consume the token too
            p.clearCurrentToken();
            return result;
        }
    }

此时,解析已经全部完成,那么还有后端的结果(也就是返回给前端的状态)的过程没有完成;

内容协商:

首先,什么是内容协商?

其实就和之前讲前后端数据交互一样的,这里往上面的接;针对标注了@ResponseBody注解处理的方法,我们的服务器会根据客户端的需要来返回不同格式的数据,比如json、xml...

原理:

1.当浏览器发送请求时,请求头(Request Headers)会携带accept信息:(eg:img/webp,img/*等等)

2.然后springboot就会对controller下的方法进行返回数据类型的处理,那么问题来了,怎么样处理的呢?上面就已经说过了,是通过messageConverter消息转换器进行处理的,messageConverter有默认的所有converter,springboot启动时它就会被加载,从getMessageConveter()可以知道优先自定义的messageConverter,如果有的话就进行读写操作;然后数据类型转换之后,springboot会统计所有转换类型格式;

在这里插入图片描述

?

3.上述两步可以理解我们获取了两种类型,一种客户端的,一种服务器响应的,然后我们进行嵌套遍历一下,就可以得到二者兼容的类型;

在这里插入图片描述

?

总的来说:

内容协商就是客户端发送请求我们要哪种格式的数据,同时服务器对自己本身多种响应的格式进行兼容处理,然后根据要求返回对应格式;

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:27:55  更:2022-02-01 20:28:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:25:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码