读取 Spring REST 控制器中的 HTTP 标头

我正在尝试在基于Spring的REST API中读取HTTP标头。我跟着这个。但是我收到此错误:

未找到类 java.lang.String、
ContentType: application/octet-stream 的消息正文读取器

我是Java和Spring的新手,所以无法弄清楚这一点。

这是我的调用的样子:

@WebService(serviceName = "common")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public interface CommonApiService {

    @GET
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/data")
    public ResponseEntity<Data> getData(@RequestHeader(value="User-Agent") String userAgent, @DefaultValue ("") @QueryParam("ID") String id);
}

我已经试过了:HTTPHeader就是在这种情况下。@Contextnull

如何从HTTP标头中获取值?


答案 1

您收到的错误似乎与 RequestHeader 无关。

而且你似乎混淆了Spring REST服务与JAX-RS,你的方法签名应该是这样的:

@RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "data")
@ResponseBody
public ResponseEntity<Data> getData(@RequestHeader(value="User-Agent") String userAgent, @RequestParam(value = "ID", defaultValue = "") String id) {
    // your code goes here
}

你的 REST 类应该有这样的注释:

@Controller
@RequestMapping("/rest/")


关于实际问题,获取HTTP标头的另一种方法是将HttpServletRequest插入到您的方法中,然后从那里获取所需的标头。

例:

@RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "data")
@ResponseBody
public ResponseEntity<Data> getData(HttpServletRequest request, @RequestParam(value = "ID", defaultValue = "") String id) {
    String userAgent = request.getHeader("user-agent");
}

不要担心注入HttpServletRequest,因为Spring为你做了这个魔术;)


答案 2

我将给你一个示例,说明我如何为控制器读取 REST 标头。我的控制器只接受 application/json 作为请求类型,如果我有需要读取的数据。我怀疑你的问题是你有一个应用程序/八位字节流,Spring不知道如何处理。

通常,我的控制器如下所示:

@Controller
public class FooController {
    @Autowired
    private DataService dataService;

    @RequestMapping(value="/foo/", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Data> getData(@RequestHeader String dataId){
        return ResponseEntity.newInstance(dataService.getData(dataId);
    }

现在有很多代码在后台做一些事情,所以我会为你分解它。

响应实体是每个控制器返回的自定义对象。它包含一个允许创建新实例的静态工厂。我的数据服务是一个标准服务类。

魔术发生在幕后,因为你正在使用JSON,你需要告诉Spring使用Jackson来映射HttpRequest对象,以便它知道你正在处理什么。

您可以通过在配置块中指定此项来执行此操作<mvc:annotation-driven>

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="objectMapper" />
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

ObjectMapper只是Jackson用来将JSON的请求实际映射到对象的扩展。com.fasterxml.jackson.databind.ObjectMapper

我怀疑你得到了你的例外,因为你还没有指定一个映射器,可以将八位字节流读入一个对象,或者Spring可以处理的东西。如果您尝试进行文件上传,那完全是另一回事。

因此,发送到我的控制器的请求看起来就像这样,只是有一个名为.dataId

如果要将其更改为请求参数,并用于从请求中读取 ID,则您的请求将如下所示:@RequestParam String dataId

contactId : {"fooId"} 

此请求参数可以根据需要尽可能复杂。您可以将整个对象序列化为JSON,将其作为请求参数发送,Spring会将其序列化(使用Jackson)回准备使用的Java对象。

控制器中的示例:

@RequestMapping(value = "/penguin Details/", method = RequestMethod.GET)
@ResponseBody
public DataProcessingResponseDTO<Pengin> getPenguinDetailsFromList(
        @RequestParam DataProcessingRequestDTO jsonPenguinRequestDTO)

请求已发送:

jsonPengiunRequestDTO: {
    "draw": 1,
    "columns": [
        {
            "data": {
                "_": "toAddress",
                "header": "toAddress"
            },
            "name": "toAddress",
            "searchable": true,
            "orderable": true,
            "search": {
                "value": "",
                "regex": false
            }
        },
        {
            "data": {
                "_": "fromAddress",
                "header": "fromAddress"
            },
            "name": "fromAddress",
            "searchable": true,
            "orderable": true,
            "search": {
                "value": "",
                "regex": false
            }
        },
        {
            "data": {
                "_": "customerCampaignId",
                "header": "customerCampaignId"
            },
            "name": "customerCampaignId",
            "searchable": true,
            "orderable": true,
            "search": {
                "value": "",
                "regex": false
            }
        },
        {
            "data": {
                "_": "penguinId",
                "header": "penguinId"
            },
            "name": "penguinId",
            "searchable": false,
            "orderable": true,
            "search": {
                "value": "",
                "regex": false
            }
        },
        {
            "data": {
                "_": "validpenguin",
                "header": "validpenguin"
            },
            "name": "validpenguin",
            "searchable": true,
            "orderable": true,
            "search": {
                "value": "",
                "regex": false
            }
        },
        {
            "data": {
                "_": "",
                "header": ""
            },
            "name": "",
            "searchable": false,
            "orderable": false,
            "search": {
                "value": "",
                "regex": false
            }
        }
    ],
    "order": [
        {
            "column": 0,
            "dir": "asc"
        }
    ],
    "start": 0,
    "length": 10,
    "search": {
        "value": "",
        "regex": false
    },
    "objectId": "30"
}

它会自动序列化回DataProcessingRequestDTO对象,然后提供给控制器准备供我使用。

如您所见,此功能非常强大,允许您将数据从 JSON 序列化为对象,而无需编写任何代码。您可以为 和 执行此操作,从而分别在参数或请求正文中访问 JSON。@RequestParam@RequestBody

现在您已经有了一个具体的示例,一旦您将请求类型更改为 .,您就不应该有任何问题了。application/json