In meiner Spring MVC-Webanwendung habe ich einen generischen RESTful-Controller für CRUD-Operationen. Und jeder konkrete Controller musste nur ein @RequestMapping
deklarieren, zum Beispiel /foo
. Der generische Controller hat alle Anfragen an /foo
und /foo/{id}
behandelt.
Jetzt muss ich jedoch einen etwas komplexeren CRUD-Controller schreiben, der zusätzliche Anfragemöglichkeiten oder Pfadvariablen erhält, z.B. /foo/{date}
und /foo/{id}/{date}
. Daher erweitere ich meinen generischen CRUD-Controller und schreibe eine überladene fetch(id, date)
-Methode, die sowohl mit {id}
als auch mit {date}
umgehen wird. Das ist kein Problem.
Aber ich muss auch die fetch(id)
-Implementierung der Basisklasse deaktivieren (die Ressource sollte nicht mehr unter /foo/{id}
verfügbar sein, nur noch unter /foo/{id}/{date}
). Die einzige Idee, die mir dazu einfällt, ist diese Methode im konkreten Controller zu überschreiben, sie auf eine falsche URI zu mappen und null
zurückzugeben. Aber das scheint eher wie ein hässlicher, schmutziger Hack, da wir eine falsche Ressourcen-URI freilegen, anstatt sie zu deaktivieren. Gibt es vielleicht eine bessere Praxis?
Irgendwelche Ideen?
//Mein generischer CRUD-Controller
public abstract class AbstractCRUDControllerBean implements AbstractCRUDController {
@RequestMapping(method=RequestMethod.GET)
public @ResponseBody ResponseEntity fetchAll() { ... }
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public @ResponseBody ResponseEntity fetch(@PathVariable("id") PK id) { ... }
@RequestMapping(method=RequestMethod.POST)
public @ResponseBody ResponseEntity add(@RequestBody E entity) { ... }
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public @ResponseBody ResponseEntity update(@PathVariable("id") PK id, @RequestBody E entity) { ... }
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public @ResponseBody ResponseEntity remove(@PathVariable("id") PK id) { .. }
}
.
//Konkreter Controller, der mit Foo-Entitäten arbeitet
@Controller
@RequestMapping("/foo")
public class FooControllerImpl extends
AbstractCRUDControllerBean implements FooController {
//Hässliches Überschreiben der Methode aus der Elternklasse
@RequestMapping(value="/null",method=RequestMethod.GET)
public @ResponseBody ResponseEntity fetch(@PathVariable("id") PK id) {
return null;
}
//Neue Fetch-Implementierung
@RequestMapping(value="/{id}/{date}", method=RequestMethod.GET)
public @ResponseBody ResponseEntity fetch(@PathVariable("id") PK id, @PathVariable("date") Date date) { .... }
}