1. 企业客户管理系统技术栈选型解析
这套企业客户管理系统采用了当前主流的技术组合:SpringBoot+Vue3+MyBatis+MySQL。这种技术选型在2023年的企业级应用开发中具有显著优势:
后端技术栈:
- SpringBoot 2.7.x:简化了Spring应用的初始搭建和开发过程,内嵌Tomcat服务器,约定优于配置的设计理念让开发者能快速构建RESTful API
- MyBatis 3.5.x:轻量级的ORM框架,通过XML或注解配置SQL,相比Hibernate提供了更灵活的SQL控制能力
- Spring Security:处理认证授权,保护API端点安全
- Lombok:通过注解减少样板代码,如自动生成getter/setter
前端技术栈:
- Vue3 + Composition API:响应式系统重构后性能提升明显,组合式API让代码组织更灵活
- TypeScript 4.x:强类型检查减少运行时错误
- Element Plus:基于Vue3的UI组件库,提供丰富的企业级UI组件
- Axios:处理HTTP请求,与后端API交互
- Pinia:Vue3推荐的状态管理库,替代Vuex
数据库:
- MySQL 8.0:关系型数据库,支持JSON类型、窗口函数等高级特性
- 连接池使用HikariCP,相比传统的DBCP、C3P0有更好的性能表现
提示:实际开发中建议锁定具体版本号,避免因依赖自动升级导致兼容性问题。例如SpringBoot 2.7.10、Vue 3.2.47等。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计与前后端分离实践
2.1 整体架构分层
系统采用经典的三层架构,但针对前后端分离做了特别设计:
code复制├── 前端 (Vue3)
│ ├── public # 静态资源
│ ├── src
│ │ ├── api # 接口定义
│ │ ├── assets # 静态资源
│ │ ├── components # 通用组件
│ │ ├── composables # 组合式函数
│ │ ├── router # 路由配置
│ │ ├── stores # 状态管理
│ │ ├── styles # 全局样式
│ │ ├── utils # 工具函数
│ │ └── views # 页面组件
│
└── 后端 (SpringBoot)
├── src/main
│ ├── java
│ │ ├── config # 配置类
│ │ ├── controller # 控制器
│ │ ├── dto # 数据传输对象
│ │ ├── entity # 实体类
│ │ ├── enums # 枚举类
│ │ ├── exception # 异常处理
│ │ ├── mapper # MyBatis接口
│ │ ├── service # 业务逻辑
│ │ └── vo # 视图对象
│ └── resources
│ ├── mapper # MyBatis XML
│ └── application.yml # 配置文件
2.2 前后端协作关键点
-
接口规范:
- 使用RESTful风格设计API
- 响应统一格式:
json复制{ "code": 200, "message": "success", "data": {...}, "timestamp": 1689321600000 } - 错误码标准化,如400表示参数错误,401未授权等
-
跨域处理:
SpringBoot中配置CORS:java复制@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .maxAge(3600); } } -
联调技巧:
- 开发阶段可使用Vue代理解决跨域:
javascript复制// vue.config.js module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/api': '' } } } } } - 使用Swagger或Knife4j生成API文档,方便前后端协作
- 开发阶段可使用Vue代理解决跨域:
3. 核心功能模块实现
3.1 客户信息管理
数据库设计:
sql复制CREATE TABLE `t_customer` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '客户名称',
`type` tinyint NOT NULL COMMENT '客户类型 1-企业 2-个人',
`contact_person` varchar(20) DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(20) DEFAULT NULL COMMENT '联系电话',
`address` varchar(200) DEFAULT NULL COMMENT '地址',
`industry` varchar(50) DEFAULT NULL COMMENT '所属行业',
`credit_rating` tinyint DEFAULT NULL COMMENT '信用等级',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`),
KEY `idx_contact_phone` (`contact_phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
MyBatis XML映射:
xml复制<!-- CustomerMapper.xml -->
<mapper namespace="com.example.mapper.CustomerMapper">
<resultMap id="BaseResultMap" type="com.example.entity.Customer">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<!-- 其他字段映射 -->
</resultMap>
<select id="selectPage" resultMap="BaseResultMap">
SELECT * FROM t_customer
<where>
<if test="query.name != null and query.name != ''">
AND name LIKE CONCAT('%', #{query.name}, '%')
</if>
<if test="query.contactPhone != null and query.contactPhone != ''">
AND contact_phone = #{query.contactPhone}
</if>
</where>
ORDER BY create_time DESC
</select>
</mapper>
Vue3组件示例:
vue复制<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="name" label="客户名称" width="180" />
<el-table-column prop="contactPerson" label="联系人" width="180" />
<el-table-column prop="contactPhone" label="联系电话" />
<el-table-column label="操作">
<template #default="scope">
<el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getCustomerPage } from '@/api/customer'
const tableData = ref([])
const fetchData = async () => {
const res = await getCustomerPage({
page: 1,
size: 10
})
tableData.value = res.data.list
}
onMounted(() => {
fetchData()
})
</script>
3.2 客户跟进记录
实现客户跟进记录的增删改查,关键点包括:
- 使用MyBatis的
@Insert注解实现插入并返回主键:java复制@Insert("INSERT INTO t_follow_record(customer_id, follow_type, content, next_follow_time) " + "VALUES(#{customerId}, #{followType}, #{content}, #{nextFollowTime})") @Options(useGeneratedKeys = true, keyProperty = "id") int insert(FollowRecord record); - Vue3中使用Element Plus的DateTimePicker组件处理时间选择
- 实现富文本编辑器集成(如使用TinyMCE或WangEditor)
4. 高级特性与性能优化
4.1 二级缓存配置
MyBatis二级缓存可提升查询性能,但需要注意缓存一致性:
xml复制<!-- 在mapper.xml中开启 -->
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
<!-- SpringBoot配置类中启用 -->
@Bean
public ConfigurationCustomizer mybatisConfigurationCustomizer() {
return configuration -> {
configuration.setCacheEnabled(true);
configuration.setLocalCacheScope(LocalCacheScope.SESSION);
};
}
注意:更新操作多的场景慎用二级缓存,可能导致脏读。可通过
@CacheNamespaceRef指定更细粒度的缓存控制。
4.2 批量操作优化
MyBatis批量插入:
java复制@Insert("<script>" +
"INSERT INTO t_customer(name, contact_phone) VALUES " +
"<foreach collection='list' item='item' separator=','>" +
"(#{item.name}, #{item.contactPhone})" +
"</foreach>" +
"</script>")
void batchInsert(@Param("list") List<Customer> list);
使用Spring的@Transactional管理事务:
java复制@Service
@RequiredArgsConstructor
public class CustomerServiceImpl implements CustomerService {
private final CustomerMapper customerMapper;
@Transactional(rollbackFor = Exception.class)
@Override
public void batchProcess(List<Customer> customers) {
// 批量处理逻辑
}
}
4.3 Vue3性能优化技巧
-
组件懒加载:
javascript复制const CustomerList = defineAsyncComponent(() => import('./views/customer/List.vue')) -
列表虚拟滚动:
使用el-table-v2处理大数据量:vue复制<el-table-v2 :columns="columns" :data="data" :width="800" :height="400" :row-height="50" fixed /> -
API请求防抖:
javascript复制import { debounce } from 'lodash-es' const search = debounce(async (query) => { const res = await api.search(query) // 处理结果 }, 500)
5. 部署与运维方案
5.1 生产环境部署
后端部署:
- 打包SpringBoot应用:
bash复制
mvn clean package -DskipTests - 使用Docker容器化:
dockerfile复制FROM openjdk:17-jdk-slim ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"]
前端部署:
- 构建生产版本:
bash复制
npm run build - Nginx配置示例:
nginx复制server { listen 80; server_name yourdomain.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; } }
5.2 监控与日志
-
SpringBoot Actuator:
yaml复制# application.yml management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: always -
日志收集:
- 使用Logback+SLF4J
- 生产环境建议接入ELK或Graylog
-
前端监控:
- 使用Sentry捕获前端错误
- 接入Google Analytics或自建监控
6. 常见问题解决方案
6.1 MyBatis映射问题
枚举类型处理:
java复制public enum CustomerType {
COMPANY(1, "企业"),
PERSON(2, "个人");
@JsonCreator
public static CustomerType fromValue(int value) {
// 转换逻辑
}
}
// 在配置类中注册枚举处理器
@Bean
public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() {
return properties -> {
properties.getConfiguration().setDefaultEnumTypeHandler(EnumOrdinalTypeHandler.class);
};
}
6.2 Vue3组件通信
跨组件状态共享:
javascript复制// stores/customer.js
import { defineStore } from 'pinia'
export const useCustomerStore = defineStore('customer', {
state: () => ({
currentCustomer: null,
searchQuery: ''
}),
actions: {
setCurrentCustomer(customer) {
this.currentCustomer = customer
}
}
})
// 组件中使用
import { useCustomerStore } from '@/stores/customer'
const store = useCustomerStore()
store.setCurrentCustomer(customer)
6.3 性能问题排查
慢SQL监控:
yaml复制# application.yml
spring:
datasource:
hikari:
data-source-properties:
logger: Slf4JLogger
slowQueryThresholdMillis: 1000
前端性能分析:
- 使用Chrome DevTools的Performance面板
- 检查组件渲染次数:
javascript复制import { useRenderCounter } from '@/composables/renderCounter' const count = useRenderCounter()
这套技术栈组合经过多个企业级项目验证,在开发效率、运行性能和可维护性方面都有良好表现。实际开发中建议根据团队技术储备适当调整,例如:
- 前端测试:引入Vitest+Testing Library
- API文档:使用Swagger或Knife4j
- 持续集成:GitHub Actions或Jenkins流水线
对于刚接触这套技术栈的开发者,建议从官方文档入手:
