十九,2024年最新java面试jvm常见面试题

zuulRunner.postRoute();

}

/**

  • executes “route” filters

  • @throws ZuulException

*/

//调用zuulRunner执行 route filter

void route() throws ZuulException {

zuulRunner.route();

}

/**

  • executes “pre” filters

  • @throws ZuulException

*/

//调用zuulRunner执行 pre filter

void preRoute() throws ZuulException {

zuulRunner.preRoute();

}

/**

  • initializes request

  • @param servletRequest

  • @param servletResponse

*/

//调用zuulRunner执行 初始化 ,主要是把servletRequest设置给ReqestContext上下文对象

void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {

zuulRunner.init(servletRequest, servletResponse);

}

/**

  • sets error context info and executes “error” filters

  • @param e

*/

//通过RequestContext设置异常

//通过zuulRunner执行 error filter

void error(ZuulException e) {

RequestContext.getCurrentContext().setThrowable(e);

zuulRunner.error();

}

3.ZuulRunner 执行器

上面涉及到一个非常重要的类ZuulRunner所有的请求都是通过它来执行的,此类将Servlet请求和响应初始化到RequestContext中,并将FilterProcessor调用包装为preRoute(),route(),postRoute()和error()方法 ,我们看一下ZuulRunner的源码

/**

  • This class initializes servlet requests and responses into the RequestContext and wraps the FilterProcessor calls

  • to preRoute(), route(), postRoute(), and error() methods

  • @author mikey@netflix.com

  • @version 1.0

*/

