我试图通过REST网络服务将数据从数据库检索到移动应用程序。我设法创建了一些基本功能但是当我尝试添加功能时遇到了问题。例如,我希望能够找到"客户"他们的身份证和他们的名字。当我有两个Get方法时,一个用" / {id}"和#34; / {name}"该应用程序不知道该使用什么。我可以做什么来按名称搜索? 这是来自Web服务的控制器。
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,但当其中一个被注释掉时,这就可以了。
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 :(得分:1)
您的宁静设计可以改善。我建议定义这样的东西:
新强>
/customers with POST method.
这是不正确的,在宁静中,资源创建应该由方法类型定义。我建议这个:
/customers/{id}
按ID搜索:
/customers/{name}
这是正确的,在restful中,资源应该通过id使用路径变量来访问。
按名称搜索:
/customers?name=<<name>>
这不正确,在这里你要查询客户资源,所以,你应该使用查询参数,我建议:
@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) {
...
}
如果您有多个查询方法,则会出现冲突,因为在具有相同路径的控制器中不能有多个GET方法。因此,您可以将@RequestMapping修改为显式断言需要哪些查询参数:
n
答案 1 :(得分:0)
使用不同的路径区分URL,这也会使它们更加RESTful。
按名称搜索:
/customers/names/{name}
按ID搜索:
/customers/ids/{id}
将来您可能想要添加另一个搜索,可能是城市:
/customers/cities/{city}
答案 2 :(得分:0)
您的控制器映射了不明确的处理程序方法,因此在调用端点时,您实际上会遇到异常。通过为id获取和按名称获取不同的映射来解决此问题。
答案 3 :(得分:0)
资源由其PATH(而不是它的参数)唯一标识。因此,使用相同路径的资源很少:internal
您可以创建两个不同的资源,例如:
"customers/"
@RequestMapping(value = "/id", method = RequestMethod.GET)
或者您可以创建一个包含许多请求参数的资源:
@RequestMapping(value = "/name", method = RequestMethod.GET)