如果早知道SpringMVC可以这样学,我也不至于被面试官虐的这么惨(1)

总结

这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!

某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!

成功只会留给那些有准备的人!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

logger.debug(“No HandlerAdapters found in servlet '” + getServletName() + “': using default”);

}

}

}

请求处理

====

流程图

===

如果早知道SpringMVC可以这样学,我也不至于被面试官虐的这么惨

doDispatch方法解析

==============

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

HttpServletRequest processedRequest = request;

HandlerExecutionChain mappedHandler = null;

boolean multipartRequestParsed = false;

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {

try {

ModelAndView mv = null;

Object dispatchException = null;

try {

processedRequest = this.checkMultipart(request);

multipartRequestParsed = processedRequest != request;

// 2.获取处理器映射器

mappedHandler = this.getHandler(processedRequest);

if (mappedHandler == null) {

// 获取不到handler 抛异常或者返回404

this.noHandlerFound(processedRequest, response);

return;

}

// 4.获取处理器适配器器

HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

String method = request.getMethod();

boolean isGet = “GET”.equals(method);

if (isGet || “HEAD”.equals(method)) {

long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {

return;

}

}

// 6.循环调用拦截器的preHandle方法

if (!mappedHandler.applyPreHandle(processedRequest, response)) {

return;

}

// 8.实际执行代码,handler通过反射执行控制器方法

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

if (asyncManager.isConcurrentHandlingStarted()) {

return;

}

// 默认视图

this.applyDefaultViewName(processedRequest, mv);

// 10.循环调用拦截的postHandle

mappedHandler.applyPostHandle(processedRequest, response, mv);

} catch (Exception var20) {

dispatchException = var20;

} catch (Throwable var21) {

dispatchException = new NestedServletException(“Handler dispatch failed”, var21);

}

// 11.处理结果,进行视图解析 & 模板引擎渲染 & request域填充

// 12.内部会调用拦截器的afterCompletion方法

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

} catch (Exception var22) {

// 目标方法完成之后执行

this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);

} catch (Throwable var23) {

// 目标方法完成之后执行

this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException(“Handler processing failed”, var23));

}

} finally {

if (asyncManager.isConcurrentHandlingStarted()) {

if (mappedHandler != null) {

mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);

}

} else if (multipartRequestParsed) {

this.cleanupMultipart(processedRequest);

}

}

}

获取处理器映射器

========

@Nullable

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

if (this.handlerMappings != null) {

Iterator var2 = this.handlerMappings.iterator();

while(var2.hasNext()) {

HandlerMapping mapping = (HandlerMapping)var2.next();

// 核心方法获取执行链

HandlerExecutionChain handler = mapping.getHandler(request);

if (handler != null) {

return handler;

}

}

}

return null;

}

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

// 获取handler

Object handler = this.getHandlerInternal(request);

if (handler == null) {

handler = this.getDefaultHandler();

}

if (handler == null) {

// 不满足,返回

return null;

} else {

if (handler instanceof String) {

String handlerName = (String)handler;

handler = this.obtainApplicationContext().getBean(handlerName);

}

// 以handler为参数获取执行链:创建一个执行链对象,handler赋值到内部变量,添加所有拦截器

HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);

return executionChain;

}

}

获取处理器适配器

========

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {

if (this.handlerAdapters != null) {

Iterator var2 = this.handlerAdapters.iterator();

while(var2.hasNext()) {

HandlerAdapter adapter = (HandlerAdapter)var2.next();

// 核心判断方法,找到支持该handler的适配器

if (adapter.supports(handler)) {

return adapter;

}

}

}

throw new ServletException(“No adapter for handler [” + handler +

“]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler”);

}

执行拦截器前置处理preHandle方法

====================

HandlerExecutionChain#applyPreHandle

  • 拦截器的preHandle方法任意一个返回false则访问不到目标方法

  • 拦截器的afterCompletion方法一定会执行

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {

HandlerInterceptor[] interceptors = this.getInterceptors();

if (!ObjectUtils.isEmpty(interceptors)) {

for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {

HandlerInterceptor interceptor = interceptors[i];

// 循环调用

if (!interceptor.preHandle(request, response, this.handler)) {

// 执行完毕拦截器的所有AfterCompletio方法后return

this.triggerAfterCompletion(request, response, (Exception)null);

// 一个返回false即停止循环

return false;

}

}

}

return true;

}

执行控制器的目标方法

==========

如果早知道SpringMVC可以这样学,我也不至于被面试官虐的这么惨

