万盛经开区规划建设局网站,陕西省煤炭建设第一中学官方网站,json网站开发,网页改版方案本文目录 本系列文章理解现有程序app文件夹中的package.json理解approuter.js 修改现有程序修改package.json新建index.js在Approuter中显示额外的逻辑 添加一些额外的Logger对应代码及branch 本系列文章
SAP CAP篇一: 快速创建一个Service#xff0c;基于Java的实现 SAP CAP… 本文目录 本系列文章理解现有程序app文件夹中的package.json理解approuter.js 修改现有程序修改package.json新建index.js在Approuter中显示额外的逻辑 添加一些额外的Logger对应代码及branch 本系列文章
SAP CAP篇一: 快速创建一个Service基于Java的实现 SAP CAP篇二为Service加上数据库支持 SAP CAP篇三定义Model SAP CAP篇四为CAP添加Fiori Elements程序(1) SAP CAP篇五为CAP添加Fiori Elements程序(2) SAP CAP篇六为CAP添加Fiori Elements程序(3) SAP CAP篇七为CAP添加Fiori Launchpad入口 (Sandbox环境) SAP CAP篇八为CAP添加App Router并支持Fiori Launchpad (Sandbox环境) SAP CAP篇九升级为SAP CDS 7.0, CAP Java 2以及Spring Boot 3 SAP CAP篇十理解Fiori UI的Annoation定义 SAP CAP篇十一支持Media Object图片、附件等 SAP CAP篇十二AppRouter 深入研究
理解现有程序
本篇基于上一篇 SAP CAP篇十一支持Media Object图片、附件等 代码基础。
app文件夹中的package.json
打开app文件夹中的package.json可以发现start命令定义如下
scripts: {start: node node_modules/sap/approuter/approuter.js
}理解approuter.js
看看上述start命令的approuter.js其中关键的部分是文件末尾的启动AppRouter部分。
if (require.main module) {let ar new Approuter();ar.start();
}修改现有程序
理解了现有程序之后可以对现有程序进行修改。
修改package.json
本步骤的修改是在app文件夹下。
修改package.json文件中的’scripts’部分
scripts: {start: node index.js
}新建index.js
由上述script所示这里的start命令将执行index.js。
该新建的index.js文件如下
const approuter require(sap/approuter);
const ar approuter();ar.start();其实上段代码其实就是Approuter.js的核心启动代码
这时候启动Service跟Approuter所有功能都正常运行。换言之上述代码修改是功能无损的修改但是它提供了额外的可能。
在Approuter中显示额外的逻辑
如果仔细研读approuter.js的源码它其实是node.js的程序。而其中的start方法是其中的关键
Approuter.prototype.start function (options, callback) {let self this;if (dynamicRoutingUtils.isDynamicRouting()) {self.first.use(dynamicRoutingUtils.initialize(self));if (options) {delete options.port;options.getRouterConfig dynamicRoutingUtils.getRouterConfig;} else {options {getRouterConfig: dynamicRoutingUtils.getRouterConfig};}}if (options) {validators.validateApprouterStartOptions(options);options _.cloneDeep(options);} else {options {};}callback optionalCallback(callback);if (this.cmdParser) {this.cmdParser.parse(process.argv);options _.defaults(options, this.cmdParser);}addImplicitExtension(this, options);let logger loggerUtil.getLogger(/approuter);logger.info(Application router version %s, require(./package.json).version);let app bootstrap(options);app.logger logger;app.approuter this;this._app app;loggerUtil.getAuditLogger(function(err, auditLogger){if (err) {throw err;}app.auditLogger auditLogger;serverLib.start(app, function (err, server) {self._server server;callback(err);});});
};继续研读下去其中最关键的serverLib.start(...)的逻辑实现在一个server.js的文件中而server的start方法
exports.start function (app, callback) {let routerConfig app.get(mainRouterConfig);let server;if (routerConfig.http2Support){server http2.createServer(app);} else if (routerConfig.httpsOptions) {server https.createServer(routerConfig.httpsOptions, app);} else {server http.createServer(app);}if (routerConfig.incomingConnectionTimeout ! undefined) {server.timeout routerConfig.incomingConnectionTimeout;}server.keepAliveTimeout routerConfig.serverKeepAlive || 0;let wsServer new WsProxy(app);wsServer.listen(server);server.on(error, callback);server.listen(routerConfig.serverPort, function () {app.logger.info(Application router is listening on port: server.address().port);callback(undefined, new Server(server, wsServer));});
};而引用到的lib在文件头部有定义
const http require(http);
const https require(https);
const http2 require(http2);
const WsProxy require(./websockets/WsProxy);
const util require(util);至此AppRouter的逻辑很清楚了就是一个基于nodejs的server。所以通过其可以实现一定额外的逻辑譬如proxy之类。
添加一些额外的Logger
虽然可以通过Approuter实现类似proxy的逻辑但是这不是本篇的重点。接下来通过AppRouter来实现额外的Log写入逻辑作为测试。
const approuter require(sap/approuter);
const { Console } require(console);// get fs module for creating write streams
const fs require(fs);ar.beforeRequestHandler.use(/api, async (req, res, next) {const myLogger new Console({stdout: fs.createWriteStream(normalStdout.txt),stderr: fs.createWriteStream(errStdErr.txt),});const { rawHeaders, method, originalUrl, url } req;let body [];let errorMessage null;// saving to normalStdout.txt filemyLogger.log(originalUrl ${originalUrl});myLogger.log(method ${method});myLogger.log(JSON.stringify(rawHeaders));// if (method POST || method PUT) {
// myLogger.log();
// myLogger.log(req);// for await (const chunk of req) {
// myLogger.log( 111 );
// myLogger.log( ${Date.now()} for each data);
// myLogger.log(Log Callback of on: ${chunk});
// body.push(chunk);
// }
// myLogger.log( 222 );
// myLogger.log( ${Date.now()} of all);
// body Buffer.concat(body).toString();
// myLogger.log(Log Callback of end: ${body});// myLogger.log();
// myLogger.log(req);
// }myLogger.log( 000 );myLogger.log( ${Date.now()} before next());next();
});运行后所有的对/api的情节都会被写入额外的normalStdout.txt。
其中被注释的代码部分会打印完整request的body部分但是作为副作用request这个stream已经被close了next()再发送到后续的处理就会失败所以这里的代码仅作为参考用途。
对应代码及branch
与本文配套的代码参见这里。
本篇对应的branch是8_approuter。