gpt4 book ai didi

java - 用于方法多参数注入(inject)的自定义 InjectableProvider,解析错误

转载 作者:行者123 更新时间:2023-12-02 05:53:00 30 4
gpt4 key购买 nike

我很难找到一个漂亮而干净的方法来实现这个 JsonParamInjectable。我在这个论坛和其他地方进行了搜索,但没有找到任何提示可以告诉我如何干净利落地实现它。

对于 jaxrs 方法:

public Object add(
@JsonParam("a") int a,
@JsonParam("b") int b
)

它将 json {"a":1, "b":2} 解析为参数 a 和 b

为此,我实现了一个 InjectableProvider,它通过方法参数创建一个 JsonInjectable 实例。

@Provider
public class JsonParamProvider implements InjectableProvider<JsonParam, Type> {

private Gson gson;

public JsonParamProvider(@Context ServletConfig sc) throws Exception {
super();
this.gson = GsonFactory.newGson(sc);
}

@Override
public Injectable<Object> getInjectable(ComponentContext cc, JsonParam a, Type type) {
if (a.value() != null) {
String signature = cc.getAccesibleObject().toString();
return new JsonInjectable(signature, a, type, gson);
}
return null;
}

@Override
public ComponentScope getScope() {
return ComponentScope.Singleton;
}

魔法就在这个 JsonInjectable 中完成,而 id 在其中做了肮脏的把戏:

public class JsonInjectable extends AbstractHttpContextInjectable<Object> {

private final JsonParam param;
private final Type type;
private final String signature;
private final Gson gson;

private static ThreadLocal<WeakReference<HttpContext>> contextCache = new ThreadLocal<WeakReference<HttpContext>>(){
@Override
protected WeakReference<HttpContext> initialValue() {
return new WeakReference<HttpContext>(null);
}
};
private static ThreadLocal<WeakReference<JsonElement>> entityCache = new ThreadLocal<WeakReference<JsonElement>>(){
@Override
protected WeakReference<JsonElement> initialValue() {
return new WeakReference<JsonElement>(null);
}
};

public JsonInjectable(String signature, JsonParam param, Type type, Gson gson) {
this.signature = signature;
this.param = param;
this.type = type;
this.gson = gson;
}

@Override
public Object getValue(HttpContext context) {
try {
JsonElement methodJsonElement = entityCache.get().get();
HttpContext context2 = contextCache.get().get();
if (context != context2) {
contextCache.set(new WeakReference<HttpContext>(context));
String entity = context.getRequest().getEntity(String.class);
System.out.println("entity:"+entity);
JsonParser parser = new JsonParser();
methodJsonElement = parser.parse(entity);
entityCache.set(new WeakReference<JsonElement>(methodJsonElement));
}
if (methodJsonElement == null || methodJsonElement.isJsonNull()) {
return null;
}
final JsonElement valueJsonElement = ((JsonObject)methodJsonElement).get(this.param.value());
if (valueJsonElement == null || valueJsonElement.isJsonNull()) {
return null;
}
if (this.type.equals(java.lang.Integer.class)) {
Number number = valueJsonElement.getAsNumber();
return number.intValue();
}
if (this.type.equals(java.lang.String.class)) {
return valueJsonElement.getAsString();
}
Class<?> c = ((Class<?>) this.type);
if (int.class.equals(c)) {
return valueJsonElement.getAsInt();
}

//other parsing code...

//try with gson
return this.gson.fromJson(valueJsonElement, this.type);

} catch (RuntimeException e) {
throw e;
}
}

问题是,在某些情况下,我怀疑实体对于有效的 http 请求来说是空的。导致 java.io.EOFException: End of input at line 1 column 2。此问题在生产中出现,但我无法在测试环境中重现它。

如果有问题,肯定与“context != context2”有关。对于每个可注入(inject)项都绑定(bind)到一个参数,并且按我无法控制的顺序调用可注入(inject)项,并且每个可注入(inject)项都处理相同的数据:从请求实体解析的 json。因此,为了避免每次重新解析实体,我使用 context != context2 来检测它是否是新请求。

检测新请求的好方法是什么,这样每个请求只能进行 1 次 json 解析。

最佳答案

在我看来,你的方法太复杂了。所需要做的就是定义具有两个字段的 bean,并将其作为单个参数,其中两个字段由 json 填充。

public class TwoParams {
public int a;
public int b;
// instead of public fields you could do proper bean
// or even make immutable with final
}

public Object add(@JsonParam TwoParams params)
....

使用 Jackson 进行这样的映射非常简单,因此甚至不需要手动编写映射代码。如果您使用 Hibernate Validator,您可以添加注释来验证输入,而无需编写任何额外的代码。

关于java - 用于方法多参数注入(inject)的自定义 InjectableProvider,解析错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23368752/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com