服务计算学习之路四——简单 web 服务与客户端开发实战

简单 web 服务与客户端开发实战

团队项目连接:

后端部分,前端部分

自己实现的部分

  • 实现后端中负责网络连接的主要部分main.go文件内容

实现过程

  • Step1:仿照 https://swapi.co/ 网站的API结构构造Planet,Species,People,Films,Starships,Vehicles结构,用Gragpql的API创建,例如Planet对应的graphql.Object:

    func createPlanetType() *graphql.Object {
    	return graphql.NewObject(graphql.ObjectConfig{
    		Name: "Planet",
    		Fields: graphql.Fields{
    			"Name": &graphql.Field{
    				Type: graphql.String,
    			},
    			"OrbitalPeriod": &graphql.Field{
    				Type: graphql.String,
    			},
    			"RotationPeriod": &graphql.Field{
    				Type: graphql.String,
    			},
    			"Diameter": &graphql.Field{
    				Type: graphql.String,
    			},
    			"Climate": &graphql.Field{
    				Type: graphql.String,
    			},
    			"Gravity": &graphql.Field{
    				Type: graphql.String,
    			},
    			"Terrain": &graphql.Field{
    				Type: graphql.String,
    			},
    			"SurfaceWater": &graphql.Field{
    				Type: graphql.String,
    			},
    			"Population": &graphql.Field{
    				Type: graphql.String,
    			},
    			"ResidentURLs": &graphql.Field{
    				Type: graphql.NewList(graphql.String),
    			},
    			"FilmURLs": &graphql.Field{
    				Type: graphql.NewList(graphql.String),
    			},
    			"Created": &graphql.Field{
    				Type: graphql.String,
    			},
    			"Edited": &graphql.Field{
    				Type: graphql.String,
    			},
    			"URL": &graphql.Field{
    				Type: graphql.String,
    			},
    		},
    	})
    }
    

    Species,People,Films,Starships,Vehicles的代码也类似。

  • Step2:然后我们的数据是用boltDB保存在服务器中,所以对API的请求,如果请求格式正确,我们要根据请求内容返回对应的Planet,Species,People,Films,Starships,Vehicles相应字段的数据,例如从数据库获取People内容的数据:

    func fetchPeopleByiD(id int) (*Person, error) {
    	result := Person{}
    	db, _ := setupDB()
    
    	db.View(func(tx *bolt.Tx) error {
    		b := tx.Bucket([]byte("DB")).Bucket([]byte("People"))
    		v := string(b.Get([]byte(strconv.Itoa(id))))
    		err := json.Unmarshal([]byte(v), &result)
    		if err != nil {
    			return fmt.Errorf("could not Unmarshal json string: %v", err)
    		}
    
    		return nil
    	})
    	db.Close()
    	return &result, nil
    }
    

    Planet,Species,Films,Starships,Vehicles的也类似。

  • Step3:最后,在main函数主体里定义好对请求返回数据的处理,这部分类似步骤1的操作:

    rootQuery := graphql.NewObject(graphql.ObjectConfig{
    		Name: "Query",
    		Fields: graphql.Fields{
    			
    			"planets": &graphql.Field{
    				Type: createPlanetType(),
    				Args: graphql.FieldConfigArgument{
    					"id": &graphql.ArgumentConfig{
    						Type: graphql.NewNonNull(graphql.Int),
    					},
    				},
    				Resolve: func(p graphql.ResolveParams) (interface{}, error) {
    					id := p.Args["id"]
    					v, _ := id.(int)
    					log.Printf("fetching planet with id: %d", v)
    					return fetchPlanetByiD(v)
    				},
    			},
    			"species": &graphql.Field{
    				Type: createSpeciesType(),
    				Args: graphql.FieldConfigArgument{
    					"id": &graphql.ArgumentConfig{
    						Type: graphql.NewNonNull(graphql.Int),
    					},
    				},
    				Resolve: func(params graphql.ResolveParams) (interface{}, error) {
    					id := params.Args["id"]
    					v, _ := id.(int)
    					log.Printf("fetching species with id: %d", v)
    					return fetchSpeciesByPostID(v)
    				},
    			},
    
    			"people": &graphql.Field{
    				Type: createPeopleType(),
    				Args: graphql.FieldConfigArgument{
    					"id": &graphql.ArgumentConfig{
    						Type: graphql.NewNonNull(graphql.Int),
    					},
    				},
    				Resolve: func(params graphql.ResolveParams) (interface{}, error) {
    					id := params.Args["id"]
    					v, _ := id.(int)
    					log.Printf("fetching people with id: %d", v)
    					return fetchPeopleByiD(v)
    				},
    			},
    			"films": &graphql.Field{
    				Type: createFilmType(),
    				Args: graphql.FieldConfigArgument{
    					"id": &graphql.ArgumentConfig{
    						Type: graphql.NewNonNull(graphql.Int),
    					},
    				},
    				Resolve: func(params graphql.ResolveParams) (interface{}, error) {
    					id := params.Args["id"]
    					v, _ := id.(int)
    					log.Printf("fetching films with id: %d", v)
    					return fetchFilmByiD(v)
    				},
    			},
    			"starships": &graphql.Field{
    				Type: createStarshipType(),
    				Args: graphql.FieldConfigArgument{
    					"id": &graphql.ArgumentConfig{
    						Type: graphql.NewNonNull(graphql.Int),
    					},
    				},
    				Resolve: func(params graphql.ResolveParams) (interface{}, error) {
    					id := params.Args["id"]
    					v, _ := id.(int)
    					log.Printf("fetching starships with id: %d", v)
    					return fetchStarshipByiD(v)
    				},
    			},
    			"vehicles": &graphql.Field{
    				Type: createVehicleType(),
    				Args: graphql.FieldConfigArgument{
    					"id": &graphql.ArgumentConfig{
    						Type: graphql.NewNonNull(graphql.Int),
    					},
    				},
    				Resolve: func(params graphql.ResolveParams) (interface{}, error) {
    					id := params.Args["id"]
    					v, _ := id.(int)
    					log.Printf("fetching Vehicles with id: %d", v)
    					return fetchVehicleByiD(v)
    				},
    			},
    			
    		},
    	})
    

    然后利用graghql提供的schema和handler对请求进行处理并在3000端口监听:

    schema, err := graphql.NewSchema(graphql.SchemaConfig{
    		Query: rootQuery,
    	})
    
    	if err != nil {
    		log.Fatalf("failed to create new schema, error: %v", err)
    	}
    	handler := gqlhandler.New(&gqlhandler.Config{
    		Schema: &schema,
    	})
    	http.Handle("/graphql", handler)
    	log.Println("Server started at http://localhost:3000/graphql")
    	log.Fatal(http.ListenAndServe(":3000", nil))
    

小总结

由于时间关系,关于实现的方法介绍得不太清晰,如需进一步了解请先查看一下资料:
graghql-go官网资料:https://godoc.org/github.com/graphql-go/graphql
Qraqhql官网资料:http://graphql.cn/

我实现的代码的github连接

https://github.com/LittleFish33/Server-Computing-Swapi/blob/master/main.go

你可能感兴趣的:(服务计算)