I remember working on a project made in Django where you could create routes that could be given a prefix and then include another URL file for the rest of the endpoint.
api_patterns= [
url('foo/', include(foo.urls)),
url('bar/', include(bar.urls)),
]
urlpatterns = [
url(r'api/', include(api_patterns)),
]
This implementation would result in endpoints /api/foo/
and /api/bar/
and these endpoints would live in separate directories with separate url files.
The question is whether we can implement something equivalent to Spring Boot.
I know you can add the prefix to the @RequestMapping
on all the files.
But in my current project, we have a lot of controllers that start from the same route prefix and then, later on, differ from each other.
// Foo controller
@Controller
@RequestMapping(path = "api/foo")
public class FooController {
@GetMapping(path = "")
// Endpoint to /api/foo
}
// Bar controller
@Controller
@RequestMapping(path = "api/bar")
public class BarController {
@GetMapping(path = "")
// Endpoint to /api/bar
}
// Tar controller by foo
@Controller
@RequestMapping(path = "api/foo/tar")
public class TarController {
@GetMapping(path = "")
// Endpoint to /api/foo/tar
}
The endpoint would then look like this /api/foo
, /api/bar
, and /api/foo/tar
.
How can I prevent the repeated path prefix on all the files?
This routing might be a bad practice for working with API endpoint, I also think that this could be prevented, and that is why I'm asking as a junior developer to try to improve and show responsibility at my first job.
CodePudding user response:
You probably need to smash the controllers with the same endpoint beginning.
I'd suggest you to remain this annotation @RequestMapping(path = "/api/foo")
and just insert inside that class the methods with @GetMapping(path = "/tar")
. And other methods could have prefix tar: "/tar/example"
.
But if there are lots of methods starting with this prefix /api/foo/tar
and the class FooController
begins to be big enough, it's nice to keep them separately.
CodePudding user response:
You can have an interface like below:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(path = "/api")
public interface BaseController {
}
Then every individual controller class can implement the interface like below:
public class FooController implements BaseController {
@GetMapping(path = "/foo")
// Endpoint to /api/foo
}
Provided it is possible to change every controller class.
CodePudding user response:
I think the best practice would be something like
/**
* Class for String constants to use in the application
*/
public final class WebConstants {
public static final String API = "api";
...other constants
}
@Controller
@RequestMapping(path = WebConstants.API "/foo")
public class FooController {
@GetMapping
// serve something for /api/foo
@GetMapping(path = "/tar")
// serve something for /api/foo/tar
}
// Bar controller
@Controller
@RequestMapping(path = WebConstants.API "/bar")
public class BarController {
@GetMapping
// Serve something for /api/bar
}