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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Controller Java Spring中使用不同的GET方法相关的知识,希望对你有一定的参考价值。

我正在尝试通过REST Web服务将数据从数据库检索到移动应用程序。我已经设法制作了一些基本功能但是当我尝试添加功能时遇到了问题。例如,我希望能够通过他们的ID和他们的名字找到“客户”。当我有两个Get方法时,一个使用“/ {id}”,另一个使用“/ {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());
                }
            });
        }
    });

希望我已经让自己明白了。请询问是否有不清楚的地方或您需要更多信息。

答案

使用不同的路径区分URL,这也将使它们更加RESTful。

按名称搜索:

/customers/names/{name}

按ID搜索:

/customers/ids/{id}

将来您可能想要按城市添加其他搜索:

/customers/cities/{city}
另一答案

您的宁静设计可以改善。我建议定义这样的东西:

新:

/customers/new

这是不正确的,在宁静中,资源创建应该由方法类型定义。我建议这个:

/customers with POST method.

按ID搜索:

/customers/{id}

这是正确的,在restful中,资源应该通过id使用路径变量来访问。

按名称搜索:

/customers/{name}

这是不正确的,在这里你要查询客户资源,所以,你应该使用查询参数,我建议:

/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) {
    ...
}
另一答案

您的控制器具有映射的模糊处理程序方法,因此在调用端点时,您实际上会获得异常。通过为id获取和按名称获取不同的映射来解决此问题。

另一答案

资源由其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)

以上是关于如何在Controller Java Spring中使用不同的GET方法的主要内容,如果未能解决你的问题,请参考以下文章

Spring的Controller如何命名最好

面试官:Spring MVC 如何保证 Controller 的并发安全性?面试必问。。

java [CashierControllerTest] Spring Controller单元测试类#java #spring

在 Spring MVC 中从 Controller 显示视图(所有员工的列表)

java springmvc 页面枚举类型作为怎样查询条件并传递参数到controller

java之spring mvc之数据处理