如何在Controller Java Spring中使用不同的GET方法

时间:2017-04-20 20:43:31

标签: java spring rest

我试图通过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());
                }
            });
        }
    });
希望我能让自己理解。请询问是否有不清楚的地方或您需要更多信息。

4 个答案:

答案 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)