EH-ADMIN:一个springboot + vue 前后端分离的后台管理模板,一键生成CRUD操作,RBAC权限控制...

EH-ADMIN:一个springboot + vue 前后端分离的后台管理模板,一键生成CRUD操作,RBAC权限控制...

一、背景与问题

在企业级应用开发中,后台管理系统的开发往往面临以下挑战:

  1. 重复性开发:每个模块都需要编写CRUD接口、前端页面、权限控制逻辑
  2. 权限控制复杂:需要实现RBAC(基于角色的访问控制)模型,处理角色-权限-资源的多维关系
  3. 技术栈整合困难:前后端分离架构需要处理API接口设计、数据格式转换、跨域等问题
  4. 开发效率低下:需要大量手动编写代码,缺乏自动化工具支持

EH-ADMIN作为一款开源模板,通过以下创新点解决上述问题:

  • 基于代码生成器的自动化开发
  • 嵌入式RBAC权限控制体系
  • 前后端分离的完整架构支持
  • 丰富的可配置选项

二、基本原理

1. 技术架构设计

EH-ADMIN采用前后端分离架构,核心组件包括:

  • 后端:Spring Boot + MyBatis Plus + Spring Security
  • 前端:Vue 3 + Element Plus + Axios
  • 数据库:MySQL + Redis(可选)

核心流程:

用户请求 -> 前端组件 -> Axios请求 -> 后端接口 -> 服务层处理 -> 数据库访问 -> 响应返回

2. 代码生成原理

通过模板引擎(如Freemarker)实现代码生成,核心流程:

1. 定义实体类模板(Entity.java.ftl)
2. 生成Service/Controller层代码(基于注解)
3. 自动生成前端组件(基于Vue单文件组件模板)
4. 动态生成API文档(Swagger)

3. RBAC权限控制原理

采用三元组模型(User-Role-Permission):

User → Role → Permission → Resource

通过数据库表结构实现:

CREATE TABLE role (
    id BIGINT PRIMARY KEY,
    name VARCHAR(50) NOT NULL
);

CREATE TABLE permission (
    id BIGINT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    resource VARCHAR(255) NOT NULL
);

CREATE TABLE role_permission (
    role_id BIGINT,
    permission_id BIGINT
);

三、环境准备

1. 后端环境配置

# 创建Spring Boot项目
spring init --build=maven --java=17 --build-gradle --no-interactive eh-admin

# 添加依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. 前端环境配置

# 创建Vue3项目
npm create vue@latest eh-admin-vue

# 安装依赖
npm install element-plus axios

四、核心实现

1. 实体类生成示例

创建实体类模板(Entity.java.ftl):

<#assign className = table.className>
<#assign classNameWithoutPackage = className?replace('.', '/')>
package ${table.namespace};

import com.baomidou.mybatisplus.annotation.*;

<#assign tableId = table.id>
<#assign tablePk = table.pk>

@TableName("${table.name}")
public class ${className} {
    @TableId(value = "${tableId}", type = IdType.AUTO)
    private Long id;

    @TableField(value = "name")
    private String name;

