当前位置: 首页 > news >正文

从零到一:手把手教你用SpringBoot+MyBatis搭建Tlias智能学习辅助系统后端(附完整源码)

SpringBoot+MyBatis实战:构建智能学习辅助系统后端全流程

1. 项目架构设计与技术选型

在当今企业级应用开发中,SpringBoot和MyBatis的组合已成为Java后端开发的黄金标准。本系统采用经典的三层架构设计:

技术栈对比表

技术组件优势在本系统中的应用场景
SpringBoot 2.7快速启动、自动配置项目基础框架
MyBatis 3.5SQL灵活可控、动态SQL支持数据持久层实现
MySQL 8.0关系型数据库、事务支持业务数据存储
Lombok简化POJO开发实体类Getter/Setter生成
PageHelper分页插件员工数据分页查询

项目目录结构

src/main/java ├── com.tlias │ ├── config # 配置类 │ ├── controller # 控制层 │ ├── service # 业务层 │ ├── mapper # 持久层 │ ├── pojo # 实体类 │ ├── utils # 工具类 │ └── aspect # AOP切面

2. 数据库设计与实体映射

系统核心业务围绕部门管理和员工管理展开,数据库设计遵循第三范式:

部门表SQL

CREATE TABLE dept ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '部门ID', name VARCHAR(10) NOT NULL UNIQUE COMMENT '部门名称', create_time DATETIME NOT NULL COMMENT '创建时间', update_time DATETIME NOT NULL COMMENT '修改时间' ) COMMENT '部门表';

员工表SQL

CREATE TABLE emp ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '员工ID', username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名', password VARCHAR(32) DEFAULT '123456' COMMENT '密码', name VARCHAR(10) NOT NULL COMMENT '姓名', gender TINYINT UNSIGNED NOT NULL COMMENT '性别(1男,2女)', image VARCHAR(300) COMMENT '头像URL', job TINYINT UNSIGNED COMMENT '职位', entrydate DATE COMMENT '入职日期', dept_id INT UNSIGNED COMMENT '部门ID', create_time DATETIME NOT NULL COMMENT '创建时间', update_time DATETIME NOT NULL COMMENT '修改时间' ) COMMENT '员工表';

实体类示例

@Data @NoArgsConstructor @AllArgsConstructor public class Dept { private Integer id; private String name; private LocalDateTime createTime; private LocalDateTime updateTime; }

3. SpringBoot工程初始化

关键依赖配置

<dependencies> <!-- SpringBoot基础依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis整合 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.3.0</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>

数据库连接配置

# application.properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/tlias?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 # MyBatis配置 mybatis.configuration.map-underscore-to-camel-case=true mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

4. RESTful接口设计与实现

采用REST风格设计API接口,遵循以下规范:

REST接口设计原则

  • 使用HTTP动词表示操作类型(GET/POST/PUT/DELETE)
  • 资源使用复数名词形式
  • 状态码遵循HTTP标准

部门管理接口示例

@RestController @RequestMapping("/depts") public class DeptController { @Autowired private DeptService deptService; @GetMapping public Result list() { List<Dept> deptList = deptService.list(); return Result.success(deptList); } @DeleteMapping("/{id}") public Result delete(@PathVariable Integer id) { deptService.delete(id); return Result.success(); } @PostMapping public Result add(@RequestBody Dept dept) { deptService.add(dept); return Result.success(); } @PutMapping public Result update(@RequestBody Dept dept) { deptService.update(dept); return Result.success(); } }

统一响应封装

@Data @NoArgsConstructor @AllArgsConstructor public class Result { private Integer code; private String msg; private Object data; public static Result success() { return new Result(1, "success", null); } public static Result success(Object data) { return new Result(1, "success", data); } public static Result error(String msg) { return new Result(0, msg, null); } }

5. MyBatis动态SQL实战

XML映射文件示例

<!-- DeptMapper.xml --> <mapper namespace="com.tlias.mapper.DeptMapper"> <select id="list" resultType="com.tlias.pojo.Dept"> SELECT id, name, create_time, update_time FROM dept </select> <delete id="deleteById"> DELETE FROM dept WHERE id = #{id} </delete> </mapper>

动态SQL应用

