2011-09-12 20 views
15

En mi aplicación web Spring MVC tengo un controlador RESTful genérico para operaciones CRUD. Y cada controlador concreto tenía que declarar solo un @RequestMapping, por ejemplo /foo. El controlador genérico manejó todas las solicitudes a /foo y /foo/{id}.Herencia y enrutamiento del controlador MVC de resorte

Pero ahora tengo que escribir un controlador CRUD un poco más complejo que obtendrá parámetros de solicitud adicionales o variables de ruta, por ejemplo, /foo/{date} y /foo/{id}/{date}. Así que extiendo mi controlador genérico CRUD y escribo sobrecargado el método fetch(id, date) que tratará tanto con {id} como con {date}. Eso no es problema.

Pero también necesito 'desactivar' la implementación fetch(id) derivada de la clase base (el recurso no debe estar disponible en /foo/{id}, solo en /foo/{id}/{date}). La única idea que se me ocurrió es anular este método en mi controlador concreto, mapearlo en un uri falso y devolver null. Pero esto parece un hack sucio bastante feo porque exponemos algunos recursos uri falsos, en lugar de deshabilitarlos. ¿Puede haber una mejor práctica?

¿Alguna idea?

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

} 

Respuesta

18

¿Está tratando de lograr el recurso, tipo de subresource de jersey utilizando la primavera? Eso puede no ser directamente posible. En lugar de declarar el servicio genérico RESTful como controlador, ¿por qué no se lo delega?

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

y delegar en el controlador.

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

} 

también, puede asignar el método basado en la disponibilidad de los parámetros también,

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

Este método de mapas/foo/id/fecha en que existe param1 y param2 y no existe param3.

+0

Gracias por esta idea. Se adapta muy bien a mis necesidades. A veces, cuando estás atascado, todo lo que necesitas es cambiar un punto de vista) – Nofate

+0

+1 buena respuesta y bien explicada – andyb

Cuestiones relacionadas