在Spring REST控制器中读取HTTP头

Ash*_*i K 31 java rest spring spring-restcontroller spring-rest

我试图在基于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);
}
Run Code Online (Sandbox Code Playgroud)

我试过了@Context:HTTPHeader是null这种情况.

如何从HTTP标头获取值?

Már*_*des 66

您获得的错误似乎与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
}
Run Code Online (Sandbox Code Playgroud)

你的REST类应该有如下注释:

@Controller
@RequestMapping("/rest/")
Run Code Online (Sandbox Code Playgroud)


关于实际问题,获取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");
}
Run Code Online (Sandbox Code Playgroud)

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


Jam*_*ENL 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);
    }
Run Code Online (Sandbox Code Playgroud)

现在有很多代码在后台执行操作,所以我会为你分解它.

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>
Run Code Online (Sandbox Code Playgroud)

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

我怀疑你得到了你的异常,因为你没有指定一个可以将Octet-Stream读入对象的映射器,或者Spring可以处理的东西.如果您正在尝试进行文件上传,那么完全不同.

所以我的请求被发送到我的控制器看起来像这样只是有一个额外的标题调用dataId.

如果您想将其更改为请求参数并使用@RequestParam String dataId从请求中读取ID,您的请求将类似于以下内容:

contactId : {"fooId"} 
Run Code Online (Sandbox Code Playgroud)

此请求参数可以像您一样复杂.您可以将整个对象序列化为JSON,将其作为请求参数发送,然后Spring将其序列化(使用Jackson)返回到Java Object,供您使用.

控制器中的示例:

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

发送请求:

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"
}
Run Code Online (Sandbox Code Playgroud)

在被提供给控制器准备供我使用之前,它会自动序列化回DataProcessingRequestDTO对象.

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

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


iam*_*der 7

不要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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 获取标头而不用使用代码生成在 swagger 定义中声明它们非常有用。谢谢 (3认同)