在Javelin框架中,NHttpContext
类在HTTP请求处理流水线中扮演着至关重要的角色。它是一个封装了请求-响应生命周期各个方面的对象,管理着HTTP请求的各个环节。下面我们将深入探讨NHttpContext
的功能、组成部分及其设计思路。
NHttpContext
概述
NHttpContext
是一个容器,保存了处理HTTP请求所需的所有必要元素。它不仅代表当前HTTP交换的状态,还管理流水线上下文、日志记录、错误处理等内容。其设计使其成为HTTP请求生命周期中的主要上下文对象,提供了一种有组织的方式来管理请求和响应。
以下是
NHttpContext
中主要属性的介绍:
-
HttpExchange exchange:
这是实际的HTTP交换对象,代表了HTTP请求和响应。它是Java HTTP服务器提供的标准HttpExchange
对象,但在Javelin中,它被封装在NHttpContext
中,以便提供更简洁和定制化的处理流程。 -
HttpPipelineContext pipelineContext:
pipelineContext
负责管理HTTP请求处理流水线的各个阶段。这个流水线包括路由、认证、日志记录等步骤。它确保HTTP请求在每个阶段都能被正确处理。 -
OprLogScope oprLogScope:
该对象用于在请求处理过程中管理日志记录的作用域。它允许Javelin在特定的作用域内创建和处理日志,确保与特定HTTP请求相关的日志能被准确捕捉。 -
Exception lastException:
如果在请求处理过程中发生任何异常,这个字段存储最后的异常。这个功能对调试非常有用,因为它允许开发者访问可能干扰HTTP请求处理的异常信息。 -
boolean skipAuthentication:
该布尔标志控制是否跳过当前请求的认证。对于某些请求,不需要认证时可以设置为true
,这样请求就不需要经过认证步骤。
public class NHttpContext {
public HttpExchange exchange;
public HttpPipelineContext pipelineContext;
public OprLogScope oprLogScope;
public Exception lastException;
public boolean skipAuthentication;
public NHttpContext(HttpExchange exchange, RouteDefinition routeDefinition) {
this.exchange = exchange;
this.pipelineContext = HttpPipelineContext.start(this);
this.pipelineContext.routeDefinition = routeDefinition;
}
void setOprLogScope(OprLogScope oprLogScope) {
this.oprLogScope = oprLogScope;
}
public void httpReply(int statusCode, String message) {
try {
this.exchange.sendResponseHeaders(statusCode, 0);
this.exchange.getResponseBody().write(message.getBytes());
this.exchange.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
HttpPipelineContext 类
HttpPipelineContext
类主要负责管理与请求处理流水线相关的信息。其功能包括:
- processId:每个请求都应该有一个唯一的 ID,方便跟踪和调试。
- startTime 和 endTime:记录请求的开始和结束时间,用于性能分析和日志记录。
- routeDefinition:该字段关联当前请求处理的路由定义,确保请求按正确的路由规则进行处理。
- setException:设置请求处理过程中发生的异常,便于在整个流程中传递和记录错误。
public class HttpPipelineContext {
public String processId;
public Date startTime;
public Date endTime;
public NHttpContext httpContext;
public RouteDefinition routeDefinition;
public Exception lastException;
public static HttpPipelineContext start(NHttpContext httpContext) {
HttpPipelineContext pipelineContext = new HttpPipelineContext(httpContext);
OprLogScope oprLogScope = OprLogScope.start(httpContext.pipelineContext);
pipelineContext.httpContext.setOprLogScope(oprLogScope);
return pipelineContext;
}
public void setRouteDefinition(RouteDefinition routeDefinition) {
this.routeDefinition = routeDefinition;
}
private HttpPipelineContext(NHttpContext httpContext) {
if (httpContext == null) {
throw new IllegalArgumentException("httpContext cannot be null");
}
this.httpContext = httpContext;
httpContext.pipelineContext = this;
}
public void setException(Exception ex) {
if (ex != null) {
httpContext.lastException = ex;
}
}
public void completeRequest() {
throw new AbortRequestException();
}
public void dispose() {
this.httpContext = null;
}
}
OprLogScope 类
OprLogScope
类负责在请求的生命周期内进行操作日志的记录和异常的处理。它的设计包括:
- steps:记录操作的每个步骤。
- oprlog:操作日志对象,记录请求处理过程中的各项操作。
- start:启动操作日志范围的方法,负责创建和初始化操作日志。
public class OprLogScope {
private List<StepItem> steps;
public OprLog oprlog;
public static OprLogScope start(HttpPipelineContext pipelineContext) {
OprLogScope scope = new OprLogScope();
scope.oprlog = OprLog.create(pipelineContext);
return scope;
}
public int setException(Exception ex) {
return oprlog.setException(ex);
}
public int saveOprLog(HttpPipelineContext pipelineContext) {
LogHelper.Write(this.oprlog);
return 1;
}
}
NHttpContext
的设计思路
在设计NHttpContext
时,重点考虑了模块化、扩展性、易用性以及与Javelin框架中的其他组件的集成。作为Javelin HTTP请求处理流水线的一部分,NHttpContext
的设计思路围绕着以下几个核心原则展开:
单一责任原则(Single Responsibility Principle)
NHttpContext
的设计遵循单一责任原则,它主要负责管理和维护一个HTTP请求生命周期中的各种上下文信息。通过将HTTP交换的相关信息(如请求、响应、路由信息、日志记录等)集中到一个对象中,NHttpContext
避免了将过多责任分散到多个地方,从而提升了代码的可读性和可维护性。
责任划分:
HttpExchange
:处理请求和响应。HttpPipelineContext
:管理HTTP请求处理的流水线上下文,确保请求按顺序经过不同阶段的处理。OprLogScope
:处理日志记录的作用域,确保所有操作的日志能够被正确追踪。Exception
:捕捉并存储在请求处理过程中出现的异常信息。
灵活的流水线处理(Flexible Pipeline Handling)
NHttpContext
将HTTP请求处理流程分为多个阶段,每个阶段由HttpPipelineContext
负责。这使得Javelin的请求处理流水线具有很高的灵活性和可定制性,开发者可以根据具体需求在不同阶段插入中间件、路由逻辑、认证步骤等。
- 流水线的动态性:
HttpPipelineContext
会根据具体的路由定义和配置动态调整请求的处理流程。每次请求的流水线都可以根据具体的业务需求进行配置,使得请求处理过程更加高效和灵活。
高度模块化(Modularization)
在NHttpContext
的设计中,各个功能模块之间的耦合度较低。例如,HttpExchange
与HttpPipelineContext
之间并没有强依赖,而是通过NHttpContext
进行解耦,使得每个模块都能够独立工作并实现其特定功能。
- 分离关注点:日志处理、异常处理、HTTP请求和响应的处理等不同的关注点被封装在不同的对象中,使得每个对象都专注于其核心功能。
- 扩展性:这种设计使得开发者可以根据需求向
NHttpContext
中添加新的处理模块,例如,新的认证方式、日志记录策略等,保持了较高的扩展性。
集成式错误处理(Integrated Error Handling)
NHttpContext
内建了异常处理机制,通过lastException
字段记录发生的异常,使得开发者能够快速定位和处理错误。错误信息被集中管理,有助于后续的调试和问题追踪。
- 集中管理异常:
NHttpContext
会捕获并存储处理过程中发生的异常,避免了异常分散在各个模块中。这样开发者可以通过lastException
迅速获取异常详情,并进行统一的处理。
public class ActionExecutor {
public void execute(NHttpContext context) throws Exception {
try{
// ...
handlerRequest(context);
} catch ( AbortRequestException e) {
// 提前结束请求,啥也不干了
} catch (Exception e) {
Throwable cause = e.getCause();
// 记录原始异常
context.pipelineContext.setException((Exception)cause);
app.onError(context);
} finally {
app.endRequest(context);
}
}
响应处理简化(Simplified Response Handling)
NHttpContext
提供了一个简单的接口httpReply
,用于发送响应。通过该接口,开发者无需过多关注底层的HttpExchange
细节,而只需传递状态码和响应体。这样简化了响应处理流程,提高了开发效率。
- 简洁的API:
httpReply
方法为响应发送提供了统一的接口,使得请求的响应处理变得直观和高效。 - 自动化的关闭连接:在异常发生后,调用
httpReply
方法自动关闭HttpExchange
连接,无需手动干预。
面向操作的日志记录(Operation-Oriented Logging)
NHttpContext
设计了OprLogScope
来管理每个HTTP请求的操作日志。这使得每个请求的日志记录都能与当前操作(例如,路由、认证等)相关联,方便进行精准的日志追踪。
- 作用域管理:
OprLogScope
允许每个请求在特定的操作上下文内生成日志。这种方式增强了日志的可读性,帮助开发者清晰地追踪每个请求在不同阶段的执行情况。 - 日志隔离:通过为每个请求提供独立的日志作用域,避免了不同请求之间日志的混淆,提高了日志的准确性和可操作性。
public static HttpPipelineContext start(NHttpContext httpContext) {
HttpPipelineContext pipelineContext = new HttpPipelineContext(httpContext);
// 为每个请求创建独立的日志作用域
OprLogScope oprLogScope = OprLogScope.start(httpContext.pipelineContext);
pipelineContext.httpContext.setOprLogScope(oprLogScope);
return pipelineContext;
}
可配置的认证机制(Configurable Authentication Mechanism)
NHttpContext
通过skipAuthentication
标志允许开发者灵活地控制是否需要认证。这使得在某些场景下(如公共API或不需要身份验证的请求)可以跳过认证过程,减少了不必要的性能开销。
- 认证跳过机制:开发者可以根据业务需求灵活地跳过认证步骤,而无需修改底层认证逻辑。
- 灵活性:认证机制的可配置性增加了框架的灵活性,使得它能够适应不同类型的Web应用。
在认证中间件里面我们可以这样使用:
public void authenticateRequest(NHttpContext httpContext) throws Exception {
// 如果skipAuthentication为true,则跳过认证
if (httpContext.skipAuthentication)
return;
for (NHttpModule module : modules) {
module.authenticateRequest(httpContext);
}
}
结论
NHttpContext
类是Javelin框架中处理HTTP请求的关键组件之一。它帮助封装了请求-响应管理的核心元素,提供了一个有组织的方式来处理HTTP交换,包括认证、日志记录、异常处理和响应生成。
通过理解并使用NHttpContext
,开发者可以更好地管理和定制HTTP请求的处理行为,确保应用保持模块化、可维护且高效。当然目前这个类还有很多缺点,后续我会在过程中继续完善。中间很多的细节没有展开,大家可以自行查看源码。
完整代码请参考GitHub仓库。