使用GraphQL + Java处理上传的文件

概述

    • JavaでGraphQLサーバーを構築した際のファイルアップロード処理の実装例

 

    GraphQLクライアント側の説明は割愛

组成

    • Java 11

 

    • SpringBoot 2.3.4

 

    • gradle 7.4.1

 

    • GraphQL For Java

graphql-spring-boot-starter 7.1.0 ref. 1

io.github.kobylynskyi.graphql.codegen 5.5.0

※ 注意,此配置不是最新的Spring Boot。

实施方式

点数 shù)

    • schema定義について

GraphQLのschema定義ではアップロードするファイルをUploadで定義する
Uploadは、Java側で任意のクラスにマッピングするため、scalarに記載する

Java側について

schema定義のUploadをjavax.servlet.http.Partで受け取る

具体细节

    全ソースはここからどうぞ

准备各种设置文件

    1. 创建基于Spring Initializr的项目

 

    1. 在build.gradle中如下所示进行编写

build.gradle
插件 {
id ‘org.springframework.boot’版本’2.3.4.RELEASE’
id ‘io.spring.dependency-management’版本’1.0.15.RELEASE’
id ‘io.github.kobylynskyi.graphql.codegen’版本’5.5.0’
id ‘java’
}

组 = ‘com.example’
版本 = ‘0.0.1-SNAPSHOT’
源兼容性 = ’11’

仓库 {
中央存储库()
}

依赖关系 {
实现 ‘org.springframework.boot:spring-boot-starter’
测试实现 ‘org.springframework.boot:spring-boot-starter-test’
实现 ‘com.graphql-java-kickstart:graphql-spring-boot-starter:7.1.0’
测试实现 ‘com.graphql-java-kickstart:graphql-spring-boot-starter:7.1.0’
}

任务的名称(’测试’) {
使用JUnit Platform()
}

由于URL等使用默认设置,因此application.properties不需要更改,参考2。

创建文件上传的schema定义。

    1. 以下是中文翻译:

graphql/schema.graphqls
”’
上传文件
”’
标量 Upload

# 在本示例中,Query 没有被使用,但如果不写它,应用程序在启动时会抱怨,所以需要添加这段
type Query {}

type Mutation {
”’
上传文件
”’
upload(
”’
文件
”’
file: Upload
): Boolean
}

从schema定义生成Java的接口和类

    1. 可以通过手动创建,但这次我们将使用graphql-java-codegen生成。ref. 4

在build.gradle中添加以下配置

build.gradle
// 在末尾添加
// 从GraphQL schema定义生成Java代码
apply from: ‘gradle/graphql-java-codegen.gradle’

创建配置文件graphql-java-codegen.gradle,并对在schema.graphqls中定义的标量类型(比如Upload)进行映射等配置 ref. 3,ref. 5

gradle/graphql-java-codegen.gradle
apply plugin: “io.github.kobylynskyi.graphql.codegen”

compileJava.options.encoding = ‘UTF-8’

graphqlCodegen {
// 所有配置选项:
// https://github.com/kobylynskyi/graphql-java-codegen/blob/master/docs/codegen-options.md
outputDir = new File(“$buildDir/generated”)
graphqlSchemas.includePattern = “schema\\.graphqls”
apiPackageName = “com.example.demographqlfileupload.graphql.resolvers”
// 通常情况下,model应该存在,但在本示例中不存在,因此不指定
//modelPackageName = “com.example.demographqlfileupload.graphql.model”
modelNameSuffix = “TO”
// 标量的映射类
customTypesMapping = [
Upload: “javax.servlet.http.Part”
]
parentInterfaces {
queryResolver = “graphql.kickstart.tools.GraphQLQueryResolver”
mutationResolver = “graphql.kickstart.tools.GraphQLMutationResolver”
}
}

使用以上配置文件执行以下gradle命令生成文件。

gradle graphqlCodegen -Dfile.encoding=utf-8