public class ZuulRunner {

private boolean bufferRequests;

/**

  • Creates a new ZuulRunner instance.

*/

public ZuulRunner() {

this.bufferRequests = true;

}

/**

  • @param bufferRequests - whether to wrap the ServletRequest in HttpServletRequestWrapper and buffer the body.

在ZuulServlet中创建ZuulRunner的时候传入的配置参数 bufferRequests,

它决定了是否把 ServletRequest包装在HttpServletRequestWrapper中并缓冲主体。

*/

public ZuulRunner(boolean bufferRequests) {

this.bufferRequests = bufferRequests;

}

/**

  • sets HttpServlet request and HttpResponse

设置 请求对象和响应对象到 RequestContext 中

  • @param servletRequest

  • @param servletResponse

*/

public void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {

RequestContext ctx = RequestContext.getCurrentContext();

if (bufferRequests) {

//把 ServletRequest包装在HttpServletRequestWrapper中并缓冲主体。

ctx.setRequest(new HttpServletRequestWrapper(servletRequest));

} else {

ctx.setRequest(servletRequest);

}

ctx.setResponse(new HttpServletResponseWrapper(servletResponse));

}

//这里通过 FilterProcessor 执行器调用各种 ZuulFilters

/**

  • executes “post” filterType ZuulFilters

  • @throws ZuulException

*/

public void postRoute() throws ZuulException {

FilterProcessor.getInstance().postRoute();

}

/**

  • executes “route” filterType ZuulFilters

  • @throws ZuulException

*/

public void route() throws ZuulException {

FilterProcessor.getInstance().route();

}

/**

  • executes “pre” filterType ZuulFilters

  • @throws ZuulException

*/

public void preRoute() throws ZuulException {

FilterProcessor.getInstance().preRoute();

}

/**

  • executes “error” filterType ZuulFilters

*/

public void error() {

FilterProcessor.getInstance().error();

}

4.FilterProcessor filter执行器

继续跟踪一下 FilterProcessor的源码

public class FilterProcessor {

…省略代码…

/**

  • runs “post” filters which are called after “route” filters. ZuulExceptions from ZuulFilters are thrown.

  • Any other Throwables are caught and a ZuulException is thrown out with a 500 status code

  • @throws ZuulException

*/

public void postRoute() throws ZuulException {

try {

//执行 post 类型的filter

runFilters(“post”);

} catch (ZuulException e) {

throw e;

} catch (Throwable e) {

throw new ZuulException(e, 500, “UNCAUGHT_EXCEPTION_IN_POST_FILTER_” + e.getClass().getName());

}

}

/**

  • runs all “error” filters. These are called only if an exception occurs. Exceptions from this are swallowed and logged so as not to bubble up.

*/

public void error() {

try {

//执行 error 类型的filter

runFilters(“error”);

} catch (Throwable e) {

logger.error(e.getMessage(), e);

}

}

/**

  • Runs all “route” filters. These filters route calls to an origin.

  • @throws ZuulException if an exception occurs.

*/

public void route() throws ZuulException {

try {

//执行 post 类型的filter

runFilters(“post”);

} catch (ZuulException e) {

throw e;

} catch (Throwable e) {

throw new ZuulException(e, 500, “UNCAUGHT_EXCEPTION_IN_ROUTE_FILTER_” + e.getClass().getName());

}

}

/**

  • runs all “pre” filters. These filters are run before routing to the orgin.

  • @throws ZuulException

*/

public void preRoute() throws ZuulException {

try {

//执行 pre 类型的filter

runFilters(“pre”);

} catch (ZuulException e) {

throw e;

} catch (Throwable e) {

throw new ZuulException(e, 500, “UNCAUGHT_EXCEPTION_IN_PRE_FILTER_” + e.getClass().getName());

}

}

/**

  • runs all filters of the filterType sType/ Use this method within filters to run custom filters by type

  • @param sType the filterType.

  • @return

  • @throws Throwable throws up an arbitrary exception

*/

//执行Filter的核心方法,运行所有过滤器/在过滤器中使用此方法可按类型运行自定义过滤器

public Object runFilters(String sType) throws Throwable {

if (RequestContext.getCurrentContext().debugRouting()) {

Debug.addRoutingDebug(“Invoking {” + sType + “} type filters”);

}

boolean bResult = false;

//通过 FilterLoader 加载 filters

List list = FilterLoader.getInstance().getFiltersByType(sType);

if (list != null) {

for (int i = 0; i < list.size(); i++) {

ZuulFilter zuulFilter = list.get(i);

//拿到每个filter,调用 processZuulFilter 去执行

Object result = processZuulFilter(zuulFilter);

if (result != null && result instanceof Boolean) {

bResult |= ((Boolean) result);

}

}

}

//返回结果

return bResult;

}

/**

  • Processes an individual ZuulFilter. This method adds Debug information. Any uncaught Thowables are caught by this method and converted to a ZuulException with a 500 status code.

  • @param filter

  • @return the return value for that filter

  • @throws ZuulException

*/

//filter的执行方法

public Object processZuulFilter(ZuulFilter filter) throws ZuulException {

RequestContext ctx = RequestContext.getCurrentContext();

//获取时候开启:debug

boolean bDebug = ctx.debugRouting();

final String metricPrefix = “zuul.filter-”;

long execTime = 0;

String filterName = “”;

try {

long ltime = System.currentTimeMillis();

//filter的类名

filterName = filter.getClass().getSimpleName();

RequestContext copy = null;

Object o = null;

Throwable t = null;

if (bDebug) {

Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);

copy = ctx.copy();

}

//【重要】调用 ZuulFilter.runFilter方法真正执行Filter

ZuulFilterResult result = filter.runFilter();

//拿到响应状态

ExecutionStatus s = result.getStatus();

execTime = System.currentTimeMillis() - ltime;

switch (s) {

//执行失败

case FAILED:

t = result.getException();

//将过滤器名称和状态附加到当前请求的过滤器执行历史记录中

ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);

break;

//执行成功

case SUCCESS:

o = result.getResult();

ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);

if (bDebug) {

Debug.addRoutingDebug(“Filter {” + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + “ms”);

Debug.compareContextState(filterName, copy);

}

break;

default:

break;

}

if (t != null) throw t;

usageNotifier.notify(filter, s);

return o;

} catch (Throwable e) {

if (bDebug) {

Debug.addRoutingDebug(“Running Filter failed " + filterName + " type:” + filter.filterType() + " order:" + filter.filterOrder() + " " + e.getMessage());

}

usageNotifier.notify(filter, ExecutionStatus.FAILED);

if (e instanceof ZuulException) {

throw (ZuulException) e;

} else {

ZuulException ex = new ZuulException(e, “Filter threw Exception”, 500, filter.filterType() + “:” + filterName);

ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);

throw ex;

}

}

}

…省略代码…

