java Spring MVC 控制器继承和路由

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7387592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:45:12  来源:igfitidea点击:

Spring MVC controller inheritance and routing

javaspringspring-mvcspring-annotations

提问by Nofate

In my Spring MVC webapp I have a generic RESTful controller for CRUD operations. And each concrete controller had to declare only a @RequestMapping, for example /foo. Generic controller handled all request to /fooand /foo/{id}.

在我的 Spring MVC webapp 中,我有一个用于 CRUD 操作的通用 RESTful 控制器。而且每个具体的控制器只有一个声明@RequestMapping,例如/foo。通用控制器处理所有对/foo和 的请求/foo/{id}

But now I need to write a bit more complex CRUD controller which will get additional request params or path variables, e.g /foo/{date}and /foo/{id}/{date}. So I extend my generic CRUD controller and write overloaded fetch(id, date)method which will deal with both {id}and {date}. That is not a problem.

但现在我需要编写一个更复杂的 CRUD 控制器,它将获得额外的请求参数或路径变量,例如/foo/{date}/foo/{id}/{date}。所以我扩展了我的通用 CRUD 控制器并编写了重载fetch(id, date)方法来处理{id}{date}. 那不是问题。

But I also need to 'disable' fetch(id)implementation derived from base class (resource mustn't be available at /foo/{id}anymore, only at /foo/{id}/{date}). The only idea I came up with is to override this method in my concrete controller, to map it on a fake uri and return null. But this looks like rather ugly dirty hack because we expose some fake resource uri, instead of disabling it. May be there is a better practice?

但我还需要“禁用”fetch(id)从基类派生的 实现(资源不能再在/foo/{id},只能在/foo/{id}/{date})。我想出的唯一想法是在我的具体控制器中覆盖这个方法,将它映射到一个假的 uri 并返回null。但这看起来很丑陋,因为我们暴露了一些虚假的资源 uri,而不是禁用它。可能有更好的做法吗?

Any ideas?

有任何想法吗?

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

}

回答by kalyan

Are you trying to achieve the resource, subresource type of jersey using spring? That may not be directly possible. Instead of declaring the generic RESTful service as controller, why don't you delegate it to them?

您是否正在尝试使用 spring 来实现球衣的资源、子资源类型?这可能不是直接可能的。与其将通用 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) { .. }
} 

and delegate in the controller.

并在控制器中委托。

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

}

also, you can map method based on the availability of the parameters too,

此外,您也可以根据参数的可用性映射方法,

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

This method maps /foo/id/date when param1 and param2 exists and param3 does not exist.

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