个人技术总结——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.参考文献

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

239

社区成员

发帖
与我相关
我的任务
社区管理员
  • FZU_SE_teacherW
  • 助教赖晋松
  • D's Honey
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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