更新政府端和银行端
This commit is contained in:
223
bank-backend/server.js
Normal file
223
bank-backend/server.js
Normal file
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* 银行管理后台服务器
|
||||
* @file server.js
|
||||
* @description 银行系统后端API服务器主入口
|
||||
*/
|
||||
const express = require('express');
|
||||
const http = require('http');
|
||||
const cors = require('cors');
|
||||
const dotenv = require('dotenv');
|
||||
const helmet = require('helmet');
|
||||
const compression = require('compression');
|
||||
const swaggerUi = require('swagger-ui-express');
|
||||
const swaggerSpec = require('./config/swagger');
|
||||
const { sequelize } = require('./config/database');
|
||||
const logger = require('./utils/logger');
|
||||
const {
|
||||
apiRateLimiter,
|
||||
loginRateLimiter,
|
||||
inputSanitizer,
|
||||
sessionTimeoutCheck,
|
||||
securityHeaders
|
||||
} = require('./middleware/security');
|
||||
|
||||
// 加载环境变量
|
||||
dotenv.config();
|
||||
|
||||
// 创建Express应用和HTTP服务器
|
||||
const app = express();
|
||||
const server = http.createServer(app);
|
||||
const PORT = process.env.PORT || 5351;
|
||||
|
||||
// 安全中间件
|
||||
app.use(securityHeaders);
|
||||
app.use(helmet());
|
||||
app.use(compression());
|
||||
|
||||
// CORS配置
|
||||
app.use(cors({
|
||||
origin: process.env.CORS_ORIGIN || '*',
|
||||
credentials: true,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
|
||||
}));
|
||||
|
||||
// 请求解析中间件
|
||||
app.use(express.json({ limit: '10mb' }));
|
||||
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
||||
|
||||
// 安全中间件
|
||||
app.use(inputSanitizer);
|
||||
app.use(apiRateLimiter);
|
||||
|
||||
// 静态文件服务
|
||||
app.use('/uploads', express.static('uploads'));
|
||||
|
||||
// API文档
|
||||
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
|
||||
|
||||
// 健康检查端点
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
message: '银行系统运行正常',
|
||||
timestamp: new Date().toISOString(),
|
||||
version: '1.0.0'
|
||||
});
|
||||
});
|
||||
|
||||
// API路由
|
||||
app.use('/api/users', require('./routes/users'));
|
||||
app.use('/api/accounts', require('./routes/accounts'));
|
||||
app.use('/api/transactions', require('./routes/transactions'));
|
||||
|
||||
// 根路径
|
||||
app.get('/', (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
message: '银行管理后台API服务',
|
||||
version: '1.0.0',
|
||||
documentation: '/api-docs',
|
||||
health: '/health'
|
||||
});
|
||||
});
|
||||
|
||||
// 404处理
|
||||
app.use('*', (req, res) => {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: '请求的资源不存在',
|
||||
path: req.originalUrl
|
||||
});
|
||||
});
|
||||
|
||||
// 全局错误处理中间件
|
||||
app.use((error, req, res, next) => {
|
||||
logger.error('服务器错误:', error);
|
||||
|
||||
// 数据库连接错误
|
||||
if (error.name === 'SequelizeConnectionError') {
|
||||
return res.status(503).json({
|
||||
success: false,
|
||||
message: '数据库连接失败,请稍后重试'
|
||||
});
|
||||
}
|
||||
|
||||
// 数据库验证错误
|
||||
if (error.name === 'SequelizeValidationError') {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '数据验证失败',
|
||||
errors: error.errors.map(err => ({
|
||||
field: err.path,
|
||||
message: err.message
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
// 数据库唯一约束错误
|
||||
if (error.name === 'SequelizeUniqueConstraintError') {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '数据已存在,请检查输入'
|
||||
});
|
||||
}
|
||||
|
||||
// JWT错误
|
||||
if (error.name === 'JsonWebTokenError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
message: '无效的访问令牌'
|
||||
});
|
||||
}
|
||||
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
message: '访问令牌已过期'
|
||||
});
|
||||
}
|
||||
|
||||
// 默认错误响应
|
||||
res.status(error.status || 500).json({
|
||||
success: false,
|
||||
message: process.env.NODE_ENV === 'production'
|
||||
? '服务器内部错误'
|
||||
: error.message,
|
||||
...(process.env.NODE_ENV !== 'production' && { stack: error.stack })
|
||||
});
|
||||
});
|
||||
|
||||
// 优雅关闭处理
|
||||
const gracefulShutdown = (signal) => {
|
||||
logger.info(`收到 ${signal} 信号,开始优雅关闭...`);
|
||||
|
||||
server.close(async () => {
|
||||
logger.info('HTTP服务器已关闭');
|
||||
|
||||
try {
|
||||
await sequelize.close();
|
||||
logger.info('数据库连接已关闭');
|
||||
} catch (error) {
|
||||
logger.error('关闭数据库连接时出错:', error);
|
||||
}
|
||||
|
||||
logger.info('银行系统已安全关闭');
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// 强制关闭超时
|
||||
setTimeout(() => {
|
||||
logger.error('强制关闭服务器');
|
||||
process.exit(1);
|
||||
}, 10000);
|
||||
};
|
||||
|
||||
// 监听关闭信号
|
||||
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
||||
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
||||
|
||||
// 未捕获的异常处理
|
||||
process.on('uncaughtException', (error) => {
|
||||
logger.error('未捕获的异常:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
logger.error('未处理的Promise拒绝:', reason);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// 启动服务器
|
||||
const startServer = async () => {
|
||||
try {
|
||||
// 测试数据库连接
|
||||
await sequelize.authenticate();
|
||||
logger.info('✅ 数据库连接成功');
|
||||
|
||||
// 同步数据库模型(开发环境)
|
||||
// 按用户要求:不要初始化数据库(不自动建表/同步)
|
||||
// if (process.env.NODE_ENV === 'development') {
|
||||
// await sequelize.sync({ alter: true });
|
||||
// logger.info('✅ 数据库模型同步完成');
|
||||
// }
|
||||
|
||||
// 启动HTTP服务器
|
||||
server.listen(PORT, () => {
|
||||
logger.info(`🚀 银行管理后台服务器启动成功`);
|
||||
logger.info(`📡 服务地址: http://localhost:${PORT}`);
|
||||
logger.info(`📚 API文档: http://localhost:${PORT}/api-docs`);
|
||||
logger.info(`🏥 健康检查: http://localhost:${PORT}/health`);
|
||||
logger.info(`🌍 环境: ${process.env.NODE_ENV || 'development'}`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logger.error('❌ 服务器启动失败:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// 启动服务器
|
||||
startServer();
|
||||
|
||||
module.exports = app;
|
||||
Reference in New Issue
Block a user