You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在/movies/{id}接口返回的Movie DTO中追加登录用户评分?

Got it, let's walk through how to add the logged-in user's rating to your /movies/{id} response—just like IMDB does. There are a few practical approaches you can pick from, depending on your project's structure and long-term needs:

方案1:创建扩展的DTO类(推荐长期维护)

This is the cleanest, most type-safe approach. You'll keep your original Movie class untouched, and create a new DTO that wraps it along with the user's rating:

// 原有的Movie类保持不变,专注于电影本身的核心信息
public class Movie {
    private final String title;
    private final MovieType type;
    private final List<LanguageType> languages;
    private final List<CountryType> countries;
    
    // 构造器、getters等方法
}

// 新的扩展DTO,专门用于返回带用户评分的电影信息
public class MovieWithUserRating {
    private final Movie movie;
    private final Integer userRating; // 用Integer可以兼容"未评分"的null场景

    public MovieWithUserRating(Movie movie, Integer userRating) {
        this.movie = movie;
        this.userRating = userRating;
    }

    // 对应的getter方法
}

Then in your controller, fetch the movie, query the user's rating, and assemble the response:

@GetMapping("/movies/{id}")
public ResponseEntity<MovieWithUserRating> getMovieWithUserRating(
        @PathVariable Long id,
        @AuthenticationPrincipal UserDetails currentUser) { // 用Spring Security获取当前登录用户

    // 1. 获取电影基础信息
    Movie movie = movieService.findById(id);
    if (movie == null) {
        return ResponseEntity.notFound().build();
    }

    // 2. 查询当前用户对该电影的评分(需要你实现对应的评分查询逻辑)
    Integer userRating = ratingService.getUserRating(currentUser.getUsername(), id);

    // 3. 组装并返回结果
    return ResponseEntity.ok(new MovieWithUserRating(movie, userRating));
}

Pros: 完全解耦电影核心数据和用户个性化数据,类型安全,后续扩展用户相关字段(比如是否收藏)非常方便。

方案2:动态扩展Movie对象(适合快速迭代)

If you don't want to create a new DTO class, you can use Jackson's annotations to dynamically add the rating field without modifying your core Movie class too much:

public class Movie {
    private final String title;
    private final MovieType type;
    private final List<LanguageType> languages;
    private final List<CountryType> countries;
    private Integer userRating; // 新增字段,注意调整构造器或添加setter

    // 原有构造器、getters
    @JsonAnyGetter
    public Map<String, Object> getAdditionalUserFields() {
        Map<String, Object> fields = new HashMap<>();
        if (userRating != null) {
            fields.put("userRating", userRating);
        }
        return fields;
    }
}

Then in your controller:

@GetMapping("/movies/{id}")
public ResponseEntity<Movie> getMovieWithUserRating(
        @PathVariable Long id,
        @AuthenticationPrincipal UserDetails currentUser) {

    Movie movie = movieService.findById(id);
    if (movie == null) {
        return ResponseEntity.notFound().build();
    }

    Integer userRating = ratingService.getUserRating(currentUser.getUsername(), id);
    movie.setUserRating(userRating); // 假设添加了setter方法

    return ResponseEntity.ok(movie);
}

Pros: 不用新增类,快速实现需求;Cons: 把用户个性化数据耦合到了核心电影实体里,长期维护会让Movie类职责变杂。

方案3:用通用响应包装器(适合有统一响应规范的项目)

If your project uses a standardized API response format, you can wrap the movie data and user rating in a generic response object:

// 通用API响应包装类
public class ApiResponse<T> {
    private T data;
    private Map<String, Object> metadata; // 存放用户评分这类元数据

    // 构造器、getters、setters
}

Controller implementation:

@GetMapping("/movies/{id}")
public ResponseEntity<ApiResponse<Movie>> getMovieWithUserRating(
        @PathVariable Long id,
        @AuthenticationPrincipal UserDetails currentUser) {

    Movie movie = movieService.findById(id);
    if (movie == null) {
        return ResponseEntity.notFound().build();
    }

    Integer userRating = ratingService.getUserRating(currentUser.getUsername(), id);
    Map<String, Object> metadata = new HashMap<>();
    metadata.put("userRating", userRating);

    ApiResponse<Movie> response = new ApiResponse<>();
    response.setData(movie);
    response.setMetadata(metadata);

    return ResponseEntity.ok(response);
}

Pros: 符合统一响应规范,把业务数据和用户元数据分离,结构清晰。

关键注意事项
  • 获取当前登录用户:如果用Spring Security,@AuthenticationPrincipal是最便捷的方式;如果是JWT认证,你可以从请求头解析token获取用户标识。
  • 性能优化:如果查询电影和评分是两次独立的DB请求,建议用JOIN查询或者批量查询来避免N+1性能问题。
  • 未评分场景:如果用户还没给电影评分,返回null或者约定的默认值(比如0),前端可以根据这个值展示"未评分"的状态。

内容的提问来源于stack exchange,提问作者JONKI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:52:46