I'm implementing a webapplication which uses a Router to validate the incoming request and map it to an action in a controller.
The routes are defined in a file like this:
"/users/all","UserController.all"
"/users/user_id","UserController.get"
"/posts/add","PostController.add"
"/posts/post_id","PostContoller.get"
The Routes class is as follows:
public class Routes {
HashMap<String,String> routes;
public Routes() {
this.routes = new HashMap<String,String>();
readRoutes();
}
public HttpResponse route(HttpRequest request) {
String mapper[] = routes.get(request.getUri()).split(".");
try {
return (HttpResponse) Class.forName(mapper[0]).getMethod(mapper[1],HttpRequest.class).invoke(null, request);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
private void readRoutes() {
// Reads the routes file and loads the routes hash map
}
}
I currently have two controllers, User and Post as follows:
public class UserController {
public static Collection<String> all(HttpRequest request) {
return DB.Users.all();
}
public static String get(HttpRequest request) {
// Extract id from request
return DB.Users.get(id);
}
}
public class PostController {
public static void add(HttpRequest request) {
// Get the data from the request and do the processing
return DB.Posts.add(data);
}
public static String get(HttpRequest request) {
// Extract id from request
return DB.Posts.get(id);
}
}
The above example is just to give an idea of what I'm trying to achieve. The obvious checks on any exceptions have been ignored.
My question is: The routes class converts the value(String) in the routes hash map to a Method in the Controller and invokes it. Is this an effecient way? I read that invoking a Method in this manner is a bad way of coding and should be avoided, but I'm not sure how else to implement this. Routes does this mapping every time a request is matched, would this slow down the application?
Any suggestions or examples on how to do this in an effecient way would be very helpful.
I know there are a bunch of MVC frameworks which I can use, but I'd really like to clarify the above.
Pre-compute or cache this information as it is known before hand:
Class.forName(mapper[0]).getMethod(mapper[1], HttpRequest.class)
So
this.routes = new HashMap<String, Method>()
leads to
routes.get(request.getUri()).invoke(null, request)
It would make you implementation faster.
Other than that it is a sound approach.