学习进度条

在最近的团队项目中,我负责了用户登录和设备管理模块的开发工作。通过这次实践,我深入学习了Spring Boot框架及相关技术的应用,下面将详细介绍我所用到的技术点和实现方案。

项目技术栈概览

  • 后端框架:Spring Boot 3.x
  • 持久层:MyBatis + MyBatis Dynamic SQL
  • 数据库:MySQL
  • 安全认证:JWT (JSON Web Token)
  • 数据校验:Jakarta Validation
  • Excel处理:Apache POI
  • 密码加密:MD5

核心功能实现

1. 统一响应格式设计

项目中设计了Result类作为统一的API响应格式:

public class Result<T> {
    private Integer code; // 0失败,1成功
    private String message; // 提示错误信息
    private T data; // 数据

    // 成功静态方法
    public static <T> Result<T> success(T data) {
        return new Result<>(1, "success", data);
    }
    
    // 失败静态方法
    public static <T> Result<T> error(String message) {
        return new Result<>(0, "操作失败" + message, null);
    }
}

这种设计使得前端处理响应更加统一,便于错误处理和数据处理。

2. 用户认证与JWT集成

登录流程实现

@PostMapping("/login")
public Result<String> login(@RequestBody @Validated LoginRequest loginRequest) {
    User loginUser = userMapper.findByUsername(loginRequest.getUsername());
    if(loginUser == null) {
        return Result.error("用户名错误");
    }
    if(Md5Util.getMD5String(loginRequest.getPassword()).equals(loginUser.getPassword())){
        Map<String,Object> claims = new HashMap<>();
        claims.put("username",loginUser.getUsername());
        claims.put("password",loginUser.getPassword());
        String token = JwtUtil.genToken(claims);
        return Result.success(token);
    }
    return Result.error("密码错误");
}

关键技术点:

  • 使用@Validated进行请求参数校验
  • 密码采用MD5加密存储和验证
  • JWT生成包含用户基本信息的token
  • 使用ThreadLocal存储当前用户信息

密码修改功能

@PostMapping("/updatePwd")
public Result updatePwd(@RequestBody Map<String, String> params) {
    // 参数校验
    String oldPwd = params.get("old_pwd");
    String newPwd = params.get("new_pwd");
    String rePwd = params.get("re_pwd");

    // 获取当前用户
    Map<String, Object> map = ThreadLocalUtil.get();
    String username = map.get("username").toString();
    User loginUser = userMapper.findByUsername(username);

    // 验证原密码
    if (!loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd))) {
        return Result.error("原密码填写不正确");
    }

    // 更新密码
    String md5NewPwd = Md5Util.getMD5String(newPwd);
    userMapper.updatePwd(md5NewPwd, loginUser.getId());
    return Result.success();
}

3. 设备管理核心功能

设备实体类设计

@Entity
@Table(name = "device", uniqueConstraints = {
    @UniqueConstraint(columnNames = "device_code", name = "idx_device_code")
})
public class Device {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "device_code", length = 64, nullable = false)
    private String deviceCode;
    
    @Column(name = "device_name", length = 128, nullable = false)
    private String deviceName;
    
    // 其他字段...
}

使用JPA注解定义实体与表的映射关系,包括唯一约束、字段长度等。

分页查询实现

@GetMapping
public Result<PageBean<Device>> list(Integer pageNum, Integer pageSize,
                                   @RequestParam(required = false) String deviceCode,
                                   @RequestParam(required = false) String deviceType,
                                   @RequestParam(required = false) String deviceName,
                                   @RequestParam(required = false) String status) {
    PageBean<Device> pb = deviceMapper.list(pageNum,pageSize,deviceCode,deviceType,deviceName,status);
    return Result.success(pb);
}

分页核心类

public class PageBean<T> {
    private Long total; // 总条数
    private List<T> items; // 当前页数据集合
}

MyBatis动态SQL实现

class DeviceSqlProvider {
    public String selectByCondition(...) {
        return new SQL() {{
            SELECT("*");
            FROM("device");
            if (deviceCode != null && !deviceCode.isEmpty()) {
                WHERE("device_code LIKE CONCAT('%', #{deviceCode}, '%')");
            }
            // 其他条件...
            ORDER_BY("id DESC");
        }}.toString() + " LIMIT #{offset}, #{pageSize}";
    }
}

设备导入导出功能

Excel导入

@PostMapping("/import")
public Result<String> importDevices(@RequestParam("file") MultipartFile file) {
    // 验证文件类型
    if (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls")) {
        return Result.error("只支持Excel文件(.xlsx, .xls)");
    }
    
    // 解析Excel
    List<Device> devices = ExcelUtil.importExcel(file.getInputStream(), Device.class);
    
    // 批量插入
    int result = deviceMapper.batchInsert(devices);
    return Result.success("成功导入" + result + "条数据");
}

模板下载

@GetMapping("/template")
public ResponseEntity<InputStreamResource> downloadTemplate() throws IOException {
    ClassPathResource resource = new ClassPathResource("templates/device_template.xlsx");
    return ResponseEntity.ok()
            .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
            .header("Content-Disposition", "attachment; filename=device_template.xlsx")
            .body(new InputStreamResource(resource.getInputStream()));
}

关键技术点总结

  1. MyBatis动态SQL:使用@SelectProvider实现复杂条件查询,避免SQL注入风险
  2. 分页查询优化:计算总数和分页数据分离,提高查询效率
  3. JWT认证:无状态认证机制,适合分布式系统
  4. Excel处理:使用Apache POI实现数据的导入导出
  5. RESTful API设计:规范的URL设计和HTTP状态码使用
  6. 参数校验:使用@Validated@Pattern进行输入验证
  7. CORS处理:通过@CrossOrigin解决跨域问题

学习收获

通过这个项目,我深入理解了以下知识点:

  1. Spring Boot的自动配置原理
  2. MyBatis的Mapper接口与XML映射的多种写法
  3. JWT的工作机制及在Spring中的集成
  4. 分页查询的性能优化技巧
  5. Excel文件处理的常见问题及解决方案
  6. REST API设计的最佳实践

后续优化方向

  1. 引入Redis缓存高频访问的设备数据
  2. 实现更精细化的权限控制
  3. 添加操作日志记录功能
  4. 优化Excel导入的性能,支持大数据量导入
  5. 增加Swagger API文档支持

这个项目让我对Spring Boot生态有了更深入的理解,特别是在数据持久化和API设计方面积累了宝贵经验。希望这篇总结能对其他开发者有所帮助。


学习进度条
今日所花时间:3小时
今日代码量:约300行
博客量:1篇
了解到的知识点:

  • MyBatis动态SQL的高级用法
  • JWT在Spring Boot中的完整实现
  • Excel导入导出的服务端处理
  • 复杂分页查询的优化技巧
posted @ 2025-05-12 20:25  haoyinuo  阅读(12)  评论(0)    收藏  举报