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

如何在Spring Rest Controller中动态设置produces值?

Got it, let's tackle this problem where you need a single Spring Boot endpoint to either return a regular API response or trigger a file download, depending on the apiResponseType parameter. Here are a few practical approaches to dynamically handle the produces value and response behavior:


Approach 1: Use ResponseEntity with Dynamic Content Type

You can declare multiple allowed media types in the produces attribute of @GetMapping, then switch the response details based on your parameter. This keeps your code aligned with Spring's standard response patterns.

import org.springframework.http.*;
import org.springframework.core.io.ByteArrayResource;
import java.nio.charset.StandardCharsets;

@GetMapping(value = "/download", produces = {MediaType.APPLICATION_JSON_VALUE, "text/csv"})
public ResponseEntity<?> downloadFile(
    @RequestParam(value = "apiResponseType", required = true) String apiResponseType)
    throws IOException {

    if ("FILE".equals(apiResponseType)) {
        String FILE_HEADER = "id,firstName,lastName,gender,age";
        byte[] fileContent = FILE_HEADER.getBytes(StandardCharsets.UTF_8);
        ByteArrayResource resource = new ByteArrayResource(fileContent);

        // Set headers for file download
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("text/csv"));
        headers.setContentDisposition(ContentDisposition.attachment()
            .filename("user-data.csv")
            .build());

        return ResponseEntity.ok()
            .headers(headers)
            .body(resource);
    } else {
        // Return your regular API response (e.g., ValidationResponse)
        ValidationResponse response = new ValidationResponse();
        response.setStatus("SUCCESS");
        response.setMessage("Returning standard API response");
        return ResponseEntity.ok(response);
    }
}
  • The produces attribute lists all valid response types your endpoint can return (JSON and CSV here).
  • For the file case, we explicitly set the Content-Disposition header to trigger a download, and set the correct media type for the file.
  • For non-file cases, we return your standard JSON response as usual.

Approach 2: Directly Manipulate HttpServletResponse (More Flexible)

If you want full control without restricting media types upfront, you can bypass ResponseEntity and work directly with HttpServletResponse. This is great for highly dynamic scenarios.

import org.springframework.http.MediaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;

@GetMapping("/download")
public void downloadFile(
    @RequestParam(value = "apiResponseType", required = true) String apiResponseType,
    HttpServletResponse response) throws IOException {

    if ("FILE".equals(apiResponseType)) {
        String FILE_HEADER = "id,firstName,lastName,gender,age";
        
        // Configure download headers
        response.setContentType("text/csv");
        response.setHeader("Content-Disposition", "attachment; filename=\"user-data.csv\"");
        
        // Write file content to response stream
        try (OutputStream os = response.getOutputStream()) {
            os.write(FILE_HEADER.getBytes(StandardCharsets.UTF_8));
            os.flush();
        }
    } else {
        // Return JSON response
        ValidationResponse validationResponse = new ValidationResponse();
        validationResponse.setStatus("SUCCESS");
        
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getOutputStream(), validationResponse);
    }
}
  • No produces attribute needed here—you set the content type and headers dynamically at runtime.
  • Just make sure to handle the output stream safely (using try-with-resources to avoid leaks).

Approach 3: Use MediaType.ALL_VALUE for Maximum Flexibility

If you don't want to predefine allowed media types, set produces = MediaType.ALL_VALUE to let Spring accept any request, then explicitly set the content type in your response:

@GetMapping(value = "/download", produces = MediaType.ALL_VALUE)
public ResponseEntity<?> downloadFile(
    @RequestParam(value = "apiResponseType", required = true) String apiResponseType)
    throws IOException {

    if ("FILE".equals(apiResponseType)) {
        String FILE_HEADER = "id,firstName,lastName,gender,age";
        ByteArrayResource resource = new ByteArrayResource(FILE_HEADER.getBytes(StandardCharsets.UTF_8));

        return ResponseEntity.ok()
            .contentType(MediaType.parseMediaType("text/csv"))
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"user-data.csv\"")
            .body(resource);
    } else {
        ValidationResponse response = new ValidationResponse();
        response.setStatus("SUCCESS");
        return ResponseEntity.ok()
            .contentType(MediaType.APPLICATION_JSON)
            .body(response);
    }
}

This is a middle ground between the first two approaches—flexible but still using Spring's ResponseEntity pattern.


Pro Tip

Don't forget to add validation for the apiResponseType parameter (e.g., check that it's either "FILE" or your expected value for API responses) to avoid unexpected behavior.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:28:50