我正在尝试在基于Spring的REST API中读取HTTP头。我跟着this。但是我收到了这个错误:
没有找到类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);
}
我尝试了@Context
:在这种情况下,HTTPHeader为null
。
如何从HTTP标头中获取值?
答案 0 :(得分:62)
您获得的错误似乎与 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为你带来了魔力;)
答案 1 :(得分:7)
我将举例说明如何读取控制器的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);
}
现在有很多代码在后台执行操作,所以我会为你分解它。
ResponseEntity是每个控制器返回的自定义对象。它包含一个允许创建新实例的静态工厂。我的数据服务是标准服务类。
魔术发生在幕后,因为你正在使用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只是com.fasterxml.jackson.databind.ObjectMapper
的扩展,是杰克逊用来将您的请求从JSON实际映射到对象的。
我怀疑你得到了你的异常,因为你没有指定一个可以将Octet-Stream读入对象的映射器,或者Spring可以处理的东西。如果您正在尝试进行文件上传,那么完全是另一回事。
所以我的请求被发送到我的控制器看起来像这样只是有一个名为dataId
的额外标题。
如果您想将其更改为请求参数并使用@RequestParam String dataId
从请求中读取ID,您的请求将类似于此:
contactId : {"fooId"}
此请求参数可以像您一样复杂。您可以将整个对象序列化为JSON,将其作为请求参数发送,然后Spring将其序列化(使用Jackson)返回到Java Object,供您使用。
控制器中的示例:
@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序列化到对象,而无需编写任何代码。您可以为@RequestParam
和@RequestBody
执行此操作,这样您就可以分别在参数或请求正文中访问JSON。
现在您已经有了一个具体的示例,一旦您将请求类型更改为application/json
,就不应该有任何问题。
答案 2 :(得分:1)
与其在每种方法中都使用HttpServletRequest
对象,而是通过构造函数进行自动装配,将其保留在控制器的上下文中。然后,您可以从控制器的所有方法进行访问。
public class OAuth2ClientController {
@Autowired
private OAuth2ClientService oAuth2ClientService;
private HttpServletRequest request;
@Autowired
public OAuth2ClientController(HttpServletRequest request) {
this.request = request;
}
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<String> createClient(@RequestBody OAuth2Client client) {
System.out.println(request.getRequestURI());
System.out.println(request.getHeader("Content-Type"));
return ResponseEntity.ok();
}
}