    @TableField(value = "created_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createdTime;

    @TableField(value = "updated_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updatedTime;

    // Getters and Setters
}

2. 权限控制配置

Spring Security配置类:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/api/**").authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .logoutSuccessUrl("/login")
                .permitAll()
                .and()
            .csrf().disable()
            .sessionManagement()
                .maximumSessions(1)
                .expiredSessionStrategy(new CustomSessionExpiredStrategy());
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

3. 前端组件示例

创建用户管理组件(UserList.vue):

<template>
  <el-table :data="users" border style="width: 100%">
    <el-table-column prop="id" label="ID" width="180"></el-table-column>
    <el-table-column prop="name" label="名称"></el-table-column>
    <el-table-column prop="createdTime" label="创建时间" width="180">
      <template slot-scope="scope">
        {{ formatDate(scope.row.createdTime) }}
      </template>
    </el-table-column>
    <el-table-column label="操作">
      <template slot-scope="scope">
        <el-button @click="editUser(scope.row)">编辑</el-button>
        <el-button @click="deleteUser(scope.row)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      users: []
    };
  },
  mounted() {
    this.fetchUsers();
  },
  methods: {
    async fetchUsers() {
      const res = await this.$axios.get('/api/users');
      this.users = res.data;
    },
    formatDate(date) {
      return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
    }
  }
};
</script>

五、完整案例

1. 用户管理模块开发

后端实现

创建实体类:

@TableName("user")
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private String name;

    private Date createdTime;

    private Date updatedTime;

    // Getters and Setters
}

创建Mapper接口:

public interface UserMapper extends BaseMapper<User> {
}

创建Service层:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public List<User> getAllUsers() {
        return userMapper.selectList(null);
    }

    public void saveUser(User user) {
        user.setCreatedTime(new Date());
        user.setUpdatedTime(new Date());
        userMapper.insert(user);
    }

    public void deleteUser(Long id) {
        userMapper.deleteById(id);
    }
}

创建Controller:

@RestController
@RequestMapping("/api/users")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @PostMapping
    public void saveUser(@RequestBody User user) {
        userService.saveUser(user);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }
}

前端实现

创建页面组件:

<template>
  <div>
    <el-button @click="addUser">新增</el-button>
    <el-table :data="users" border style="width: 100%">
      <el-table-column prop="id" label="ID" width="180"></el-table-column>
      <el-table-column prop="name" label="名称"></el-table-column>
      <el-table-column prop="createdTime" label="创建时间" width="180">
        <template slot-scope="scope">
          {{ formatDate(scope.row.createdTime) }}
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button @click="editUser(scope.row)">编辑</el-button>
          <el-button @click="deleteUser(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      users: []
    };
  },
  mounted() {
    this.fetchUsers();
  },
  methods: {
    async fetchUsers() {
      const res = await this.$axios.get('/api/users');
      this.users = res.data;
    },
    formatDate(date) {
      return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
    }
  }
};
</script>

六、源码解析

1. 代码生成器核心逻辑

public class CodeGenerator {
    public static void main(String[] args) {
        // 1. 读取配置文件
        Properties props = new Properties();
        try (InputStream is = new FileInputStream("generator.properties")) {
            props.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 2. 创建模板引擎
        Configuration configuration = Configuration.defaultConfiguration();
        configuration.setClassForTemplateLoading("templates", "java");
        configuration.setTemplateExceptionHandler(WrapperTemplateExceptionHandler.class);

        // 3. 生成实体类
        Template template = configuration.getTemplate("entity.ftl");
        Map<String, Object> model = new HashMap<>();
        model.put("entity", new Entity());
        try (Writer writer = new FileWriter("src/main/java/com/example/demo/Entity.java")) {
            template.process(model, writer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 权限控制核心逻辑

public class PermissionService {
    public boolean checkPermission(String username, String resource) {
        // 1. 查询用户角色
        List<Role> roles = roleRepository.findByUser(username);
        // 2. 查询角色权限
        Set<String> permissions = roles.stream()
            .flatMap(role -> role.getPermissions().stream())
            .map(Permission::getName)
            .collect(Collectors.toSet());
        // 3. 检查资源权限
        return permissions.contains(resource);
    }
}

七、进阶使用

1. 多租户支持

通过在实体类中添加tenant字段:

@TableName("tenant")
public class Tenant {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private String name;

    private String tenantId;

    // Getters and Setters
}

在SQL查询中添加租户过滤:

public List<User> getTenantUsers(String tenantId) {
    return userMapper.selectList(new QueryWrapper<User>().eq("tenant_id", tenantId));
}

2. 工作流集成

结合Flowable实现审批流程:

public void startProcess(String userId, String processDefinitionId) {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    ProcessInstanceEntity processInstance = runtimeService.startProcessInstanceById(processDefinitionId, 
        Collections.singletonMap("userId", userId));
}

3. 审计日志

通过AOP记录操作日志:

@Aspect
@Component
public class AuditAspect {
    @Around("execution(* com.example.demo.controller.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long duration = System.currentTimeMillis() - start;
        // 记录日志
        return result;
    }
}

八、性能与工程实践

1. 性能优化策略

  1. 数据库优化

    • 为常用查询字段添加索引
    • 使用分页查询(limit offset
    • 对大数据量使用分库分表
  2. 缓存策略

    • 对频繁访问的权限数据使用Redis缓存
    • 对数据更新操作使用缓存失效策略
  3. 异步处理

    • 使用Spring Task处理定时任务
    • 使用RabbitMQ处理耗时操作

2. 安全防护措施

  1. 防止SQL注入

    • 使用MyBatis Plus的QueryWrapper构建查询
    • 避免直接拼接SQL语句
  2. 防止XSS攻击

    • 使用Vue的v-html时进行内容过滤
    • 对用户输入进行HTML转义处理
  3. 防止CSRF攻击

    • 使用Spring Security的CsrfToken机制
    • 对关键操作添加token验证

九、常见问题与踩坑

1. 权限验证失败

问题表现:用户访问授权资源时提示403 Forbidden

原因分析

  • 权限配置错误
  • 权限缓存未更新
  • 未正确处理角色继承关系

解决办法

// 确保权限缓存及时更新
@Cacheable(value = "permissions", key = "#username")
public Set<String> getPermissions(String username) {
    // 查询逻辑
}

2. 前端页面加载缓慢

问题表现:首次访问页面时出现明显延迟

优化方案

  • 使用Vue的懒加载组件(lazy
  • 对大数据量使用虚拟滚动(vue-virtual-scroller
  • 对接口进行分页处理

3. 权限配置错误

问题表现:新增权限后未生效

解决办法

  • 检查RBAC配置是否正确
  • 检查权限分配是否完整
  • 确认缓存是否已清除

十、最佳实践

1. 使用建议

  1. 适用场景

    • 快速开发标准CRUD功能
    • 需要RBAC权限控制的管理系统
    • 需要前后端分离的项目架构
  2. 开发规范

    • 保持代码结构清晰
    • 使用统一的命名规范
    • 对关键业务逻辑进行单元测试

2. 避免使用场景

  1. 不适合的场景

    • 需要高度定制化业务逻辑的项目
    • 需要复杂工作流的系统
    • 需要高性能实时处理的场景

十一、总结

EH-ADMIN作为一款Spring Boot + Vue的后台管理模板,通过代码生成器和RBAC权限控制模块,有效解决了传统开发中的重复性工作和权限管理难题。其核心价值体现在:

  • 自动化代码生成提高开发效率
  • 嵌入式权限控制体系确保安全
  • 前后端分离架构适应现代开发需求
  • 灵活的扩展能力适应不同业务场景

在实际应用中,开发者需要根据项目需求合理使用该模板,同时注意避免在需要高度定制化或复杂业务逻辑的场景中过度依赖。通过合理配置和优化,EH-ADMIN能够显著提升开发效率,降低维护成本,是企业级后台管理系统开发的理想选择。

最后修改于:2026年09月19日 09:28

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日