이 JsonParamInjectable을 구현하는 데는 훌륭하고 깨끗한 방법이 필요합니다. 나는이 포럼과 다른 곳에서 수색했지만 아무렇지도 않게 그것을 구현하는 법을 알려주는 힌트는 찾지 못했다. 내가 InjectableProvider을 구현하는 일이 들어 A와 B메소드 multi param injectable의 사용자 정의 InjectableProvider, 구문 분석 오류
를 param으로 대체
public Object add(
@JsonParam("a") int a,
@JsonParam("b") int b
)
그것이 JSON {1, "B"2 "A"를} 파싱하십시오 jaxrs의 방법
메소드 param에 의해 하나의 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 : 1 행 2 열의 입력 끝.이 문제는 프로덕션 환경에서 발생하지만 env 테스트에서이를 재현 할 수 없습니다.
문제가있는 경우 "context! = context2"와 반드시 관련이 있습니다. 각각의 주 사용 가능 인자는 param에 바인드되어 있고 주사 가능 인자는 제어 할 수없는 순서로 호출되며, 각각의 주 사용 가능 데이터는 요청 데이터에서 파싱 된 json입니다. 따라서 매번 엔티티를 다시 구문 분석하지 않으려면 context! = context2를 사용하여 새로운 요청인지 확인하십시오.
새 요청을 감지하는 훌륭하고 깨끗한 방법은 json 파싱이 요청 당 1 회만 발생할 수 있기 때문입니다.
내 접근 방식은 실제로 복잡하지만이 방식으로 제작하는 데 많은 코드가 있습니다. 변화를 만드는 것은 정말로 시간이 많이 걸릴 것입니다. 나는 그렇게 할 수있는 길을 찾았다. 나는 그렇게 생각한다. 그것은 내 junit 테스트를 통과하므로, 생산을 통과한다면, 여기에 게시하십시오. – sstlaurent
코드를 다시 보면 WeakReference를 사용하는 것이 문제가 될 수 있습니다. JVM의 메모리가 부족하고 GC가 첫 번째와 두 번째 매개 변수를 가져 오는 사이에 null을 반환하게되는 경우입니다. 이것은 매우 간헐적이며 대부분 바쁜 서버에서 발생합니다. 다음 요청이 덮어 쓸 때까지 마지막 객체를 유지할 수있는 일반 참조를 사용할 수는 있지만, 그렇게 크지 않은 경우에는 매우 추한 빠른 수정이 될 수 있습니다. – Swav