个人技术总结——Spring Boot RESTful

222200115吴俊斌 2024-12-20 23:34:16
这个作业属于哪个课程FZU_SE_teacherW_4
这个作业要求在哪里软件工程实践总结&个人技术博客
这个作业的目标个人技术总结
其他参考文献<<构建之法>>

目录

  • 1.技术概述
  • 2.技术详述
  • 3.遇到的问题与解决方案
  • 4.总结
  • 5.参考文献

1.技术概述

  • 技术用途:
    Spring Boot提供了RESTful API,其具有的快速开发能力,能够轻松实现前后端的交互,使得开发人员可以快速搭建基于Spring的Web应用。

2.技术详述

  • 首先在Repository层定义接口。
@Repository
public interface ExerciseRecordRepository extends JpaRepository<ExerciseRecord, String> {
  // 获取指定用户最新的运动记录
  Optional<ExerciseRecord> findTopByUserIdOrderByExerciseIdDesc(String userId);

  // 获取指定用户的所有记录,按开始时间降序排列
  List<ExerciseRecord> findByUserIdOrderByStartTimeDesc(String userId);

 // 查询指定时间段内的运动记录
  List<ExerciseRecord> findByUserIdAndStartTimeBetween(String userId, Date startDate, Date today);
}
  • 之后在Controller层提供映射接口。
@RestController
@RequestMapping("/api/exercise-records")
public class ExerciseRecordController {
  @Autowired
  private ExerciseRecordRepository exerciseRecordRepository;

  // 获取用户的所有运动记录
  @GetMapping
  public List<ExerciseRecord> getAllExerciseRecords(@RequestParam String userId) {
    return exerciseRecordRepository.findByUserIdOrderByStartTimeDesc(userId);
  }

  // 获取指定用户最新的运动记录
  @GetMapping("/latest")
  public ResponseEntity<ExerciseRecord> getLatestExerciseRecord(@RequestParam String userId) {
    Optional<ExerciseRecord> latestRecord = exerciseRecordRepository.findTopByUserIdOrderByExerciseIdDesc(userId);
    return latestRecord.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.noContent().build());
  }

  // 获取一段时间内的消耗热量,按运动种类分类
  @SuppressWarnings("deprecation")
  @GetMapping("/total-calories")
  public ResponseEntity<?> getTotalCalories(@RequestParam String userId, @RequestParam String period) {
    // period:"today","week","month","year"
    Date today = new Date();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(today);

    Date startDate;
    switch (period) {
      case "week":
        startDate = getStartOfWeek(today);
        break;
      case "month":
        startDate = getStartOfMonth(today);
        break;
      case "year":
        startDate = getStartOfYear(today);
        break;
      case "today":
      default:
        startDate = getStartOfDay(today);
        break;
    }

    List<ExerciseRecord> records = exerciseRecordRepository.findByUserIdAndStartTimeBetween(userId, startDate,
        today);

    // 计算一段时间内运动消耗的热量...代码较长省略...
  }
  • 在前端View层调用接口,通过HTTP/AJAX请求接口获取数据并进行渲染。
    function fetchCaloriesData(period) {
      fetch(`/api/exercise-records/total-calories?userId=${userId}&period=${period}`)
        .then(response => response.json())
        .then(data => {
          // 构造图表所需的数据
          const labels = Object.keys(data);
          const values = Object.values(data);

          // 绘制图表
          drawChartCalories(labels, values);
        })
        .catch(error => console.error("获取数据失败:", error));
    }

    // 查看历史运动记录
    function viewHistory() {
      if (isViewHistory === false) {
        fetch(`/api/exercise-records?userId=${userId}`)
          .then(response => response.json())
          .then(data => {
            let tableHTML = `<table>
                        <tr>
                          <th>运动类型</th>
                          <th>运动时长/分钟</th>
                          <th>运动距离/公里</th>
                          <th>消耗卡路里/千卡</th>
                          <th>开始时间</th>
                          <th>结束时间</th>
                        </tr>`;
            data.forEach(record => {
              tableHTML += `<tr>
                        <td>${record.type}</td>
                        <td>${formatDuration(record.duration)}</td>
                        <td>${record.distance}</td>
                        <td>${record.calories}</td>
                        <td>${new Date(record.startTime).toLocaleString()}</td>
                        <td>${record.endTime ? new Date(record.endTime).toLocaleString() : '进行中'}</td>
                      </tr>`;
            });
            tableHTML += '</table>';
            document.getElementById('history').innerHTML = tableHTML;
            document.getElementById('history').style.display = 'block'; // 显示历史记录
          });
        isViewHistory = true;
        document.getElementById('viewHistoryButton').textContent = '隐藏历史记录';
      }
      else {
        document.getElementById('history').style.display = 'none'; // 隐藏历史记录
        isViewHistory = false;
        document.getElementById('viewHistoryButton').textContent = '查看历史记录';
      }
    }
}

3.遇到的问题与解决方案

  • 问题1:数据查询效率低
    在 getAllExerciseRecords 和 getLatestExerciseRecord 接口中,直接查询数据库中的全部记录或最新记录,随着数据量的增加,查询时间变长,性能下降。
  • 解决方案:
    在数据库中为查询字段(如 userId 和 startTime)建立索引,提高查询效率。
    使用分页技术,在查询用户所有记录时,限制返回的记录数量,并允许前端通过分页请求获取数据:
@GetMapping
public Page<ExerciseRecord> getAllExerciseRecords(
    @RequestParam String userId, 
    @RequestParam int page, 
    @RequestParam int size
) {
    Pageable pageable = PageRequest.of(page, size, Sort.by("startTime").descending());
    return exerciseRecordRepository.findByUserId(userId, pageable);
}
  • 问题2:前端数据展示性能问题
    前端在展示历史记录时,直接加载所有数据可能导致页面卡顿或崩溃。
  • 解决方案:
    分页加载: 修改前端调用接口时传递分页参数。
    后端返回分页结果,前端实现“加载更多”功能。
fetch(`/api/exercise-records?userId=${userId}&page=${currentPage}&size=${pageSize}`)

4.总结

Spring Boot 提供了自动化配置和快速开发能力,配合 JpaRepository 实现复杂查询逻辑,简化了代码
接口设计。
合理设计 RESTful API 的路径和数据格式,不仅让接口更清晰,还提高了前后端协作的效率。

5.参考文献

...全文
199 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

239

社区成员

发帖
与我相关
我的任务
社区管理员
  • FZU_SE_teacherW
  • 202501福大-软件工程实践-W班
  • D's Honey
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