java架构师面试题及答案大全,阿昌教你看懂SpringMVC执行流程,建议细读


8、handle

ha.handle(processedRequest, response, mappedHandler.getHandler());

这里是真正执行我们这次请求处理的controller对应的方法

在这里插入图片描述

那阿昌这里就好奇了,他是如何执行,并拿到对应的结果的,这个结果封装在哪里???

  • handleInternal()

在这里插入图片描述

  • invokeHandlerMethod()

在这里插入图片描述

  • invokeAndHandle()

在这里插入图片描述

  • invokeForRequest

@Nullable

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object… providedArgs) throws Exception {

//获取这次请求的参数

Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);

if (logger.isTraceEnabled()) {

logger.trace("Arguments: " + Arrays.toString(args));

}

//执行对应的controller方法

return doInvoke(args);

}

在这里插入图片描述

  • doInvoke

这里就是controller的代理了,对应的代理设计模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3QukQUNv-1639907575817)(../AppData/Roaming/Typora/typora-user-images/image-20211219165433034.png)]

  • invoke

在这里插入图片描述

那上面拿到执行了controller的方法后,拿到的结果是如何处理的呢?

在这里插入图片描述

  • handleReturnValue

在这里插入图片描述

  • writeWithMessageConverters

将处理响应的结果,写入响应中,这个方法很长,对应与servletHttp响应的介绍

protected void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,

ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)

throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

Object body;

Class<?> valueType;

Type targetType;

if (value instanceof CharSequence) {

body = value.toString();

valueType = String.class;

targetType = String.class;

}

else {

body = value;

valueType = getReturnValueType(body, returnType);

targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass());

}

if (isResourceType(value, returnType)) {

outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, “bytes”);

if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null &&

outputMessage.getServletResponse().getStatus() == 200) {

Resource resource = (Resource) value;

try {

List httpRanges = inputMessage.getHeaders().getRange();

outputMessage.getServletResponse().setStatus(HttpStatus.PARTIAL_CONTENT.value());

body = HttpRange.toResourceRegions(httpRanges, resource);

valueType = body.getClass();

targetType = RESOURCE_REGION_LIST_TYPE;

}

catch (IllegalArgumentException ex) {

outputMessage.getHeaders().set(HttpHeaders.CONTENT_RANGE, “bytes */” + resource.contentLength());

outputMessage.getServletResponse().setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());

}

}

}

MediaType selectedMediaType = null;

MediaType contentType = outputMessage.getHeaders().getContentType();

boolean isContentTypePreset = contentType != null && contentType.isConcrete();

if (isContentTypePreset) {

if (logger.isDebugEnabled()) {

logger.debug(“Found 'Content-Type:” + contentType + “’ in response”);

}

selectedMediaType = contentType;

}

else {

HttpServletRequest request = inputMessage.getServletRequest();

List acceptableTypes = getAcceptableMediaTypes(request);

List producibleTypes = getProducibleMediaTypes(request, valueType, targetType);

if (body != null && producibleTypes.isEmpty()) {

throw new HttpMessageNotWritableException(

"No converter found for return value of type: " + valueType);

}

List mediaTypesToUse = new ArrayList<>();

for (MediaType requestedType : acceptableTypes) {

for (MediaType producibleType : producibleTypes) {

if (requestedType.isCompatibleWith(producibleType)) {

mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));

}

}

}

if (mediaTypesToUse.isEmpty()) {

if (body != null) {

throw new HttpMediaTypeNotAcceptableException(producibleTypes);

}

if (logger.isDebugEnabled()) {

logger.debug("No match for " + acceptableTypes + ", supported: " + producibleTypes);

}

return;

}

MediaType.sortBySpecificityAndQuality(mediaTypesToUse);

for (MediaType mediaType : mediaTypesToUse) {

if (mediaType.isConcrete()) {

selectedMediaType = mediaType;

break;

}

else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {

selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;

break;

}

}

if (logger.isDebugEnabled()) {

logger.debug(“Using '” + selectedMediaType + "', given " +

acceptableTypes + " and supported " + producibleTypes);

}

}

if (selectedMediaType != null) {

selectedMediaType = selectedMediaType.removeQualityValue();

for (HttpMessageConverter<?> converter : this.messageConverters) {

GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?

(GenericHttpMessageConverter<?>) converter : null);

if (genericConverter != null ?

((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :

converter.canWrite(valueType, selectedMediaType)) {

body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,

(Class<? extends HttpMessageConverter<?>>) converter.getClass(),

inputMessage, outputMessage);

if (body != null) {

Object theBody = body;

LogFormatUtils.traceDebug(logger, traceOn ->

“Writing [” + LogFormatUtils.formatValue(theBody, !traceOn) + “]”);

addContentDispositionHeader(inputMessage, outputMessage);

if (genericConverter != null) {

genericConverter.write(body, targetType, selectedMediaType, outputMessage);

}

else {

((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);

}

}

else {

if (logger.isDebugEnabled()) {

logger.debug(“Nothing to write: null body”);

}

}

return;

}

}

}

if (body != null) {

Set producibleMediaTypes =

(Set) inputMessage.getServletRequest()

.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);

if (isContentTypePreset || !CollectionUtils.isEmpty(producibleMediaTypes)) {

throw new HttpMessageNotWritableException(

“No converter for [” + valueType + “] with preset Content-Type '” + contentType + “'”);

}

throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);

}

}

