1. 项目背景与技术选型
集团门户网站作为企业对外展示和内部协作的核心平台,需要兼顾高并发访问、多角色权限管理和复杂业务逻辑处理。传统单体架构在应对这些需求时往往捉襟见肘,这正是我们采用SpringBoot+Vue前后端分离架构的根本原因。
SpringBoot的自动配置特性让后端开发效率提升显著。实测中,相比传统Spring MVC项目,同样的RESTful API接口开发时间可缩短40%。我们特别看重其内嵌Tomcat和Starter依赖机制——这意味着不需要额外配置Servlet容器,一个简单的main方法就能启动生产级服务。对于集团门户这种需要快速迭代的项目,这种"约定优于配置"的理念至关重要。
Vue.js的响应式数据绑定和组件化开发模式,则完美解决了前端开发的痛点。在门户网站中,不同部门往往需要定制化的展示模块。通过Vue的单文件组件(SFC),我们可以将导航栏、轮播图、新闻列表等拆分为独立组件,复用率提升60%以上。Element UI的引入更是让表单验证、表格分页这些高频功能开发时间缩短至原来的1/3。
数据库选型上,MySQL 8.0凭借其完善的ACID特性、窗口函数等高级特性成为首选。特别值得一提的是其JSON字段支持——对于门户网站中常见的动态扩展字段需求(如不同子公司需要不同的信息字段),可以直接存储JSON结构,避免了频繁的ALTER TABLE操作。MyBatis-Plus作为持久层框架,其Lambda表达式查询让SQL编写效率提升显著,一个典型的动态查询代码量可以减少50%。
2. 系统架构设计详解
2.1 前后端分离架构实践
我们采用严格的前后端分离架构,通过JWT进行身份认证。具体流程是:前端Vue应用部署在Nginx,后端SpringBoot服务独立部署,两者通过RESTful API交互。这种架构的最大优势在于并行开发——前端团队可以基于Mock数据先行开发,不受后端进度影响。
在网关层,我们使用Spring Cloud Gateway统一处理路由和跨域问题。实测发现,相比直接在Controller加@CrossOrigin注解,网关层统一处理能让跨域请求响应时间减少约15ms。对于门户网站高频的静态资源请求,我们配置了如下路由规则:
java复制@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("static_route", r -> r.path("/static/**")
.uri("http://localhost:8081"))
.build();
}
2.2 数据库设计关键点
集团门户的数据库设计需要特别注意扩展性和性能平衡。我们的核心表包括:
- 用户体系表:采用RBAC(基于角色的访问控制)模型,通过user、role、permission三张表实现细粒度权限控制。特别注意password字段使用BCrypt加密存储:
sql复制CREATE TABLE `sys_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '登录账号',
`password` varchar(100) NOT NULL COMMENT 'BCrypt加密密码',
`dept_id` bigint DEFAULT NULL COMMENT '所属部门',
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
内容管理表:采用"主表+扩展表"设计,主表存储通用字段,扩展表通过JSON字段存储动态属性。这种设计完美解决了不同子公司内容字段差异的问题。
-
操作日志表:记录关键操作,使用MyBatis的拦截器自动填充操作人、时间等信息。这里有个坑要注意:MySQL的DATETIME精度只到秒,如果需要更精确需要改用TIMESTAMP(3)。
3. 核心功能实现
3.1 多级权限控制系统
权限控制是集团门户的重中之重。我们实现了:
- 页面权限:通过Vue路由守卫控制
- 按钮权限:自定义v-permission指令
- 数据权限:通过MyBatis拦截器动态拼接SQL
后端权限校验采用Spring Security结合自定义注解:
java复制@PreAuthorize("@ss.hasPermission('system:user:edit')")
@PostMapping("/update")
public Result updateUser(@Validated @RequestBody SysUser user) {
// 业务逻辑
}
前端对应实现权限指令:
javascript复制Vue.directive('permission', {
inserted(el, binding) {
if (!checkPermission(binding.value)) {
el.parentNode.removeChild(el);
}
}
})
3.2 高性能内容发布
内容发布面临的主要挑战是富文本处理和大文件上传。我们的解决方案:
- 使用WangEditor作为富文本编辑器,后端通过XSS过滤防止注入攻击
- 大文件采用分片上传,前端使用Web Worker计算文件hash
- 引入Redis缓存热点内容,实测QPS从200提升到1500+
文件上传关键代码:
javascript复制// 前端分片逻辑
const chunkSize = 5 * 1024 * 1024; // 5MB
const chunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < chunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
uploadChunk(chunk, i);
}
4. 部署优化与性能调优
4.1 前端部署策略
我们采用以下优化措施:
- 按需加载:Vue路由使用懒加载
- 资源压缩:通过webpack配置gzip
- CDN加速:静态资源部署到阿里云OSS
实测首屏加载时间从4.2s降至1.8s。关键的webpack配置:
javascript复制configureWebpack: {
optimization: {
splitChunks: {
chunks: 'all',
maxSize: 244 * 1024 // 拆分包大小
}
}
}
4.2 后端性能调优
通过以下手段提升性能:
- 连接池优化:Druid配置maxWait=60000ms
- 二级缓存:Redis+MyBatis二级缓存
- SQL优化:使用EXPLAIN分析慢查询
一个典型的Druid配置:
yaml复制spring:
datasource:
druid:
max-active: 50
initial-size: 5
max-wait: 60000
min-idle: 5
validation-query: SELECT 1
test-on-borrow: false
test-on-return: false
test-while-idle: true
5. 踩坑实录与解决方案
5.1 跨域问题深度解决
虽然SpringBoot提供了@CrossOrigin注解,但在实际项目中我们发现几个坑:
- 预检请求(OPTIONS)缓存问题:通过添加Cache-Control头解决
- 带Cookie的跨域请求:必须设置withCredentials=true
- 网关层跨域配置:需要与业务服务层协调
最终的全局跨域配置:
java复制@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setMaxAge(3600L);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
5.2 MyBatis动态SQL陷阱
在使用MyBatis动态SQL时,我们遇到过几个典型问题:
- 条件判断失效:因为MyBatis使用OGNL表达式,注意0和'0'的区别
- 批量插入性能:推荐使用
配合rewriteBatchedStatements=true - 分页插件冲突:PageHelper与MyBatis-Plus分页不要混用
一个优化的批量插入示例:
xml复制<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO sys_log(operation, params) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.operation}, #{item.params})
</foreach>
</insert>
6. 项目扩展与演进
当前系统已经支持了基础的集团门户需求,但根据实际运营情况,我们规划了几个扩展方向:
- 微服务化改造:将用户中心、内容管理等模块拆分为独立服务
- SSO集成:与现有OA系统实现单点登录
- 智能化推荐:基于用户行为数据的内容推荐
- 低代码平台:允许业务部门自助配置展示模块
对于计划进行类似开发的同行,我的建议是前期一定要做好领域模型设计,特别是权限模型和数据权限模型。我们在二期开发时就因为初期设计不够灵活,不得不进行了大量重构工作。另外,前端组件化程度越高,后期维护成本就越低——这是我们用3个月重构换来的宝贵经验。