不管是前置,后置,路由,异常的Filter ,FilterProcessor 都通过 runFilters("类型"); 方法去执行filter,方法中通过 FilterLoader加载指定类型的Filter列表,然后交给 processZuulFilter方法去执行 ,该方法最终调用ZuulFilter.runFilter();方法去执行具体的Filter 。它会以下面的顺序去执行内置的Filter:

| 类型 | 过滤器 | 描述 | 顺序 |

| — | — | — | — |

| pre | ServletDetectionFilter | 在pre过滤器中,ServletDetectionFilter是第一个执行的过滤器,检测请求是用 DispatcherServlet还是 ZuulServlet,将结果设置到RequestContext中 | -3 |

| pre | Servlet30WrapperFilter | 主要是将原始请求进行包装,将原始的HttpServletRequest请求包装成Servlet30RequestWrapper类型 | -2 |

| pre | FormBodyWrapperFilter | 同Servlet30RequestWrapper一样,也是对请求的一个包装,只不过他只包装表单数据,即:content-type中必须带有“application/x-www-form-urlencoded”或“multipart/form-data” | -1 |

| error | SendErrorFilter | 这个是用来发送错误的Filter | 0 |

| pre | DebugFilter | 设置请求过程是否开启debug,将当前请求上下文中的debugRoutingdebugRequest参数设置为true | 1 |

| pre | PreDecorationFilter | 基本的路由转发配置,根据uri调用哪一个route过滤器 | 5 |

| route | RibbonRoutingFilter | 服务路由的过滤器,使用用Ribbon 做负载均衡,hystrix做熔断 | 10 |

| route | SimpleHostRoutingFilter | 简单主机路由过滤器,如果使用url路由,则用这个过滤器 | 100 |

| route | SendForwardFilter | 它使用RequestDispatcher转发请求 | 500 |

| post | SendResponseFilter | SendResponseFilter是Zuul的最后一个Filter,负责最终响应结果的输出。 | 1000 |

error类型的filter在出异常的时候才会执行

5.ZuulFilter

ZuulFilter 是所有Filter的抽象类,它的接口是IZuulFilter ,它里面有四个很重要的方法

//这个是

public interface IZuulFilter {

//是否要执行Run方法

boolean shouldFilter();

//filter的核心业务方法

Object run() throws ZuulException;

}

public abstract class ZuulFilter implements IZuulFilter, Comparable {

private final AtomicReference filterDisabledRef = new AtomicReference<>();

/**

  • to classify a filter by type. Standard types in Zuul are “pre” for pre-routing filtering,

  • “route” for routing to an origin, “post” for post-routing filters, “error” for error handling.

  • We also support a “static” type for static responses see StaticResponseFilter.

  • Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)

  • @return A String representing that type

*/

//这个是filter的类型 ,有 pre ,route,post error

abstract public String filterType();

/**

  • filterOrder() must also be defined for a filter. Filters may have the same filterOrder if precedence is not

  • important for a filter. filterOrders do not need to be sequential.

  • @return the int order of a filter

*/

//这个是filter的执行顺序,越小越先执行

abstract public int filterOrder();

…省略…

}

详细看一下ZuulFilter 的源码

public abstract class ZuulFilter implements IZuulFilter, Comparable {

…省略…

public ZuulFilterResult runFilter() {

ZuulFilterResult zr = new ZuulFilterResult();

if (!isFilterDisabled()) {

//调用shouldFilter方法,这是个抽象方法,子类需要复写该方法返回 bool值决定要不要执行run方法

if (shouldFilter()) {

Tracer t = TracerFactory.instance().startMicroTracer(“ZUUL::” + this.getClass().getSimpleName());

try {

//调用 filter的run方法去执行,也是个抽象方法,需要子类去实现自己的业务逻辑

Object res = run();

//执行成功,包装一个成功状态的ZuulFilterResult对象返回

zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);

} catch (Throwable e) {

t.setName(“ZUUL::” + this.getClass().getSimpleName() + " failed");

//执行失败,包装一个失败状态的ZuulFilterResult对象返回

zr = new ZuulFilterResult(ExecutionStatus.FAILED);

zr.setException(e);

} finally {

t.stopAndLog();

}

} else {

zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);

}

}

return zr;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值