重要的部分在:

  • body:controller处理的结果

在这里插入图片描述

  • outputMessage:上面封装的webRequest中拿到的响应输出

在这里插入图片描述

//将通过converter将内容body写入outputMessage

((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);

在这里插入图片描述


  • write()

t:就是我们的结果“我是结果”

@Override

public final void write(final T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)

throws IOException, HttpMessageNotWritableException {

final HttpHeaders headers = outputMessage.getHeaders();

addDefaultHeaders(headers, t, contentType);

if (outputMessage instanceof StreamingHttpOutputMessage) {

StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;

streamingOutputMessage.setBody(outputStream -> writeInternal(t, new HttpOutputMessage() {

@Override

public OutputStream getBody() {

return outputStream;

}

@Override

public HttpHeaders getHeaders() {

return headers;

}

}));

}

else {

//将t写入到outputMessage

writeInternal(t, outputMessage);

//flush刷新响应body

outputMessage.getBody().flush();

}

}

他是如何写入outputMessage的呢?

  • writeInternal

将t写入到outputMessage

在这里插入图片描述

  • copy

就直接通过OutputStreamWriter直接调用write写入in也就是结果,最后flush刷新

在这里插入图片描述

执行完写入响应结果后,他就会提交这次响应,什么是 提交响应呢?介绍:响应提交

在这里插入图片描述


9、小总结

  • 上面我们拿到对应的HandlerExecutionChain拦截器链

这里包含:↓

  • 处理器handlermapping

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

Spring全套教学资料

Spring是Java程序员的《葵花宝典》,其中提供的各种大招,能简化我们的开发,大大提升开发效率!目前99%的公司使用了Spring,大家可以去各大招聘网站看一下,Spring算是必备技能,所以一定要掌握。

目录:

部分内容:

Spring源码

  • 第一部分 Spring 概述
  • 第二部分 核心思想
  • 第三部分 手写实现 IoC 和 AOP(自定义Spring框架)
  • 第四部分 Spring IOC 高级应用
    基础特性
    高级特性
  • 第五部分 Spring IOC源码深度剖析
    设计优雅
    设计模式
    注意:原则、方法和技巧
  • 第六部分 Spring AOP 应用
    声明事务控制
  • 第七部分 Spring AOP源码深度剖析
    必要的笔记、必要的图、通俗易懂的语言化解知识难点

脚手框架:SpringBoot技术

它的目标是简化Spring应用和服务的创建、开发与部署,简化了配置文件,使用嵌入式web服务器,含有诸多开箱即用的微服务功能,可以和spring cloud联合部署。

Spring Boot的核心思想是约定大于配置,应用只需要很少的配置即可,简化了应用开发模式。

  • SpringBoot入门
  • 配置文件
  • 日志
  • Web开发
  • Docker
  • SpringBoot与数据访问
  • 启动配置原理
  • 自定义starter

微服务架构:Spring Cloud Alibaba

同 Spring Cloud 一样,Spring Cloud Alibaba 也是一套微服务解决方案,包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

  • 微服务架构介绍
  • Spring Cloud Alibaba介绍
  • 微服务环境搭建
  • 服务治理
  • 服务容错
  • 服务网关
  • 链路追踪
  • ZipKin集成及数据持久化
  • 消息驱动
  • 短信服务
  • Nacos Confifig—服务配置
  • Seata—分布式事务
  • Dubbo—rpc通信

Spring MVC

目录:

部分内容:

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

a—分布式事务

  • Dubbo—rpc通信

[外链图片转存中…(img-4diiTfWx-1712426094558)]

[外链图片转存中…(img-vxwvvJjl-1712426094559)]

Spring MVC

目录:

[外链图片转存中…(img-QWt7zf0K-1712426094559)]

[外链图片转存中…(img-dqVnZ5Z7-1712426094560)]

[外链图片转存中…(img-3OnceT8M-1712426094560)]

部分内容:

[外链图片转存中…(img-LL6qnd1v-1712426094560)]

[外链图片转存中…(img-SNg47Abm-1712426094561)]

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

书籍1:互联网 Java 工程师面试题 内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、 Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、 Linux 等技术栈 1、MyBatis 面试题 1、什么是 Mybatis 2、Mybaits 的优点 3、MyBatis 框架的缺点 4、MyBatis 框架适用场合 5、MyBatis 与 Hibernate 有哪些不同? 6、#{}和${}的区别是什么? 7、当实体类中的属性名和表中的字段名不一样 ,怎么办 ? 8、 模糊查询 like 语句该怎么写? 9、通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应,请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗? 10、Mybatis 是如何进行分页的?分页插件的原理是什么? 11、Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式? 12、如何执行批量插入? 13、如何获取自动生成的(主)键值? 14、在 mapper 中如何传递多个参数? 15、Mybatis 动态 sql 有什么用?执行原理?有哪些动态 sql? 16、Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签? 18、为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里? 19、 一对一、一对多的关联查询 ? 20、MyBatis 实现一对一有几种方式?具体怎么操作的? 21、MyBatis 实现一对多有几种方式,怎么操作的? 22、Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么? 23、Mybatis 的一级、二级缓存 24、什么是 MyBatis 的接口绑定?有哪些实现方式? 25、使用 MyBatis 的 mapper 接口调用时有哪些要求? 26、Mapper 编写有哪几种方式? 27、简述 Mybatis 的插件运行原理,以及如何编写一个插件 等等 书籍2:JAVA核心知识整理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值