2017-04-20 17 views
0

データベースからREST Webサービスを介してモバイルアプリケーションにデータを取得しようとしています。私はいくつかの基本的な機能を作りましたが、機能を追加しようとすると問題にぶつかります。たとえば、自分のIDとその名前で「顧客」を見つけることができるようにしたいと考えています。 "/ {id}"と "/ {name}"の2つのGetメソッドがある場合、アプリケーションは何を使うべきかを知らない。名前で検索するにはどうすればよいですか? これはWebサービスのコントローラです。Controller Java Springで異なるGETメソッドを使用する方法

package com.example; 


import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.HttpStatus; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.*; 

import java.util.List; 

@RestController 
@RequestMapping("/customers") 
public class CustomerController { 
private CustomerRepository repository; 

@Autowired 
public CustomerController(CustomerRepository repository) { 
    this.repository = repository; 
} 

@RequestMapping(value = "/{name}", method = RequestMethod.GET) 
public ResponseEntity<Customer> get(@PathVariable("name") String name) { 
    Customer customer = repository.findByName(name); 
    if (null == customer) { 
     return new ResponseEntity<Customer>(HttpStatus.NOT_FOUND); 
    } 
    return new ResponseEntity<Customer>(customer, HttpStatus.OK); 
} 

@RequestMapping(value = "/{id}", method = RequestMethod.GET) 
public ResponseEntity<Customer> get(@PathVariable("id") Long id) { 
    Customer customer = repository.findOne(id); 
    if (null == customer) { 
     return new ResponseEntity<Customer>(HttpStatus.NOT_FOUND); 
    } 
    return new ResponseEntity<Customer>(customer, HttpStatus.OK);* 
} 

@RequestMapping(value = "/new", method = RequestMethod.POST) 
public ResponseEntity<Customer> update(@RequestBody Customer customer) { 
    repository.save(customer); 
    return get(customer.getName()); 
} 

@RequestMapping 
public List<Customer> all() { 
    return repository.findAll(); 
} 
} 

これは、Androidアプリケーション

package com.ermehtar.poppins; 

import java.util.List; 

import retrofit2.Call; 
import retrofit2.http.Body; 
import retrofit2.http.GET; 
import retrofit2.http.PATCH; 
import retrofit2.http.POST; 
import retrofit2.http.Path; 

public interface CustomerService { 
@GET("customers") 
Call<List<Customer>> all(); 

@GET("customers/{id}") 
Call<Customer> getUser(@Path("id") Long id); 

@GET("customers/{name}") 
Call<Customer> getUser(@Path("name") String name); 

@POST("customers/new") 
Call<Customer> create(@Body Customer customer); 
} 

からのサービスは、これは私が名前でサービスを呼び出すために使用する関数です。/nameと/ idの両方の関数がWebサービスコントローラーにある場合、response.bodyはnullになりますが、そのうちの1つがコメントアウトされているときには正常に動作します。

findUsernameButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      Call<Customer> createCall = service.getUser("John"); 
      createCall.enqueue(new Callback<Customer>() { 
       @Override 
       public void onResponse(Call<Customer> _, Response<Customer> resp) { 
        findUsernameButton.setText(resp.body().name); 
       } 

       @Override 
       public void onFailure(Call<Customer> _, Throwable t) { 
        t.printStackTrace(); 
        allCustomers.setText(t.getMessage()); 
       } 
      }); 
     } 
    }); 

私は自分自身を理解できたと思っています。不明な点があるか、さらに詳しい情報が必要かどうか尋ねてください。

答えて

0

URLを別のパスで区別して、よりRESTfulにします。

名で検索:IDによって

/customers/names/{name} 

検索:あなたは、おそらく街で、別の検索を追加したい場合があります将来的には

/customers/ids/{id} 

/customers/cities/{city} 
+0

これは機能しました!ありがとう! – Ermehtar

0

お使いのコントローラあいまいなハンドラメソッドがマップされているため、エンドポイントを呼び出すときに実際に例外が発生します。これを修正するには、get by idとget by nameという異なるマッピングを作成します。

0

リソースはPATHによって一意に識別されます(パラメータではなく)。だから、同じパスを持ついくつかのリソースをそこにいる:"customers/"

あなたが好きな二つの異なるリソースを作成することができます。

  • @RequestMapping(value = "/id", method = RequestMethod.GET)
  • @RequestMapping(value = "/name", method = RequestMethod.GET)

それとも、多くは一つのリソースを作ることができますリクエストパラメータ: @RequestMapping(value = "/get", method = RequestMethod.GET) public ResponseEntity<Customer> get(@RequestParam ("id") Long id, @RequestParam ("name") String name)

1

残りフルデザインを改善することができます。

新:私はこのような何かを定義することをお勧め

/customers/new 

これは、リソースの作成は法の種類によって規定されるべきで安らかに、正しくありません。私はこれをお勧め:

/customers with POST method. 

IDで検索:

/customers/{id} 

これは安らかにリソースがパス変数を使用してIDによるアクセスである必要があり、正確です。名前で

検索:

/customers/{name} 

これは私がこれを示唆して、クエリーのparamsを使用する必要があり、ここにあなたが顧客リソースをキシにしている、正しくない、ので:

/customers?name=<<name>> 

場合複数のクエリメソッドがある場合、同じパスを持つコントローラ内に複数のGETメソッドを持つことができないため、競合が発生します。だから、@ ReQuestMappingを変更して、どのようなクエリパラメータが必要なのかを明示的にアサートすることができます:

@RequestMapping(value = "/", method = RequestMethod.GET, , params = "name") 
public ResponseEntity<Customer> getByName(@RequestParam("name") String name) { 
    ... 
} 

@RequestMapping(value = "/", method = RequestMethod.GET, , params = "lastname") 
public ResponseEntity<Customer> getByLastname(@RequestParam("lastname") String lastname) { 
    ... 
} 
関連する問題