InvocableHandlerMethod#doInvoke

@Nullable

protected Object doInvoke(Object… args) throws Exception {

ReflectionUtils.makeAccessible(this.getBridgedMethod());

try {

// method.invoke(obj,args);

// 反射调用目标类的目标方法

// 目标方法:this.getBridgedMethod()

// this.getBean()获取handler中的bean,即为容器中的目标类实例/可能是一个CGLIB增强后的代理对象

return this.getBridgedMethod().invoke(this.getBean(), args);

} catch (IllegalArgumentException var4) {

this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args);

String text = var4.getMessage() != null ? var4.getMessage() : “Illegal argument”;

throw new IllegalStateException(this.formatInvokeError(text, args), var4);

} catch (InvocationTargetException var5) {

Throwable targetException = var5.getTargetException();

if (targetException instanceof RuntimeException) {

throw (RuntimeException)targetException;

} else if (targetException instanceof Error) {

throw (Error)targetException;

} else if (targetException instanceof Exception) {

throw (Exception)targetException;

} else {

throw new IllegalStateException(this.formatInvokeError(“Invocation failure”, args), targetException);

}

}

}

处理返回结果 & 执行拦截器afterCompletion方法

===============================

DispatcherServlet#processDispatchResult

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {

boolean errorView = false;

if (exception != null) {

if (exception instanceof ModelAndViewDefiningException) {

this.logger.debug(“ModelAndViewDefiningException encountered”, exception);

mv = ((ModelAndViewDefiningException)exception).getModelAndView();

} else {

Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;

mv = this.processHandlerException(request, response, handler, exception);

errorView = mv != null;

}

}

if (mv != null && !mv.wasCleared()) {

// a.视图解析 & 模板引擎渲染

this.render(mv, request, response);

if (errorView) {

WebUtils.clearErrorRequestAttributes(request);

}

} else if (this.logger.isTraceEnabled()) {

this.logger.trace(“No view rendering, null ModelAndView returned.”);

}

if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

if (mappedHandler != null) {

// b.调用拦截器afterCompletion方法

mappedHandler.triggerAfterCompletion(request, response, (Exception)null);

}

}

}

a.视图解析 & 模板引擎渲染

===============

DispatcherServlet#render

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {

Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();

response.setLocale(locale);

String viewName = mv.getViewName();

View view;

if (viewName != null) {

// 视图解析

view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);

if (view == null) {

throw new ServletException(“Could not resolve view with name '” + mv.getViewName() + “’ in servlet with name '” + this.getServletName() + “'”);

}

} else {

view = mv.getView();

if (view == null) {

throw new ServletException(“ModelAndView [” + mv + “] neither contains a view name nor a View object in servlet with name '” + this.getServletName() + “'”);

}

}

if (this.logger.isTraceEnabled()) {

this.logger.trace(“Rendering view [” + view + "] ");

}

try {

if (mv.getStatus() != null) {

response.setStatus(mv.getStatus().value());

}

// 模板引擎渲染

view.render(mv.getModelInternal(), request, response);

} catch (Exception var8) {

if (this.logger.isDebugEnabled()) {

this.logger.debug(“Error rendering view [” + view + “]”, var8);

}

throw var8;

}

}

b.调用拦截器afterCompletion方法,一定会执行

==============================

HandlerExecutionChain#afterCompletion

public void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {

HandlerInterceptor[] interceptors = this.getInterceptors();

if (!ObjectUtils.isEmpty(interceptors)) {

最后如何让自己一步步成为技术专家

说句实话,如果一个打工人不想提升自己,那便没有工作的意义,毕竟大家也没有到养老的年龄。

当你的技术在一步步贴近阿里p7水平的时候,毫无疑问你的薪资肯定会涨,同时你能学到更多更深的技术,交结到更厉害的大牛。

推荐一份Java架构之路必备的学习笔记,内容相当全面!!!

成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。

你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!

进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!

【关注】+【转发】+【点赞】支持我!创作不易!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

最后如何让自己一步步成为技术专家

说句实话,如果一个打工人不想提升自己,那便没有工作的意义,毕竟大家也没有到养老的年龄。

当你的技术在一步步贴近阿里p7水平的时候,毫无疑问你的薪资肯定会涨,同时你能学到更多更深的技术,交结到更厉害的大牛。

推荐一份Java架构之路必备的学习笔记,内容相当全面!!!

[外链图片转存中…(img-Z3lm2zAa-1715533061263)]

成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。

你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!

进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!

【关注】+【转发】+【点赞】支持我!创作不易!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值