1.拦截器执行流程
1.准备一个拦截器
2.在准备的html中输入账号密码并提交请求。
我们知道在DispatcherServlet中,
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
是真正执行方法的语句,所以拦截器的pre方法必须在此之前执行。
通过观察源码的方法命名我们不难猜测出applyPreHandle就是执行拦截器pre方法的语句。
进入该方法
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
return true;
}
首先通过遍历,从头到尾遍历获取所有的拦截器,然后执行preHandle方法。若返回false,则直接执行AfterCompletion方法。若为true则继续遍历。直到所有拦截器都执行完毕,或者某个拦截器返回false,执行afterCompletion方法。
继续走流程
再执行完handle方法获取了ModelAndView对象后,开始执行postHandler方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
进入该方法
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
for(int i = this.interceptorList.size() - 1; i >= 0; --i) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
它与preHandler的执行类似,也是先遍历所有的拦截器,再分别执行每个拦截器postHandler方法。与preHandler的执行不同的是,他是从大到小遍历拦截器,也就是说先从最后一个拦截器开始执行。当遇到异常时,直接抛出。在DispatcherServlet中处理。
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
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));
}
可以看到处理的方式也是直接执行每个拦截器的afterCompletion方法。
我们假设无异常抛出,程序继续运行。
在获得了ModelAndView对象并执行完postHandler方法后,开始渲染视图。视图渲染结束后该执行拦截器的afterCompletion方法了
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var7) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var7);
}
}
}
afterCompletion的执行是从尾到头开始执行,首先获取拦截器的索引,索引的初始化值为-1,当我们遍历执行preHandler方法是,索引会随着遍历而递增,它始终比拦截器个数少一。所以当我们第一个拦截器在preHandler阶段就为false时,此时索引为-1,会直接结束该方法。若为正数,则反向执行afterCompletion方法。
正常执行的流程图。
当某个拦截器的preHandler方法返回false时:
2.Linux常用指令
启动某服务:/bin/ststemctl start 服务名
查看进程树:pstree
-p 显示进程号
-u 显示用户信息
服务管理相关指令:service 服务名 【start|stop|restart|reload|status】
setup 查看所有命令 带*为自启动应用
chkconfig
1.给服务的各个运行级别设置自启动/关闭
基本语法
查看: chkconfig --list | grep xxx
chkconfig 服务名 --list
设置在指定级别下的自启动/关闭: chkconfig --level5 服务名 on/off
systemctl管理指令
在/usr/lib/systemd/system中查看systemctl管理的指令
systemctl list-unit-files查看莫格服务的开机启动状态。
systemctl is-enable 服务名 查看某服务是否开机自启
systemctl enable 服务名 设置某服务开机自启动
systemctl disable 服务名 关闭某服务开机自启动
systemctl status 服务名 查看某服务状况
systemctl star/stop 服务名(临时生效,重启后回归默认设置)
打开或关闭指定端口:
打开:
firewall-cmd --permanent --add-port=端口号/协议
关闭:
firewall-cmd --permanent --remove-port=端口号协议
重新载入使其生效:firewall-cmd--reload
查询是否开放:firewall-cm --query-port=端口号/协议
netstat -anp 查看端口