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或名称?
我的问题是当用户发送@PathVariable
或String
时,不确定如何定义Long
。它甚至可以吗?或者我应该把@PathVariable
作为String
并解析Long
?
简短的回答。你不能将不同的类型混合到一个@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);
}
鉴于这是一个搜索,另一种合理的方法是使用查询参数:
/users?name=jdoe
要么
/users?id=123
并使用多个@QueryParameter而不是@PathParameter。
并考虑创建使用@PathParamter的别名,例如:
/users/name/{name}
/users/id/{id}
客户端可以使用查询参数方法或别名,以较容易的方式。 findUser()
can根据提供的查询参数简单地委托给findById()
或findByName()
。