Spring MVC控制器继承和路由

Nof*_*ate 15 java spring spring-mvc spring-annotations

在我的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) { .. }
} 
Run Code Online (Sandbox Code Playgroud)

.

//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) { .... }

}
Run Code Online (Sandbox Code Playgroud)

kal*_*yan 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) { .. }
} 
Run Code Online (Sandbox Code Playgroud)

并在控制器中委派.

//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) { .... }

}
Run Code Online (Sandbox Code Playgroud)

另外,你也可以根据参数的可用性来映射方法,

@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) {...}
Run Code Online (Sandbox Code Playgroud)

当param1和param2存在且param3不存在时,此方法映射/ foo/id/date.