public <T> T[] toArray(T[] a) { // Estimate size of array; be prepared to see more or fewer elements intsize= size(); T[] r = a.length >= size ? a : (T[])java.lang.reflect.Array .newInstance(a.getClass().getComponentType(), size); Iterator<E> it = iterator();
for (inti=0; i < r.length; i++) { if (! it.hasNext()) { // fewer elements than expected if (a == r) { r[i] = null; // null-terminate } elseif (a.length < i) { return Arrays.copyOf(r, i); } else { System.arraycopy(r, 0, a, 0, i); if (a.length > i) { a[i] = null; } } return a; } r[i] = (T)it.next(); } // more elements than expected return it.hasNext() ? finishToArray(r, it) : r; }
Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.
@GetMapping @ResponseBody public List<User> fetch() { returnthis.userService.findAll(); }
@GetMapping("{id}") @ResponseBody public User get(@PathVariable("id") Long id) { // 由于是示例这里就不考虑没有数据的情况了 returnthis.userService.findById(id).get(); }
@PostMapping @ResponseBody public User create(@RequestBody User user) { returnthis.userService.save(user); }
@PutMapping("{id}") @ResponseBody public User update(@RequestBody User user) { returnthis.userService.save(user); }
@DeleteMapping("{id}") @ResponseBody public User delete(@PathVariable("id") Long id) { Useruser=this.userService.findById(id); this.userService.deleteById(id); return user; } }
为了不让这项枯燥而又容易犯错的工作占去我们宝贵的私人时间,我们可以通过泛型和继承的技巧来重构从 Service 层到 Controller 的这段代码(感谢 spring-data 提供了 JpaRepository, 让我们不至于从 DAO 层重构)
3.1 Service 层的重构
首先是 Service 接口的重构,我们 Service 层接口就是定义了一组 CRUD 的操作,我们可以将这组 CRUD 操作抽象到一个父接口,然后所有 Service 层的接口都将继承自这个父接口。而接口中出现的 Entity 和主键的类型(上例中 User 的主键 id 的类型是 Long)就可以用泛型来展现。
1 2 3 4 5 6 7 8 9 10 11
// 这里泛型表示 E 来指代 Entity, ID 用来指代 Entity 主键的类型 publicinterfaceICrudService<E, ID> { List<E> findAll(); Optional<E> findById(ID id); E save(E e); voiddeleteById(ID id); }
// 然后 Service 层的接口,就可以简化成这样 publicinterfaceUserServiceextendsICrudService<User, Long> { }
// Controller 层的基类 publicabstractclassAbstractCrudController<T extendsICrudService<E, ID>, E, ID> { private T service; publicAbstractCrudController(T service) { this.service = service; }
@GetMapping @ResponseBody public List<E> fetch() { returnthis.service.findAll(); }
@GetMapping("{id}") @ResponseBody public E get(@PathVariable("id") ID id) { // 由于是示例这里就不考虑没有数据的情况了 returnthis.service.findById(id).get(); }
@PostMapping @ResponseBody public E create(@RequestBody E e) { returnthis.service.save(e); }
@PutMapping("{id}") @ResponseBody public E update(@RequestBody E e) { returnthis.service.save(e); }
@DeleteMapping("{id}") @ResponseBody public E delete(@PathVariable("id") ID id) { Ee=this.service.findById(id).get(); this.service.deleteById(id); return e; } }