分离Controller与RequestMapping定义
分离Controller与RequestMapping定义
Spring在解析RequestMapping的注解的时候, 会从父类或者接口上读取RequestMapping注解的信息.
利用这种方法, 可以分离Controller和RequestMapping注解.
例如下面是一个常见的RESTful风格的Controller代码
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public User get(@PathVariable("id") Long id) {
return userService.findById(id);
}
@GetMapping
public Page<User> page(@QuerydslPredicate Predicate predicate, Pageable pageable) {
return userService.findByPage(predicate, pageable);
}
@PostMapping
public User create(@RequestBody User user) {
return userService.create(user);
}
@PutMapping("{id}")
public User update(@PathVariable("id") Long id, @RequestBody User user) {
return userService.update(id, user);
}
@DeleteMapping("{id}")
public void delete(@PathVariable("id") Long id) {
userService.deleteById(id);
}
}
我们可以定义一个UserRequestMappingDefinition的接口, 方法与UserController一致.
public interface UserRequestMappingDefinition {
@GetMapping("/{id}")
User get(@PathVariable("id") Long id);
@GetMapping
Page<User> page(@QuerydslPredicate Predicate predicate, Pageable pageable);
@PostMapping
User create(@RequestBody User user);
@PutMapping("{id}")
User update(@PathVariable("id") Long id, @RequestBody User user);
@DeleteMapping("{id}")
void delete(@PathVariable("id") Long id);
}
然后让UserController实现该接口, 并去掉UserController上的注解
@RestController
@RequestMapping("/user")
public class UserController implements UserRequestMappingDefinition {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
public User get(Long id) {
return userService.findById(id);
}
public Page<User> page(Predicate predicate, Pageable pageable) {
return userService.findByPage(predicate, pageable);
}
public User create(User user) {
return userService.create(user);
}
public User update(Long id, User user) {
return userService.update(id, user);
}
public void delete(Long id) {
userService.deleteById(id);
}
}
然而, 这又有什么用呢? 如果每个Controller都添加一个RequestMappingDefinition来定义, 无端增加了很多的类.
但是仔细观察, 你会发现, RESTful风格的Controller的注解基本上一样, 每个Controller上的方法中都要同样编写一样的注解来修饰方法和方法参数等, 我们只需利用上面的机制, 就可以省去重复定义注解的过程.
定义一个RequestMappingDefinition
public interface RequestMappingDefinition<T> {
@GetMapping("/{id}")
default T get(@PathVariable("id") Long id) {
return null;
}
@GetMapping
default Page<T> page(@QuerydslPredicate Predicate predicate, Pageable pageable) {
return null;
}
@PostMapping
default T create(@RequestBody T entity) {
return null;
}
@PutMapping("{id}")
default T update(@PathVariable("id") Long id, @RequestBody T entity) {
return null;
}
@DeleteMapping("{id}")
default void delete(@PathVariable("id") Long id) {}
}
UserController使用实现该接口并添加泛型
@RestController
@RequestMapping("user")
public class UserController implements RequestMappingDefinition<User> {
// ...
}
其它Controller可以使用同样的方式
@RestController
@RequestMapping("role")
public class RoleController implements RequestMappingDefinition<Role>{
// ...
}
这样就可以在RoleController内编写接口的逻辑, 但不需要重复编写注解, 其它Controller也是同理.
但是这会带来一个问题, 直接实现接口会引入RequestMappingDefinition定义的所有接口, 即RoleController中你没有重写实现的接口方法也会被注解为Handler. 但是很有可能对于某些Controller我们不需要RequestMappingDefinition中的部分接口.
可以用下面的方法解决.
定义一个DefaultController
public class DefaultController<T> {
public T get(Long id) {
throw new UnsupportedOperationException();
}
public Page<T> page(Predicate predicate, Pageable pageable) {
throw new UnsupportedOperationException();
}
public T create(T entity) {
throw new UnsupportedOperationException();
}
public T update(Long id, T entity) {
throw new UnsupportedOperationException();
}
public void delete(Long id) {
throw new UnsupportedOperationException();
}
}
让RoleController继承他.
@RestController
@RequestMapping("role")
public class RoleController extends DefaultController<Role>
implements RequestMappingDefinition<Role> {
// ...
}
此时, 没有在RoleController中重写的方法就不会再被注册为Handler.

浙公网安备 33010602011771号