<!-- 员工条件分页查询 --> <select id="list" resultType="com.tlias.pojo.Emp"> SELECT * FROM emp <where> <if test="name != null and name != ''"> name LIKE CONCAT('%',#{name},'%') </if> <if test="gender != null"> AND gender = #{gender} </if> <if test="begin != null and end != null"> AND entrydate BETWEEN #{begin} AND #{end} </if> </where> ORDER BY update_time DESC </select>

6. 分页查询优化方案

原生分页与PageHelper对比

分页方式SQL编写复杂度性能功能丰富度
LIMIT语句
PageHelper

PageHelper整合步骤

  1. 添加依赖:
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.4.2</version> </dependency>
  1. 业务层实现:
@Override public PageBean page(Integer page, Integer pageSize) { // 设置分页参数 PageHelper.startPage(page, pageSize); // 执行查询 List<Emp> empList = empMapper.list(); Page<Emp> p = (Page<Emp>) empList; // 封装分页结果 PageBean pageBean = new PageBean(p.getTotal(), p.getResult()); return pageBean; }

7. 文件上传与云存储

本地存储方案

@PostMapping("/upload") public Result upload(MultipartFile image) throws IOException { // 原始文件名 String originalFilename = image.getOriginalFilename(); // 使用UUID生成新文件名 String extname = originalFilename.substring(originalFilename.lastIndexOf(".")); String newFileName = UUID.randomUUID() + extname; // 存储文件 image.transferTo(new File("D:/images/"+newFileName)); return Result.success("/images/"+newFileName); }

阿里云OSS集成

@Component public class AliOSSUtils { @Value("${aliyun.oss.endpoint}") private String endpoint; @Value("${aliyun.oss.accessKeyId}") private String accessKeyId; @Value("${aliyun.oss.accessKeySecret}") private String accessKeySecret; @Value("${aliyun.oss.bucketName}") private String bucketName; public String upload(MultipartFile file) throws IOException { // 创建OSSClient实例 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 生成随机文件名 String fileName = UUID.randomUUID() + file.getOriginalFilename(); // 上传文件流 ossClient.putObject(bucketName, fileName, file.getInputStream()); // 生成访问URL String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName; ossClient.shutdown(); return url; } }

8. 登录认证与JWT集成

JWT工具类实现

public class JwtUtils { private static String signKey = "tlias"; private static Long expire = 3600000L; public static String generateJwt(Map<String, Object> claims) { return Jwts.builder() .addClaims(claims) .signWith(SignatureAlgorithm.HS256, signKey) .setExpiration(new Date(System.currentTimeMillis() + expire)) .compact(); } public static Claims parseJWT(String jwt) { return Jwts.parser() .setSigningKey(signKey) .parseClaimsJws(jwt) .getBody(); } }

登录接口实现

@PostMapping("/login") public Result login(@RequestBody Emp emp) { Emp loginEmp = empService.login(emp); if(loginEmp != null) { Map<String, Object> claims = new HashMap<>(); claims.put("id", loginEmp.getId()); claims.put("username", loginEmp.getUsername()); claims.put("name", loginEmp.getName()); String token = JwtUtils.generateJwt(claims); return Result.success(token); } return Result.error("用户名或密码错误"); }

9. 全局异常处理机制

统一异常处理器

@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public Result handleException(Exception ex) { ex.printStackTrace(); return Result.error("操作失败,请联系管理员"); } @ExceptionHandler(SQLIntegrityConstraintViolationException.class) public Result handleSQLException(SQLIntegrityConstraintViolationException ex) { String message = ex.getMessage(); if(message.contains("Duplicate entry")) { return Result.error("数据已存在"); } return Result.error("数据库操作异常"); } }

10. AOP实现操作日志记录

日志切面实现

@Aspect @Component @Slf4j public class LogAspect { @Autowired private HttpServletRequest request; @Autowired private OperateLogMapper operateLogMapper; @Around("@annotation(com.tlias.annotation.Log)") public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable { // 获取操作人信息 String token = request.getHeader("token"); Claims claims = JwtUtils.parseJWT(token); Integer operateUser = (Integer) claims.get("id"); // 记录开始时间 long beginTime = System.currentTimeMillis(); // 执行原始方法 Object result = joinPoint.proceed(); // 记录结束时间 long endTime = System.currentTimeMillis(); long costTime = endTime - beginTime; // 记录操作日志 OperateLog operateLog = new OperateLog(); operateLog.setOperateUser(operateUser); operateLog.setOperateTime(LocalDateTime.now()); operateLog.setClassName(joinPoint.getTarget().getClass().getName()); operateLog.setMethodName(joinPoint.getSignature().getName()); operateLog.setMethodParams(Arrays.toString(joinPoint.getArgs())); operateLog.setReturnValue(JSONObject.toJSONString(result)); operateLog.setCostTime(costTime); operateLogMapper.insert(operateLog); log.info("操作日志记录:{}", operateLog); return result; } }

11. 系统安全防护策略

安全防护措施

  1. SQL注入防护:使用MyBatis预编译机制
  2. XSS攻击防护:Jackson全局HTML转义
  3. CSRF防护:Spring Security默认启用
  4. 数据脱敏:敏感字段加密存储
  5. 接口幂等性:Token机制防止重复提交

安全配置示例

@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/login").anonymous() .anyRequest().authenticated(); } }

12. 项目部署与性能优化

部署方案对比

部署方式启动速度资源占用适用场景
内嵌Tomcat开发测试环境
外置Tomcat传统部署环境
Docker容器化云原生环境

JVM调优参数

java -jar -Xms512m -Xmx1024m -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4 \ -XX:ConcGCThreads=2 tlias-web-management.jar

缓存优化方案

@Cacheable(value = "deptCache", key = "#id") public Dept getById(Integer id) { return deptMapper.getById(id); } @CacheEvict(value = "deptCache", key = "#dept.id") public void update(Dept dept) { deptMapper.update(dept); }

通过以上完整实现,我们构建了一个功能完善、安全可靠的智能学习辅助系统后端。系统采用模块化设计,各层职责明确,通过AOP实现了横切关注点的统一处理,利用SpringBoot的自动配置特性简化了开发流程,MyBatis提供了灵活的SQL控制能力,整体架构既保证了开发效率又确保了系统性能。

http://www.jsqmd.com/news/596918/

相关文章:

  • OpenClaw备份策略:保障SecGPT-14B长期任务数据不丢失
  • BongoCat:让你的桌面充满生命力的互动伙伴
  • 缩略图预加载工具:让Windows用户告别文件夹预览卡顿
  • 华硕笔记本合盖模式终极指南:外接显示器工作不断电
  • TensorFlow-v2.15从零开始:利用镜像快速搭建稳定高效的AI开发环境
  • mirrord 终极教程:如何将本地进程无缝接入 Kubernetes 集群的完整指南 [特殊字符]
  • 终极指南:如何使用Polly.JS实现API版本控制与路径重写
  • 如何实现NextFaster极致图片优化:Vercel Blob与边缘缓存实战指南
  • Duix-Mobile:下一代全离线AI数字人交互平台革命性突破移动端实时交互体验
  • 屏幕截图与录屏常见问题解决:从滚动截屏到带标注的视频录制
  • 解锁突破平台限制:res-downloader资源获取的创新解决方案
  • FanControl:智能调节风扇转速的创新方案
  • 书匠策AI:毕业论文写作的“智慧魔法棒”大揭秘
  • 如何在PS4上使用GoldHEN Cheats Manager实现游戏修改:终极完整指南
  • Windows电脑安装安卓APK的完整指南:告别模拟器的终极解决方案
  • 从‘单打独斗’到‘团队协作’:实战解析如何将DeepSeek的文本能力与Gemini的多模态API组合使用
  • PPP协议安全指南:为什么CHAP比PAP更安全?一次抓包分析带你搞懂认证过程
  • 3步打造你的智能游戏助手:ChampR让英雄联盟决策效率提升300%
  • OpenCV入门:Ubuntu系统下OpenCV的安装与环境配置
  • AI for Science:当语言学遇见人工智能,一场研究范式的革命
  • Batocera.linux主题定制完全指南:打造个性化游戏界面终极教程
  • 4位精度革命:alpaca.cpp如何让7B模型在本地高效运行
  • PaveBench:一个用于路面病害感知与交互式视觉语言分析的多功能基准
  • 如何永久保存微信聊天记录:WeChatMsg终极指南与数据守护方案
  • FuelUX模板系统终极指南:掌握Handlebars与Underscore的完整集成方案
  • G-Helper终极指南:颠覆性轻量级华硕笔记本性能控制解决方案
  • 原神抽卡模拟器:无需安装也能精准规划资源?浏览器端祈愿体验全解析
  • GitHub Actions缓存终极升级指南:从v3到v5的平滑迁移路径
  • Zabbix图形配置踩坑记:想把多台机器的CPU使用率放一张图里对比,我试了三种方法
  • 深度解密Win11Debloat:三大核心引擎重塑Windows系统性能体验