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ヘッダーから値を取得する方法は?
表示されるエラーは、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があなたのためにその魔法を行うからです;)
コントローラーの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は、すべてのコントローラーが返すカスタムオブジェクトです。新しいインスタンスを作成できる静的ファクトリーが含まれています。 My Data Serviceは標準のサービスクラスです。
魔法は舞台裏で発生します。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
の単なる拡張であり、Jacksonが実際にリクエストをJSONからオブジェクトにマッピングするために使用するものです。
オクテットストリームをオブジェクトに読み込むことができるマッパーまたはSpringが処理できるものを指定していないため、例外が発生していると思われます。ファイルをアップロードしようとしている場合、それはまったく別のことです。
そのため、コントローラーに送信されるリクエストには、dataId
というヘッダーが追加されているだけです。
これをリクエストパラメータに変更し、@RequestParam String dataId
を使用してリクエストからIDを読み取る場合、リクエストは次のようになります。
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オブジェクトに戻された後、使用可能な状態のコントローラーに渡されます。
ご覧のとおり、これは非常に強力であり、1行のコードを記述することなく、JSONからオブジェクトにデータをシリアル化できます。 @RequestParam
および@RequestBody
に対してこれを行うことができます。これにより、パラメーターまたはリクエストボディ内のJSONにそれぞれアクセスできます。
具体的な例を示したので、リクエストタイプをapplication/json
に変更しても問題はないはずです。