这应该优化吗?

时间:2015-04-10 07:44:47

标签: java java-ee

这是一个将在Tomcat 7.0上运行的servlet。该应用程序非常繁忙。

我们所做的是以下内容:

public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //get the path {/api/login}
    String requestPath = request.getRequestURI().substring(request.getRequestURI().indexOf(getServletConfig().getServletContext().getContextPath()) + getServletConfig().getServletContext().getContextPath().length());
    //get the responder class {mobi.foo.base.api.login}
    Class<? extends Responder> responderClass = Class.forName("mobi.foo.base"+requestPath.replaceAll("/", ".")).asSubclass(Responder.class);
    //initialize a responder using reflection
    Responder responder = responderClass.newInstance();

    //print the response
    PrintWriter out = response.getWriter();
    out.write(responder.respond());
    out.close();
}

所以在第一次,我倾向于接受这个,因为它不计入瓶颈。换句话说,即使它相对较慢,它的便利性也超过了它引入的相当微不足道的开销:我们正在讨论可能访问数据库的http请求!

我是对的吗?我只是想了解其他人&#39;对此有所了解。

2 个答案:

答案 0 :(得分:2)

问:问题应该优化吗?

答:使用分析器来衡量在关注代码中花费的时间百分比。如果时间百分比很大,那么优化它。否则不要。

当然,我们无法对您进行明确的量化&#34;重要的&#34;。它实际上取决于实际成本。例如,如果你有一个webapp实例并且大部分时间都是轻载,那么性能提升1%很可能是不值得的。另一方面,如果你有成千上万的这个程序副本在数千台服务器上运行,那么性能提升1%可能是值得的......只是减少你的电费。


可以优化吗?

我认为你不太可能加速。用class.forName查找工厂对象替换newInstance()HashMap等,每次调用 1 可能会节省一些微秒的时间。那个可能相当于一个显着的加速......但我对此表示怀疑。

但我认为@JBNizet正在提出重要观点。这里存在潜在的安全问题。解决该问题将是对此代码进行大修的合理原因。


1 - 加载类的成本会随着请求类型的重复而摊销。当您为之前加载的类调用class.forName时,类加载器只需查找并返回现有的Class对象。

答案 1 :(得分:0)

如果你的respond()方法只使用方法变量(不是类字段),你可以创建响应者并将其放在响应者池中并重复使用它,而不是每次都创建它。

基本上是这样的:

//get the path {/api/login}
String requestPath = request.getRequestURI().substring(request.getRequestURI().indexOf(getServletConfig().getServletContext().getContextPath()) + getServletConfig().getServletContext().getContextPath().length());
//get the responder class {mobi.foo.base.api.login}

String responderName = "mobi.foo.base"+requestPath.replaceAll("/", ".");

Responder responder = responderMap.get(responderName);
if (responder == null) {
    Class<? extends Responder> responderClass = Class.forName("mobi.foo.base"+requestPath.replaceAll("/", ".")).asSubclass(Responder.class);
    //initialize a responder using reflection
    Responder responder = responderClass.newInstance();
    responderMap.put(responderName, responder);
}


//print the response
PrintWriter out = response.getWriter();
out.write(responder.respond());
out.close();

其中responderMap是保存在ServletContext中的Map<String, Responder>类型的映射,或者作为单例提供。