在我的Spring MVC webapp中,我有一个用于CRUD操作的通用RESTful控制器。并且每个具体控制器必须仅声明@RequestMapping
,例如/foo
。通用控制器处理了对/foo
和/foo/{id}
的所有请求。
但现在我需要编写一个更复杂的CRUD控制器,它将获得额外的请求参数或路径变量,例如/foo/{date}
和/foo/{id}/{date}
。所以我扩展了我的通用CRUD控制器并编写了重载的fetch(id, date)
方法,该方法将处理{id}
和{date}
。这不是问题。
但我还需要“禁用”从基类派生的fetch(id)
实现(资源不能再在/foo/{id}
处可用,只能在/foo/{id}/{date}
)。我想出的唯一想法是在我的具体控制器中覆盖此方法,将其映射到假uri并返回null
。但这看起来像是丑陋的脏黑客,因为我们暴露了一些假的资源uri,而不是禁用它。可能有更好的做法吗?
有什么想法吗?
//My generic CRUD controller
public abstract class AbstractCRUDControllerBean<E, PK extends Serializable> implements AbstractCRUDController<E, PK> {
@RequestMapping(method=RequestMethod.GET)
public @ResponseBody ResponseEntity<E[]> fetchAll() { ... }
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public @ResponseBody ResponseEntity<E> fetch(@PathVariable("id") PK id) { ... }
@RequestMapping(method=RequestMethod.POST)
public @ResponseBody ResponseEntity<E> add(@RequestBody E entity) { ... }
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public @ResponseBody ResponseEntity<E> update(@PathVariable("id") PK id, @RequestBody E entity) { ... }
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public @ResponseBody ResponseEntity<E> remove(@PathVariable("id") PK id) { .. }
}
//Concrete controller, working with Foo entities
@Controller
@RequestMapping("/foo")
public class FooControllerImpl extends
AbstractCRUDControllerBean<Foo, Long> implements FooController {
//ugly overriding parent's method
@RequestMapping(value="/null",method=RequestMethod.GET)
public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id) {
return null;
}
//new fetch implementation
@RequestMapping(value="/{id}/{date}", method=RequestMethod.GET)
public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id, @PathVariable("date") Date date) { .... }
}
答案 0 :(得分:18)
您是否尝试使用弹簧来实现资源,子资源类型的球衣?这可能不是直接可能的。而不是将通用RESTful服务声明为控制器,为什么不将它委托给它们?
//My generic CRUD Operations
public abstract class AbstractCRUDControllerBean<E, PK extends Serializable> implements AbstractCRUDController<E, PK> {
public ResponseEntity<E[]> fetchAll() { ... }
public ResponseEntity<E> fetch(@PathVariable("id") PK id) { ... }
public ResponseEntity<E> add(@RequestBody E entity) { ... }
public ResponseEntity<E> update(@PathVariable("id") PK id, @RequestBody E entity) { ... }
public ResponseEntity<E> remove(@PathVariable("id") PK id) { .. }
}
并在控制器中委派。
//Concrete controller, working with Foo entities
@Controller
@RequestMapping("/foo")
public class FooControllerImpl extends
AbstractCRUDControllerBean<Foo, Long> implements FooController {
//we are interested in using fetchall but not others
@RequestMapping(method=RequestMethod.GET)
public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id) {
return fetchAll();
}
//fetch with id and date
@RequestMapping(value="/{id}/{date}", method=RequestMethod.GET)
public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id, @PathVariable("date") Date date) { .... }
}
另外,您也可以根据参数的可用性来映射方法,
@RequestMapping(value="/{id}/{date}", params={"param1","param2","!param3"})
public @ResponseBody ResponseEntity<E> customFetch(@PathVariable("id") PK id,
@PathVariable("date") Date date, @RequestParam("param1") String param1,
@RequestParam("param2") String param2) {...}
当param1和param2存在且param3不存在时,此方法映射/ foo / id / date。