文件将生成在$buildDir/generated目录下,将文件移动到项目的任意文件夹下。这次移动到以下文件夹下:

/demographqlfileupload/src/main/java/com/example/demographqlfileupload/graphql/resolvers

生成的文件如下,将其复制到项目中

UploadMutationResolver.java
package com.example.demographqlfileupload.graphql.resolvers;

/**
* 上传文件
*/
@javax.annotation.processing.Generated(
value = “com.kobylynskyi.graphql.codegen.GraphQLCodegen”,
date = “2022-10-25T19:12:40+0900”
)
public interface UploadMutationResolver extends graphql.kickstart.tools.GraphQLMutationResolver {

/**
* 上传文件
*/
Boolean upload(javax.servlet.http.Part file) throws Exception;

}

明确表明从scalar到转换

    1. 以下是一个创建ExtendedScalarConfiguration类的示例:

“`java
package com.example.demographqlfileupload.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import graphql.kickstart.servlet.apollo.ApolloScalars;
import graphql.schema.GraphQLScalarType;

@Configuration
public class ExtendedScalarConfiguration {

@Bean
public GraphQLScalarType uploadScalar() {
return ApolloScalars.Upload;
}
}
“`

使用在步骤③生成的接口来创建解析器类。

    1. 创建以下类:

UploadResolver
package com.example.demographqlfileupload.resolver;

import javax.servlet.http.Part;

import org.springframework.stereotype.Component;

import com.example.demographqlfileupload.graphql.resolvers.QueryResolver;
import com.example.demographqlfileupload.graphql.resolvers.UploadMutationResolver;

@Component
public class UploadResolver
implements UploadMutationResolver, QueryResolver {

@Override
public Boolean upload(Part file) throws Exception {
if (Objects.isNull(file)) {
return false;
}
System.out.println(file.getSubmittedFileName());
return null;
}
}

确保你能够适当地进行文件处理,以完成任务!

确认动作

    • いろいろGraphQLクライアントはあると思いますが、私はPostmanで統一したいのでPostmanを使っています。

 

    ファイルアップロードについては癖があるので注意

邮递员步骤参考7号。

image.png

总结

    • GraphQLのschema定義scalarでUploadを指定する

 

    • Java側ではschema定義のUploadをjavax.servlet.http.Partで受け取れるようマッピングしてやる

 

    SpringBootのバージョンによって取得するGraphQLのDependenciesが変わっているので注意!!

其他

    • GraphQLはアップロードはサポートしていますがダウンロードに使うのは想定されていないようです。自前で実装しましょう。

Springならコントローラーを追加して通常のHttpRequestとして処理すればOK

Spring Boot 2.7 以降はSpring InitializrでSpring for GraphQLというDependenciesを利用することができます。提供されるパッケージが変わるため本稿の実装はそのままは使えないです。

例えば本稿ではgraphql.kickstartのパッケージを利用していますが、バージョンによってはこのパッケージは提供されていないため利用できなくなります。ref. 8, ref. 9, ref. 10

提供的信息参考

我只需要一个中文的选项来将下面的内容进行释义:

引用部

    • ref. 1 GraphQL Java Kickstart

 

    • ref. 2 Enable GraphQL Servlet

 

    • ref. 3 How to upload files with graphql-java

 

    • ref. 4 kobylynskyi/graphql-java-codegen

 

    • ref. 5 graphql-java-codegen/docs/codegen-options.md

 

    • ref. 6 Custom Scalar実装(GraphQL-SpringBoot)

 

    • ref. 7 Is there any way to upload files via postman into a GraphQL API?

 

    • ref. 8 GraphQL with spring-boot-starter-graphql

 

    • ref. 9 Spring for GraphQL Documentation

 

    ref. 10 Getting started with Spring for GraphQL

整体来说

    • Spring BootでGraphQLを試した

 

    Uploading files with Spring and GraphQL
bannerAds