如何解决非法字符导致在创建docker映像期间Spring Boot微服务构建失败
我正在Spring引导应用程序中与Micro服务建立内部通信。响应以JSON格式生成,并使用logback.xml登录到日志文件中。 ELK方面通过docker-maven插件进一步利用了这一点。在执行mvn全新安装时,它会在通过pom.xml创建Docker映像期间引发异常。
错误堆栈:
原因:com.spotify.docker.client.exceptions.DockerException: com.spotify.docker.client.shaded.com.fasterxml.jackson.core.JsonParseException: 非法字符((CTRL-CHAR,代码0)):仅常规空格(\ r, 令牌之间允许\ n,\ t) 在[来源:(文件);行:1,列:2] 在com.spotify.docker.client.auth.ConfigFileRegistryAuthSupplier.authForBuild (ConfigFileRegistryAuthSupplier.java:108) 在com.spotify.docker.client.auth.MultiRegistryAuthSupplier.authForBuild (MultiRegistryAuthSupplier.java:77) 在com.spotify.docker.client.DefaultDockerClient.build(DefaultDockerClient.java:1483) 在com.spotify.docker.client.DefaultDockerClient.build(DefaultDockerClient.java:1460) 在com.spotify.plugin.dockerfile.BuildMojo.buildImage(BuildMojo.java:240) 在com.spotify.plugin.dockerfile.BuildMojo.execute(BuildMojo.java:135) 在com.spotify.plugin.dockerfile.AbstractDockerMojo.tryExecute(AbstractDockerMojo.java:265) 在com.spotify.plugin.dockerfile.AbstractDockerMojo.execute(AbstractDockerMojo.java:254) 在org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137) 在org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
pom.xml:
<!-- Dockerfile from Spotify -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.11</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>install</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
我调试了代码,找到了错误原因。这是由于以下方法在突出显示的行上引起的:
private List<Comment> findCommentsForFeed(Feeds feed) {
log.info("Finding comments of feed with id {}",feed.getId());
String url = UriComponentsBuilder.fromHttpUrl(commentServiceBaseUrl).path("comments")
.queryParam("feedId",feed.getId()).toUriString();
// ** THIS LINE CAUSES ERROR... **
ResponseEntity<List<Comment>> response = restTemplate.exchange(url,HttpMethod.GET,null,new ParameterizedTypeReference<List<Comment>>() {
});
List<Comment> comments = Objects.isNull(response.getBody()) ? new ArrayList<>() : response.getBody();
log.info("Found {} comment(s) of feed with id {}",comments.size(),feed.getId());
return comments;
}
我的控制器看起来像:
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/feeds",produces = MediaType.APPLICATION_JSON_VALUE)
public class FeedController {
@Autowired
private final FeedService service;
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<Feeds>> getFeeds() {
List<Feeds> feeds = service.getFeeds();
return ResponseEntity.ok(feeds);
}
@GetMapping(path = "/{id}",produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<FeedWithComment> getFeed(@PathVariable Long id) {
FeedWithComment feedWithComments = service.getFeed(id).orElseThrow(ResourceNotFoundException::new);
return ResponseEntity.ok(feedWithComments);
}
我用于json输出的logback.xml文件如下所示:
<springProfile name="docker">
<appender name="jsonConsoleAppender"
class="ch.qos.logback.core.ConsoleAppender">
<encoder
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
<version />
<logLevel />
<message />
<loggerName />
<threadName />
<context />
<pattern>
<omitEmptyFields>true</omitEmptyFields>
<pattern>
{
"trace": {
"trace_id": "%mdc{X-B3-TraceId}","span_id":
"%mdc{X-B3-SpanId}","parent_span_id": "%mdc{X-B3-ParentSpanId}","exportable": "%mdc{X-Span-Export}"
}
}
</pattern>
</pattern>
<mdc>
<excludeMdcKeyName>traceId</excludeMdcKeyName>
<excludeMdcKeyName>spanId</excludeMdcKeyName>
<excludeMdcKeyName>parentId</excludeMdcKeyName>
<excludeMdcKeyName>spanExportable</excludeMdcKeyName>
<excludeMdcKeyName>X-B3-TraceId</excludeMdcKeyName>
<excludeMdcKeyName>X-B3-SpanId</excludeMdcKeyName>
<excludeMdcKeyName>X-B3-ParentSpanId</excludeMdcKeyName>
<excludeMdcKeyName>X-Span-Export</excludeMdcKeyName>
</mdc>
<stackTrace />
</providers>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="jsonConsoleAppender" />
</root>
</springProfile>
解决方法
我做了一些分析,发现问题是由于Spring引导版本引起的。在引入Springboot 2.3.0之后,Spring Boot的目录结构发生了变化。我正在使用Spring Boot版本2.3.3。我在dockerfile中做了一些更改,它起作用了。 Maven Docker插件成功创建了映像。 Dockerfile:
FROM adoptopenjdk/openjdk14 as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM adoptopenjdk/openjdk14
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java","-Dspring.profiles.active=docker","org.springframework.boot.loader.JarLauncher"]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。