|
|
@@ -0,0 +1,141 @@
|
|
|
+package cn.seecoder.codejudge.client;
|
|
|
+
|
|
|
+import cn.seecoder.bok.client.SeecoderBokConstants;
|
|
|
+import cn.seecoder.bok.client.SeecoderBokException;
|
|
|
+import cn.seecoder.bok.common.vo.QuestionVO;
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+import com.fasterxml.jackson.core.type.TypeReference;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fasterxml.jackson.databind.json.JsonMapper;
|
|
|
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
|
|
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
|
+import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
|
|
|
+import okhttp3.*;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import javax.validation.constraints.NotNull;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.Optional;
|
|
|
+import java.util.function.Function;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author kunduin
|
|
|
+ */
|
|
|
+public class CodeJudgeClient implements CodeJudgeApi {
|
|
|
+
|
|
|
+ private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
|
+
|
|
|
+ private final OkHttpClient client;
|
|
|
+ private final ObjectMapper mapper;
|
|
|
+
|
|
|
+ private final String CONFIG_HOST;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建client
|
|
|
+ *
|
|
|
+ * @param host code judge 地址,示例:{@code "http://codejudge.seec.seecoder.cn"}
|
|
|
+ */
|
|
|
+ public CodeJudgeClient(String host) {
|
|
|
+ this.CONFIG_HOST = host;
|
|
|
+ client = new OkHttpClient();
|
|
|
+ mapper = JsonMapper.builder()
|
|
|
+ .addModule(new ParameterNamesModule())
|
|
|
+ .addModule(new Jdk8Module())
|
|
|
+ .addModule(new JavaTimeModule())
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判题接口
|
|
|
+ *
|
|
|
+ * @param judgeDTO 判题信息
|
|
|
+ * @return 判题结果
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public JudgeResult judge(@NotNull JudgeDTO judgeDTO) {
|
|
|
+ HttpUrl httpUrl = createUrlBuilder("/api/judge").build();
|
|
|
+ Response response = post(httpUrl, writeRequestBody(judgeDTO));
|
|
|
+ return getResponseBody(response, JudgeResult.class)
|
|
|
+ .map(judgeResult -> {
|
|
|
+ if (judgeResult.getMessage() == null) {
|
|
|
+ return judgeResult;
|
|
|
+ } else {
|
|
|
+ throw new CodeJudgeSystemException(judgeResult.getMessage());
|
|
|
+ }
|
|
|
+ }).orElseThrow(() -> SeecoderBokException.UNWRAP_EXCEPTION);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private HttpUrl.Builder createUrlBuilder(final String path) {
|
|
|
+ return Objects.requireNonNull(HttpUrl.parse(CONFIG_HOST + path)).newBuilder();
|
|
|
+ }
|
|
|
+
|
|
|
+ private Response post(HttpUrl httpUrl, RequestBody requestBody) {
|
|
|
+ return requestWithMethod("POST", httpUrl, requestBody);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Response requestWithMethod(String method, HttpUrl httpUrl, RequestBody requestBody) {
|
|
|
+ Request request = new Request.Builder().url(httpUrl).method(method, requestBody).build();
|
|
|
+ try {
|
|
|
+ return client.newCall(request).execute();
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("IOException.", e);
|
|
|
+ throw SeecoderBokException.IO_EXCEPTION;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private <T> Optional<T> getResponseBody(Response response, Class<T> tClass) {
|
|
|
+ return getResponseBody(
|
|
|
+ response,
|
|
|
+ bodyString -> {
|
|
|
+ try {
|
|
|
+ return mapper.readValue(bodyString, tClass);
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ logger.error("JsonProcessingException.", e);
|
|
|
+ throw SeecoderBokException.JSON_EXCEPTION;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private <T> Optional<T> getResponseBody(Response response, TypeReference<T> typeReference) {
|
|
|
+ return getResponseBody(
|
|
|
+ response,
|
|
|
+ bodyString -> {
|
|
|
+ try {
|
|
|
+ return mapper.readValue(bodyString, typeReference);
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ logger.error("JsonProcessingException.", e);
|
|
|
+ throw SeecoderBokException.JSON_EXCEPTION;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private <T> Optional<T> getResponseBody(Response response, Function<String, T> mapType) {
|
|
|
+ return Optional.ofNullable(response.body())
|
|
|
+ .map(body -> {
|
|
|
+ try {
|
|
|
+ String bodyString = body.string();
|
|
|
+ return mapType.apply(bodyString);
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("IOException.", e);
|
|
|
+ throw SeecoderBokException.IO_EXCEPTION;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private <T> RequestBody writeRequestBody(T obj) {
|
|
|
+ if (obj == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ return RequestBody.create(CodeJudgeConstants.JSON, mapper.writeValueAsString(obj));
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ logger.error("JsonProcessingException.", e);
|
|
|
+ throw SeecoderBokException.JSON_EXCEPTION;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|