3

パラメータ化された取得(別名検索)を実行しようとしています。なぜこれが機能しないのかわかりません。最新の jersey 依存関係 (1.14) を使用しており、これまでのところ、すべての REST インターフェイスは問題なく機能していました。単純な REST:

@Path("/some/path")
@Component
public class SomeRest {

    @GET
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Produces({ MediaType.APPLICATION_JSON })
    public Response getAll(MultivaluedMap<String, String> queryParams) {

        // extract params, do search, return response as JSON
        // (Using ObjectMapper.writeValue() to convert object to JSON String)

    }
}

メソッドの動作は重要ではないと思います。エラーには、サポートされていないメディアタイプが原因で最初に入力できないことが明確に示されているためです (ブラウザーにパスを入力すると)。

HTTP Status 415 - Unsupported Media Type

出力は次のとおりです。

SEVERE: A message body reader for Java class javax.ws.rs.core.MultivaluedMap, and Java type javax.ws.rs.core.MultivaluedMap<java.lang.String, java.lang.String>, and MIME media type application/octet-stream was not found.
The registered message body readers compatible with the MIME media type are:
....

誰にもアイデアがありますか?ありがとう!

編集:

私の目標は、GET リソースでクエリ パラメータを使用して検索を実装することです。そのため、呼び出す/some/pathとすべての結果が得られますが、呼び出すsome/path?limit=10&offset=10と2番目の10セットが得られます。クエリパラメーターでその特定の問題を解決できますが、name = fooなどのwhere句のパラメーターを同じように定義できるようにしたいと考えていますパラメータ マップ。そして、GET 呼び出しでパラメーターの任意のマップを取得できる汎用 getAll メソッドを作成したいので、これらのパラメーターは動的でなければなりません。

だから私が推測する質問は、動的クエリパラメーターをどのように実装するのですか?

4

3 に答える 3

3

実際の URL にあるクエリ パラメータを混乱させていると思います。

someurl/resource?param1=value1¶m2=value2

フォーム URL エンコードされた情報は同じ形式ですが、パラメーターは本文にあります。GET リクエストは本文を取らないため、POST を実行するか、x-www-form-urlencoded の代わりにクエリ パラメータを使用することを意味します。

幸運を!

編集:

入ってくるパラメーターが正確にわかっている場合は @QueryParam を使用し、URL で予想されるクエリパラメーターの数/種類がわからない場合は @Context UriInfo を使用します。

于 2012-09-20T13:38:32.607 に答える
0

より複雑な問題の解決策を書きます: map GET params throw MultivaluedMap to Object. 他の人に役立つかもしれません。

GET クエリは、サーバーとチャットするための非常に簡単な方法です。ブラウザーの URL コントロールを使用する非プログラマーでも、単純な API タスクを実行できます。

ただし、「get」クエリからオブジェクトを作成する方法はお勧めしません (理由の 1 つは、シンボルの最大制限が 4000 であることです)。

GET クエリには、デフォルトで MediaType.APPLICATION_OCTET_STREAM があります。

// GOAL: create simple in use API (for non-programmers) to call rest service to test functional. User can use any business object field.
//      So need map GET query params to server business object.

// Create Provider and save it in jersey rest folder (for auto detect).
// 
// PROBLEM: "get" query hasn't body and query params don't available get from readFrom prodiver method
//          So use uriInfo for getting query params 

@Provider
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
public class GETQueryMapperProvider<T> implements MessageBodyReader<T> {
    //[!!!] MAIN PART: save the uri
    @Context
    private UriInfo uriInfo;

    @Override
    public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public T readFrom(Class<T> tClass, Type type, Annotation[] annotations, MediaType mediaType,
                      MultivaluedMap<String, String> stringStringMultivaluedMap,
                      InputStream inputStream) throws IOException, WebApplicationException {
        MultivaluedMap queryParams = uriInfo.getQueryParameters();
        //create from Map Object
        return ServiceUtils.convertMapToObject(queryParams, tClass);
    }
}

そして2番目の部分の解決策:

public static <T> T convertMapToObject(Map map, Class<T> objectClass) {
    try {
        //[!!!] MAIN PART - MultivaluedMap for each value create list. 
        //But we list only for fields with collection type, for other need take first value. 
        map = fixCollectionsValue(map, objectClass);

        ObjectMapper ob = new ObjectMapper();
        StringWriter json = new StringWriter();
        ob.writeValue(json, map);

        return ob.readValue(json.toString(), objectClass);
    } catch (IOException e) {
        log.error(e.getMessage(), e);
    }
    return null;
}
protected static Map fixCollectionsValue(Map map, Class objectClass) {
    Map newMap = new HashMap(map);
    for(Field field : objectClass.getDeclaredFields()) {
        if(!Modifier.isStatic(field.getModifiers())
                &&!Modifier.isFinal(field.getModifiers())) {
            String name = field.getName();
            Object value = map.get(name);
            Object newValue = value;
            if(value != null) {
                if(isCollectionClass(field.getType())) {
                    if(!isCollectionClass(value.getClass())) {
                        newValue = new ArrayList();
                        ((ArrayList) newValue).add(value);
                        newMap.put(name, newValue);
                    }
                } else {
                    if(isCollectionClass(value.getClass())) {
                        //take first value to our object
                        newValue = ((Collection) newValue).iterator().next();
                        newMap.put(name, newValue);
                    }
                }
            }
        }
    }
    return newMap;
}
protected static boolean isCollectionClass(Class clazz) {
    return clazz.isArray() ||
           Collection.class.isAssignableFrom(clazz);
}
于 2013-02-13T16:29:38.500 に答える
0

@GETJAX-RSからのものです。GET リクエストに本文を含めないでください。で同じ例を試してください@POST

于 2012-09-20T13:35:49.030 に答える