使用 Java 在响应实体(Spring Boot)中设置 Content-Length 标头

问题描述 投票:0回答:2

我想根据需要将内容长度响应标头设置为我的控制器之一。在参考这两个问题(FirstSecond)之后,我可以理解设置响应头是至关重要的。但是,我确实需要这个。我的代码片段如下,

@GetMapping(value = /employees, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String, List<Object>>> getEmployeeDetails(@RequestParam(value = "organization_id", required = false) Integer orgId) {

      Map<String, List<Object>> responseMap = //some method returns the data
      ObjectMapper objMapper = new ObjectMapper();
      String responseString = objMapper.writeValueAsString(responseMap);
      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(responseString.length()));
      return ResponseEntity.ok().headers(httpHeaders).body(responseMap);
}

在上述情况下,Content-Length计算不正确,响应json被收缩。 (即,如果地图包含 50 个对象,则响应会在中间某处缩小)

请帮忙如何达到预期的结果。预先感谢。

java json spring-boot spring-mvc
2个回答
1
投票

我对上面链接的问题之一的答案做了一些修改。下面的代码为我提供了内容长度标头的正确值,并且我的响应 json 已完全提供。

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
@RequestMapping("/rest")
public class EmployeeController {
    @GetMapping(value = /employees, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Map<String, List<Object>>> getEmployeeDetails(@RequestParam(value = "organization_id", required = false) Integer orgId) throws IOException {
        Map<String, List<Object>> responseMap = //some method returns the data
        ObjectMapper objMapper = new ObjectMapper();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        //getFactory() and createJsonGenerator() methods are deprecated
        JsonGenerator jsonGenerator = objMapper.getFactory().createGenerator(byteArrayOutputStream);
        objMapper.writeValue(jsonGenerator, responseMap);
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(HttpHeaders.CONTENT_LENGTH,String.valueOf(byteArrayOutputStream.size()));
        return ResponseEntity.ok().headers(httpHeaders).body(responseMap);
    }
}

0
投票

您的代码可以通过做两件事来改进:

  • 从应用程序上下文中使用
    ObjectMapper
  • 使用自定义非分配
    OutputStream
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
@RequestMapping("/rest")
public class EmployeeController {
    @Autowired
    private ObjectMapper objMapper;

    @GetMapping(value = /employees, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Map<String, List<Object>>> getEmployeeDetails(@RequestParam(value = "organization_id", required = false) Integer orgId) throws IOException {
        Map<String, List<Object>> responseMap = //some method returns the data

        var countingOutputStream = new CountingOutputStream();
        objMapper.writeValue(countingOutputStream, responseMap);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(HttpHeaders.CONTENT_LENGTH,String.valueOf(countingOutputStream.count));
        return ResponseEntity.ok().headers(httpHeaders).body(responseMap);
    }
}

private static class CountingOutputStream extends OutputStream {
    private int count;

    @Override
    public void write(int b) {
        count++;
    }

    @Override
    public void write(byte[] b) {
        count += b.length;
    }

    @Override
    public void write(byte[] b, int off, int len) {
        count += b.length;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.