Spring引导休息单路径变量,它采用不同类型的值

问题描述 投票:-2回答:2

Spring引导休息如何提供一个具有一个路径变量的终点,该变量采用不同类型的值

@Autowired
private UserRepository userRepository;

@RequestMapping(value="/user/{idOrName}", method=RequestMethod.GET)
public User findUser(@PathVariable String idOrName) {
  this.userRepository.findByIdOrName(idOrName, idOrName);
}

public interface UserRepository extends MongoRepository<User, Long> {
  User findByIdOrName(Long id, String name);
}

@Data
@Document(collection="user")
public class User {
  private Long Id;
  private String name;
}

问题陈述:正如您在用户模型中看到的,Id是Long的类型,而Name是String的类型。现在我需要实现单端点,它提供了通过id或name搜索用户的工具。

如何实现具有一个路径变量的休息终点,该变量接受不同类型的id或名称?

我的问题是当用户发送@PathVariableString时,不确定如何定义Long。它甚至可以吗?或者我应该把@PathVariable作为String并解析Long

java spring-boot spring-data-mongodb spring-restcontroller spring-repositories
2个回答
1
投票

简短的回答。你不能将不同的类型混合到一个@PathVariable中,就像Spring在他们的文档中所说的那样。

根据有关Spring IO@PathVariable文档:

@PathVariable参数可以是任何简单类型,如int,long,Date等。如果无法执行此操作,Spring会自动转换为适当的类型或抛出TypeMismatchException。

请注意,文档将@PathVariable参数概述为单个对象类型,该类型不可互换为不同类型。

另外,在another stackoverflow question中回答异常处理是完全正常的,试图在没有try/catch的情况下从String确定Long甚至不值得工作并降低性能。

您可以使用单个@PathVariable并使用try/catch块来捕获NumberFormatException或只是一个正则表达式。

方法1:异常处理

@RequestMapping(value="/user/{identifier}", method=RequestMethod.GET)
public User findUser(@PathVariable("identifier") String identifier) {
    try {
        Long long_identifier = Long.parseLong(identifier);
        this.userRepository.findByIdOrName(long_identifier);
    } catch(NumberFormatException nfe) {
        //We know it's a plain string by now.
        this.userRepository.findByIdOrName(identifier);
    }
}

方法2:正则表达式

注意:如果未找到值,则查询应该只返回空结果。

@RequestMapping(value="/user/{identifier}", method=RequestMethod.GET)
public User findUser(@PathVariable("identifier") String identifier) {
    //Check for digits only
    String regexpr = "\\d+";
    this.userRepository.findByIdOrName(
        identifier.matches(regexpr)
        ? Long.parseLong(identifier)
        : identifier
    );
}

方法3:使用正则表达式请求映射

@RequestMapping(value="/user/{identifier:[A-Za-z]+}", method=RequestMethod.GET)
public User findUserByString(@PathVariable("identifier") String identifier) {
    this.userRepository.findByIdOrName(identifier);
}

@RequestMapping(value="/user/{identifier:[0-9]+}", method=RequestMethod.GET)
public User findUserByLong(@PathVariable("identifier") Long identifier) {
    this.userRepository.findByIdOrName(identifier);
}

0
投票

鉴于这是一个搜索,另一种合理的方法是使用查询参数:

/users?name=jdoe

要么

/users?id=123

并使用多个@QueryParameter而不是@PathParameter。

并考虑创建使用@PathParamter的别名,例如:

/users/name/{name}
/users/id/{id}

客户端可以使用查询参数方法或别名,以较容易的方式。 findUser()can根据提供的查询参数简单地委托给findById()findByName()

© www.soinside.com 2019 - 2024. All rights reserved.