node-web-mvc
Version:
node spring mvc
179 lines (178 loc) • 9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const src_1 = __importDefault(require("../hmr/src"));
const WebMvcConfigurationSupport_1 = __importDefault(require("./config/WebMvcConfigurationSupport"));
const ModuleLoader_1 = __importDefault(require("./util/ModuleLoader"));
const GenericApplicationContext_1 = __importDefault(require("./context/GenericApplicationContext"));
const BeanDefinition_1 = __importDefault(require("../ioc/factory/BeanDefinition"));
const FilterDispatcher_1 = __importDefault(require("./filter/FilterDispatcher"));
const HttpServletRequest_1 = __importDefault(require("./http/HttpServletRequest"));
const HttpServletResponse_1 = __importDefault(require("./http/HttpServletResponse"));
const FilterHandlerAdapter_1 = __importDefault(require("./filter/FilterHandlerAdapter"));
const HttpStatus_1 = __importDefault(require("./http/HttpStatus"));
const DefaultListableBeanFactory_1 = __importDefault(require("../ioc/factory/DefaultListableBeanFactory"));
const Javascript_1 = __importDefault(require("../interface/Javascript"));
const RuntimeAnnotation_1 = __importDefault(require("./annotations/annotation/RuntimeAnnotation"));
const Configuration_1 = __importDefault(require("../ioc/annotations/Configuration"));
const NodeNativeConnector_1 = __importDefault(require("./connector/NodeNativeConnector"));
const RequestBodyReader_1 = __importDefault(require("./http/body/RequestBodyReader"));
const ApplicationDispatcher_1 = __importDefault(require("./http/ApplicationDispatcher"));
const BootConfiguration_1 = __importDefault(require("./BootConfiguration"));
const Tracer_1 = __importDefault(require("./annotations/annotation/Tracer"));
const HotUpdaterReleaseManager_1 = __importDefault(require("../hmr/src/HotUpdaterReleaseManager"));
class SpringApplication {
constructor(...primarySources) {
this.primarySources = primarySources;
registerHotUpdate(this, this.initializeApplication.bind(this));
}
static run(primarySource, connect) {
return new SpringApplication(primarySource).run(connect);
}
/**
* 尝试注入配置
*/
tryInjectDefaultConfiguration(context) {
const beanFactory = context.getBeanFactory();
const configAnnos = RuntimeAnnotation_1.default.getAnnotations(Configuration_1.default);
const configAnno = configAnnos.find((m) => Javascript_1.default.createTyper(m.ctor).isType(WebMvcConfigurationSupport_1.default));
const SpringConfig = configAnno === null || configAnno === void 0 ? void 0 : configAnno.ctor;
if (!SpringConfig) {
// 如果没有自定义配置,则使用默认配置对象
const definition = new BeanDefinition_1.default(WebMvcConfigurationSupport_1.default, null, 'singleton');
const beanName = BeanDefinition_1.default.toBeanName(WebMvcConfigurationSupport_1.default);
beanFactory.registerBeanDefinition(beanName, definition);
}
}
/**
* 加载所有模块
*/
readyWorkprogress(cwd, exclude) {
// 存储cacheKeys
const cache = {};
Object.keys(require.cache).forEach((k) => cache[k.replace(/\\/g, '/').toLowerCase()] = true);
// 加载controller等
cwd
.filter(Boolean)
.forEach((dir) => new ModuleLoader_1.default(dir, cache, exclude));
}
/**
* 顶层异常兜底
*/
onError(status, res, ex) {
const response = res.nativeResponse;
ex && console.error(ex);
if (!res.headersSent) {
const content = `HTTP Status ${status.code} - ${status.message}`;
response.setHeader('content-type', 'text/html');
response
.writeHead(status.code, status.message).end(`<html lang="en">
<head>
<title>${content}</title>
<style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style>
</head>
<body>
<h1>${content}</h1>
</body>
</html>`);
}
}
initBootConfigs() {
var _a, _b;
const bootConfig = this.bootConfig = new BootConfiguration_1.default(this.primarySources);
const hotOptions = bootConfig.getHotOptions();
(_b = (_a = this.hotUpdater) === null || _a === void 0 ? void 0 : _a.close) === null || _b === void 0 ? void 0 : _b.call(_a);
if (hotOptions) {
// 启动热更新
this.hotUpdater = src_1.default.run(hotOptions);
}
if (bootConfig.getLaunchLogOff() !== true) {
const port = bootConfig.getPort();
console.log(`
-----------------------------------------------------------
====> Start Node-Mvc Server
====> Enviroment: development
====> Listening: port ${port}
====> Hot Module Update: ${this.hotUpdater ? 'eanbled' : 'disabled'}
====> Url: http://localhost:${port}/
====> Swagger: ${bootConfig.getEanbleSwagger() ? `http://localhost:${port}/swagger-ui/index.html` : 'disabled'}
-----------------------------------------------------------
`.split('\n').map((m) => m.trim()).join('\n'));
}
// 装载所有模块
this.readyWorkprogress(bootConfig.getScanBasePackages(), bootConfig.getExcludeScan());
}
initializeApplication() {
// 创建应用上下文
const context = this.context = new GenericApplicationContext_1.default(this.bootConfig);
const beanFactory = context.getBeanFactory();
if (beanFactory instanceof DefaultListableBeanFactory_1.default) {
beanFactory.setAllowBeanDefinitionOverridable(false);
}
// 默认配置处理
this.tryInjectDefaultConfiguration(context);
// 应用上下文刷新
context.refresh();
// 构建过滤器处理适配器
this.filterAdapter = new FilterHandlerAdapter_1.default(beanFactory);
this.filterAdapter.addFilter(new FilterDispatcher_1.default(context));
this.configurer = beanFactory.getBeansOfType(WebMvcConfigurationSupport_1.default)[0];
}
handleRequest(nativeRequest, nativeResponse, next) {
const serverOptions = this.bootConfig.getServerOptions();
const base = serverOptions.base || '/';
const configurer = this.configurer;
if (nativeRequest.url.indexOf(base) !== 0) {
return next();
}
const filterAdapter = this.filterAdapter;
const reader = new RequestBodyReader_1.default(configurer.multipart);
const createDispatcher = (path) => new ApplicationDispatcher_1.default(filterAdapter, path);
const request = new HttpServletRequest_1.default(nativeRequest, base, createDispatcher, reader);
const response = new HttpServletResponse_1.default(nativeResponse);
filterAdapter
.doFilter(request, response)
// 尝试404处理
.then(() => this.onError(HttpStatus_1.default.NOT_FOUND, response, null))
// 尝试500处理
.catch((ex) => this.onError(HttpStatus_1.default.INTERNAL_SERVER_ERROR, response, ex));
}
/**
* 启动服务
*/
run(connect) {
this.initBootConfigs();
this.initializeApplication();
const serverOptions = this.bootConfig.getServerOptions();
const handleRequest = this.handleRequest.bind(this);
if (connect) {
// 自定义服务链接
connect(handleRequest, serverOptions).then(this.onConnected.bind(this));
}
else {
// 默认使用node服务链接
(new NodeNativeConnector_1.default()).connect(handleRequest, serverOptions).then(this.onConnected.bind(this));
}
return this.context;
}
onConnected(server) {
HotUpdaterReleaseManager_1.default.push(() => server.close());
}
}
exports.default = SpringApplication;
function registerHotUpdate(app, refreshLifecycle) {
src_1.default
.create(module)
.clean()
.postend((m) => {
var _a, _b, _c;
const tracer = Tracer_1.default.getTracer(app.configurer.constructor);
if ((tracer === null || tracer === void 0 ? void 0 : tracer.id) === m.filename) {
(_c = (_b = (_a = app.context) === null || _a === void 0 ? void 0 : _a.getBeanFactory()) === null || _b === void 0 ? void 0 : _b.destory) === null || _c === void 0 ? void 0 : _c.call(_b);
// 如果是配置文件更新,则需要重新初始化(并非重启服务,而是刷新掉上下文)
refreshLifecycle();
}
});
}